blob: d8a420586a1e093cde63d5346f581912872f9279 [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;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011913 if (bssid) {
11914 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011915 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011916 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011917 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011918 /*
11919 * Save BSSID in seperate variable as
11920 * pRoamProfile's BSSID is getting zeroed out in the
11921 * association process. In case of join failure
11922 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011923 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011924 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011925 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011926 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011927 } else if (bssid_hint) {
11928 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011929 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011930 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011931 /*
11932 * Save BSSID in a separate variable as
11933 * pRoamProfile's BSSID is getting zeroed out in the
11934 * association process. In case of join failure
11935 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011936 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011937 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011938 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011939 hdd_info("bssid_hint is given by upper layer %pM",
11940 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011942 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011943 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011944 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011945 }
11946
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011947 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011948 pRoamProfile->SSIDs.SSIDList->SSID.length,
11949 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11950 operatingChannel);
11951
11952 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11953 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011954 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11956 }
11957#ifdef FEATURE_WLAN_WAPI
11958 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011959 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011960 switch (pAdapter->wapi_info.wapiAuthMode) {
11961 case WAPI_AUTH_MODE_PSK:
11962 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011963 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011964 pAdapter->wapi_info.wapiAuthMode);
11965 pRoamProfile->AuthType.authType[0] =
11966 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11967 break;
11968 }
11969 case WAPI_AUTH_MODE_CERT:
11970 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011971 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011972 pAdapter->wapi_info.wapiAuthMode);
11973 pRoamProfile->AuthType.authType[0] =
11974 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11975 break;
11976 }
11977 } /* End of switch */
11978 if (pAdapter->wapi_info.wapiAuthMode ==
11979 WAPI_AUTH_MODE_PSK
11980 || pAdapter->wapi_info.wapiAuthMode ==
11981 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011982 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011983 pRoamProfile->AuthType.numEntries = 1;
11984 pRoamProfile->EncryptionType.numEntries = 1;
11985 pRoamProfile->EncryptionType.encryptionType[0] =
11986 eCSR_ENCRYPT_TYPE_WPI;
11987 pRoamProfile->mcEncryptionType.numEntries = 1;
11988 pRoamProfile->mcEncryptionType.
11989 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11990 }
11991 }
Krunal Soni31949422016-07-29 17:17:53 -070011992#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993#ifdef WLAN_FEATURE_GTK_OFFLOAD
11994 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011995 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11996 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11998 sizeof(tSirGtkOffloadParams));
11999 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12000 GTK_OFFLOAD_DISABLE;
12001 }
12002#endif
12003 pRoamProfile->csrPersona = pAdapter->device_mode;
12004
12005 if (operatingChannel) {
12006 pRoamProfile->ChannelInfo.ChannelList =
12007 &operatingChannel;
12008 pRoamProfile->ChannelInfo.numOfChannels = 1;
12009 } else {
12010 pRoamProfile->ChannelInfo.ChannelList = NULL;
12011 pRoamProfile->ChannelInfo.numOfChannels = 0;
12012 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012013 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012014 && operatingChannel) {
12015 /*
12016 * Need to post the IBSS power save parameters
12017 * to WMA. WMA will configure this parameters
12018 * to firmware if power save is enabled by the
12019 * firmware.
12020 */
12021 status = hdd_set_ibss_power_save_params(pAdapter);
12022
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012023 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012024 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012025 return -EINVAL;
12026 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012027 pRoamProfile->ch_params.ch_width =
12028 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053012029 /*
12030 * In IBSS mode while operating in 2.4 GHz,
12031 * the device supports only 20 MHz.
12032 */
12033 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
12034 pRoamProfile->ch_params.ch_width =
12035 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012036 hdd_select_cbmode(pAdapter, operatingChannel,
12037 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012038 }
Abhishek Singh99bce862016-06-20 15:10:51 +053012039 /*
12040 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12041 * or pmf=2 is an explicit configuration in the supplicant
12042 * configuration, drop the connection request.
12043 */
12044 if (pWextState->roamProfile.MFPEnabled &&
12045 !(pWextState->roamProfile.MFPRequired ||
12046 pWextState->roamProfile.MFPCapable)) {
12047 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12048 pWextState->roamProfile.MFPEnabled,
12049 pWextState->roamProfile.MFPRequired,
12050 pWextState->roamProfile.MFPCapable);
12051 return -EINVAL;
12052 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012053
Krunal Soni3091bcc2016-06-23 12:28:21 -070012054 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012055 hdd_err("Connection refused: conn in progress");
12056 return -EINVAL;
12057 }
12058
Krunal Soni31949422016-07-29 17:17:53 -070012059 /*
12060 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070012062 * enhancements, the supplicant is not issuing the scan command
12063 * now. So the unicast frames which are sent from the host are
12064 * not having the additional IEs. If it is P2P CLIENT and there
12065 * is no additional IE present in roamProfile, then use the
12066 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012067 */
12068
Krunal Sonib4326f22016-03-10 13:05:51 -080012069 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012070 (!pRoamProfile->pAddIEScan)) {
12071 pRoamProfile->pAddIEScan =
12072 &pAdapter->scan_info.scanAddIE.addIEdata[0];
12073 pRoamProfile->nAddIEScanLength =
12074 pAdapter->scan_info.scanAddIE.length;
12075 }
12076 /*
12077 * When policy manager is enabled from ini file, we shouldn't
12078 * check for other concurrency rules.
12079 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070012080 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080012081 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012082 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012083 pAdapter, pRoamProfile, &roamId))
12084 return 0;
12085 }
12086
Krunal Soni3091bcc2016-06-23 12:28:21 -070012087 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012088 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
12089 pRoamProfile))) {
12090 hdd_err("sap-sta conc will fail, can't allow sta");
12091 hdd_conn_set_connection_state(pAdapter,
12092 eConnectionState_NotConnected);
12093 return -ENOMEM;
12094 }
12095
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012096 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012097 if (!sme_config) {
12098 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012099 hdd_conn_set_connection_state(pAdapter,
12100 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012101 return -ENOMEM;
12102 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012103 sme_get_config_param(pHddCtx->hHal, sme_config);
12104 /* These values are not sessionized. So, any change in these SME
12105 * configs on an older or parallel interface will affect the
12106 * cb mode. So, restoring the default INI params before starting
12107 * interfaces such as sta, cli etc.,
12108 */
12109 sme_config->csrConfig.channelBondingMode5GHz =
12110 pHddCtx->config->nChannelBondingMode5GHz;
12111 sme_config->csrConfig.channelBondingMode24GHz =
12112 pHddCtx->config->nChannelBondingMode24GHz;
12113 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012114 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053012115 /*
12116 * Change conn_state to connecting before sme_roam_connect(),
12117 * because sme_roam_connect() has a direct path to call
12118 * hdd_sme_roam_callback(), which will change the conn_state
12119 * If direct path, conn_state will be accordingly changed to
12120 * NotConnected or Associated by either
12121 * hdd_association_completion_handler() or
12122 * hdd_dis_connect_handler() in sme_RoamCallback()if
12123 * sme_RomConnect is to be queued,
12124 * Connecting state will remain until it is completed.
12125 *
12126 * If connection state is not changed, connection state will
12127 * remain in eConnectionState_NotConnected state.
12128 * In hdd_association_completion_handler, "hddDisconInProgress"
12129 * is set to true if conn state is
12130 * eConnectionState_NotConnected.
12131 * If "hddDisconInProgress" is set to true then cfg80211 layer
12132 * is not informed of connect result indication which
12133 * is an issue.
12134 */
12135 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053012136 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053012137 hdd_conn_set_connection_state(pAdapter,
12138 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012139
Komal Seelama89be8d2016-09-29 11:09:26 +053012140 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
12141 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080012142 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143 pAdapter->sessionId, pRoamProfile,
12144 &roamId);
12145
Rajeev Kumard31e1542017-01-13 14:37:42 -080012146 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080012147 (QDF_STA_MODE == pAdapter->device_mode ||
12148 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012149 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080012150 "qdf_status %d. -> NotConnected",
12151 pAdapter->sessionId, qdf_status);
12152 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012153 /* change back to NotAssociated */
12154 hdd_conn_set_connection_state(pAdapter,
12155 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053012156 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
12157 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012158 }
12159
12160 pRoamProfile->ChannelInfo.ChannelList = NULL;
12161 pRoamProfile->ChannelInfo.numOfChannels = 0;
12162
Nitesh Shah044fd672016-10-13 18:53:25 +053012163 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080012164 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053012165 cds_get_channel_from_scan_result(pAdapter,
12166 pRoamProfile, &channel);
12167 if (channel)
12168 cds_checkn_update_hw_mode_single_mac_mode
12169 (channel);
12170 }
12171
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012172 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012173 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 return -EINVAL;
12175 }
12176 EXIT();
12177 return status;
12178}
12179
12180/**
12181 * wlan_hdd_cfg80211_set_auth_type() - set auth type
12182 * @pAdapter: Pointer to adapter
12183 * @auth_type: Auth type
12184 *
12185 * This function is used to set the authentication type (OPEN/SHARED).
12186 *
12187 * Return: 0 for success, non-zero for failure
12188 */
12189static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
12190 enum nl80211_auth_type auth_type)
12191{
12192 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12193 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012195 /*set authentication type */
12196 switch (auth_type) {
12197 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012198 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012199 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
12200 break;
12201
12202 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012203 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012204 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012205 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12206 break;
12207
12208 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012209 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012210 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
12211 break;
12212#ifdef FEATURE_WLAN_ESE
12213 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012214 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012215 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
12216 break;
12217#endif
12218
12219 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012220 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012221 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
12222 return -EINVAL;
12223 }
12224
12225 pWextState->roamProfile.AuthType.authType[0] =
12226 pHddStaCtx->conn_info.authType;
12227 return 0;
12228}
12229
12230/**
12231 * wlan_hdd_set_akm_suite() - set key management type
12232 * @pAdapter: Pointer to adapter
12233 * @key_mgmt: Key management type
12234 *
12235 * This function is used to set the key mgmt type(PSK/8021x).
12236 *
12237 * Return: 0 for success, non-zero for failure
12238 */
12239static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
12240{
12241 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012243#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
12244#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
12245 /*set key mgmt type */
12246 switch (key_mgmt) {
12247 case WLAN_AKM_SUITE_PSK:
12248 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012250 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012251 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
12252 break;
12253
12254 case WLAN_AKM_SUITE_8021X_SHA256:
12255 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012256 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012257 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012258 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12259 break;
12260#ifdef FEATURE_WLAN_ESE
12261#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
12262#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
12263 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012264 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012265 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
12266 break;
12267#endif
12268#ifndef WLAN_AKM_SUITE_OSEN
12269#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
12270#endif
12271 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012272 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012273 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12274 break;
12275
12276 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012277 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 return -EINVAL;
12279
12280 }
12281 return 0;
12282}
12283
12284/**
12285 * wlan_hdd_cfg80211_set_cipher() - set encryption type
12286 * @pAdapter: Pointer to adapter
12287 * @cipher: Cipher type
12288 * @ucast: Unicast flag
12289 *
12290 * This function is used to set the encryption type
12291 * (NONE/WEP40/WEP104/TKIP/CCMP).
12292 *
12293 * Return: 0 for success, non-zero for failure
12294 */
12295static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
12296 u32 cipher, bool ucast)
12297{
12298 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12299 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12300 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012302 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012303 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012304 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12305 } else {
12306
12307 /*set encryption method */
12308 switch (cipher) {
12309 case IW_AUTH_CIPHER_NONE:
12310 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12311 break;
12312
12313 case WLAN_CIPHER_SUITE_WEP40:
12314 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
12315 break;
12316
12317 case WLAN_CIPHER_SUITE_WEP104:
12318 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
12319 break;
12320
12321 case WLAN_CIPHER_SUITE_TKIP:
12322 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
12323 break;
12324
12325 case WLAN_CIPHER_SUITE_CCMP:
12326 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12327 break;
12328#ifdef FEATURE_WLAN_WAPI
12329 case WLAN_CIPHER_SUITE_SMS4:
12330 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
12331 break;
12332#endif
12333
12334#ifdef FEATURE_WLAN_ESE
12335 case WLAN_CIPHER_SUITE_KRK:
12336 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
12337 break;
12338#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12339 case WLAN_CIPHER_SUITE_BTK:
12340 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
12341 break;
12342#endif
12343#endif
12344 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012345 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012346 return -EOPNOTSUPP;
12347 }
12348 }
12349
12350 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012351 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012352 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12353 pWextState->roamProfile.EncryptionType.numEntries = 1;
12354 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12355 encryptionType;
12356 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012357 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012358 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
12359 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
12360 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
12361 encryptionType;
12362 }
12363
12364 return 0;
12365}
12366
12367/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012368 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
12369 * @wext_state: Pointer to wext state
12370 * @gen_ie: Pointer to IE data
12371 * @len: length of IE data
12372 *
12373 * Return: 0 for success, non-zero for failure
12374 */
12375static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
12376 const uint8_t *gen_ie, uint16_t len)
12377{
12378 uint16_t cur_add_ie_len =
12379 wext_state->assocAddIE.length;
12380
12381 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12382 (wext_state->assocAddIE.length + len)) {
12383 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12384 QDF_ASSERT(0);
12385 return -ENOMEM;
12386 }
12387 memcpy(wext_state->assocAddIE.addIEdata +
12388 cur_add_ie_len, gen_ie, len);
12389 wext_state->assocAddIE.length += len;
12390
12391 wext_state->roamProfile.pAddIEAssoc =
12392 wext_state->assocAddIE.addIEdata;
12393 wext_state->roamProfile.nAddIEAssocLength =
12394 wext_state->assocAddIE.length;
12395 return 0;
12396}
12397
12398/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012399 * wlan_hdd_cfg80211_set_ie() - set IEs
12400 * @pAdapter: Pointer to adapter
12401 * @ie: Pointer ot ie
12402 * @ie: IE length
12403 *
12404 * Return: 0 for success, non-zero for failure
12405 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012406static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407 size_t ie_len)
12408{
12409 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12410 const uint8_t *genie = ie;
12411 uint16_t remLen = ie_len;
12412#ifdef FEATURE_WLAN_WAPI
12413 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12414 u16 *tmp;
12415 uint16_t akmsuiteCount;
12416 int *akmlist;
12417#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012418 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012419
12420 /* clear previous assocAddIE */
12421 pWextState->assocAddIE.length = 0;
12422 pWextState->roamProfile.bWPSAssociation = false;
12423 pWextState->roamProfile.bOSENAssociation = false;
12424
12425 while (remLen >= 2) {
12426 uint16_t eLen = 0;
12427 uint8_t elementId;
12428 elementId = *genie++;
12429 eLen = *genie++;
12430 remLen -= 2;
12431
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012432 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012433
12434 switch (elementId) {
12435 case DOT11F_EID_WPA:
12436 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 -070012437 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438 return -EINVAL;
12439 } else if (0 ==
12440 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12441 uint16_t curAddIELen =
12442 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012443 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444
12445 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12446 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012447 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012448 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012449 return -ENOMEM;
12450 }
12451 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12452 memcpy(pWextState->assocAddIE.addIEdata +
12453 curAddIELen, genie - 2, eLen + 2);
12454 pWextState->assocAddIE.length += eLen + 2;
12455
12456 pWextState->roamProfile.bWPSAssociation = true;
12457 pWextState->roamProfile.pAddIEAssoc =
12458 pWextState->assocAddIE.addIEdata;
12459 pWextState->roamProfile.nAddIEAssocLength =
12460 pWextState->assocAddIE.length;
12461 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012462 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 memset(pWextState->WPARSNIE, 0,
12464 MAX_WPA_RSN_IE_LEN);
12465 memcpy(pWextState->WPARSNIE, genie - 2,
12466 (eLen + 2));
12467 pWextState->roamProfile.pWPAReqIE =
12468 pWextState->WPARSNIE;
12469 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12470 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12471 P2P_OUI_TYPE_SIZE))) {
12472 uint16_t curAddIELen =
12473 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012474 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475
12476 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12477 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012478 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012479 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 return -ENOMEM;
12481 }
12482 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12483 memcpy(pWextState->assocAddIE.addIEdata +
12484 curAddIELen, genie - 2, eLen + 2);
12485 pWextState->assocAddIE.length += eLen + 2;
12486
12487 pWextState->roamProfile.pAddIEAssoc =
12488 pWextState->assocAddIE.addIEdata;
12489 pWextState->roamProfile.nAddIEAssocLength =
12490 pWextState->assocAddIE.length;
12491 }
12492#ifdef WLAN_FEATURE_WFD
12493 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12494 WFD_OUI_TYPE_SIZE)) &&
12495 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012496 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012497 pAdapter->device_mode)) {
12498 uint16_t curAddIELen =
12499 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012500 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012501
12502 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12503 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012504 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012505 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506 return -ENOMEM;
12507 }
12508 /* WFD IE is saved to Additional IE ; it should
12509 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012510 * WFD IE
12511 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012512 memcpy(pWextState->assocAddIE.addIEdata +
12513 curAddIELen, genie - 2, eLen + 2);
12514 pWextState->assocAddIE.length += eLen + 2;
12515
12516 pWextState->roamProfile.pAddIEAssoc =
12517 pWextState->assocAddIE.addIEdata;
12518 pWextState->roamProfile.nAddIEAssocLength =
12519 pWextState->assocAddIE.length;
12520 }
12521#endif
12522 /* Appending HS 2.0 Indication Element in Assiciation Request */
12523 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12524 HS20_OUI_TYPE_SIZE))) {
12525 uint16_t curAddIELen =
12526 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012527 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528
12529 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12530 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012531 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012532 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533 return -ENOMEM;
12534 }
12535 memcpy(pWextState->assocAddIE.addIEdata +
12536 curAddIELen, genie - 2, eLen + 2);
12537 pWextState->assocAddIE.length += eLen + 2;
12538
12539 pWextState->roamProfile.pAddIEAssoc =
12540 pWextState->assocAddIE.addIEdata;
12541 pWextState->roamProfile.nAddIEAssocLength =
12542 pWextState->assocAddIE.length;
12543 }
12544 /* Appending OSEN Information Element in Assiciation Request */
12545 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12546 OSEN_OUI_TYPE_SIZE))) {
12547 uint16_t curAddIELen =
12548 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012549 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550
12551 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12552 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012553 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012554 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 return -ENOMEM;
12556 }
12557 memcpy(pWextState->assocAddIE.addIEdata +
12558 curAddIELen, genie - 2, eLen + 2);
12559 pWextState->assocAddIE.length += eLen + 2;
12560
12561 pWextState->roamProfile.bOSENAssociation = true;
12562 pWextState->roamProfile.pAddIEAssoc =
12563 pWextState->assocAddIE.addIEdata;
12564 pWextState->roamProfile.nAddIEAssocLength =
12565 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012566 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12567 MBO_OUI_TYPE_SIZE))){
12568 hdd_info("Set MBO IE(len %d)", eLen + 2);
12569 status = wlan_hdd_add_assoc_ie(pWextState,
12570 genie - 2, eLen + 2);
12571 if (status)
12572 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012573 } else {
12574 uint16_t add_ie_len =
12575 pWextState->assocAddIE.length;
12576
12577 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12578
12579 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12580 (pWextState->assocAddIE.length + eLen)) {
12581 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012582 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583 return -ENOMEM;
12584 }
12585
12586 memcpy(pWextState->assocAddIE.addIEdata +
12587 add_ie_len, genie - 2, eLen + 2);
12588 pWextState->assocAddIE.length += eLen + 2;
12589
12590 pWextState->roamProfile.pAddIEAssoc =
12591 pWextState->assocAddIE.addIEdata;
12592 pWextState->roamProfile.nAddIEAssocLength =
12593 pWextState->assocAddIE.length;
12594 }
12595 break;
12596 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012597 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12599 memcpy(pWextState->WPARSNIE, genie - 2,
12600 (eLen + 2));
12601 pWextState->roamProfile.pRSNReqIE =
12602 pWextState->WPARSNIE;
12603 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12604 break;
12605 /*
12606 * Appending Extended Capabilities with Interworking bit set
12607 * in Assoc Req.
12608 *
12609 * In assoc req this EXT Cap will only be taken into account if
12610 * interworkingService bit is set to 1. Currently
12611 * driver is only interested in interworkingService capability
12612 * from supplicant. If in future any other EXT Cap info is
12613 * required from supplicat, it needs to be handled while
12614 * sending Assoc Req in LIM.
12615 */
12616 case DOT11F_EID_EXTCAP:
12617 {
12618 uint16_t curAddIELen =
12619 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012620 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012621
12622 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12623 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012624 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012625 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012626 return -ENOMEM;
12627 }
12628 memcpy(pWextState->assocAddIE.addIEdata +
12629 curAddIELen, genie - 2, eLen + 2);
12630 pWextState->assocAddIE.length += eLen + 2;
12631
12632 pWextState->roamProfile.pAddIEAssoc =
12633 pWextState->assocAddIE.addIEdata;
12634 pWextState->roamProfile.nAddIEAssocLength =
12635 pWextState->assocAddIE.length;
12636 break;
12637 }
12638#ifdef FEATURE_WLAN_WAPI
12639 case WLAN_EID_WAPI:
12640 /* Setting WAPI Mode to ON=1 */
12641 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012642 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012643 tmp = (u16 *) ie;
12644 tmp = tmp + 2; /* Skip element Id and Len, Version */
12645 akmsuiteCount = WPA_GET_LE16(tmp);
12646 tmp = tmp + 1;
12647 akmlist = (int *)(tmp);
12648 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12649 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12650 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012651 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012652 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012653 return -EINVAL;
12654 }
12655
12656 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012657 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012658 pAdapter->wapi_info.wapiAuthMode =
12659 WAPI_AUTH_MODE_PSK;
12660 }
12661 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012662 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012663 pAdapter->wapi_info.wapiAuthMode =
12664 WAPI_AUTH_MODE_CERT;
12665 }
12666 break;
12667#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012668 case DOT11F_EID_SUPPOPERATINGCLASSES:
12669 {
12670 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12671 status = wlan_hdd_add_assoc_ie(pWextState,
12672 genie - 2, eLen + 2);
12673 if (status)
12674 return status;
12675 break;
12676 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012677 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012678 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012679 /* when Unknown IE is received we break
12680 * and continue to the next IE in the buffer
12681 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 break;
12683 }
12684 genie += eLen;
12685 remLen -= eLen;
12686 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012687 return 0;
12688}
12689
12690/**
12691 * hdd_is_wpaie_present() - check for WPA ie
12692 * @ie: Pointer to ie
12693 * @ie_len: Ie length
12694 *
12695 * Parse the received IE to find the WPA IE
12696 *
12697 * Return: true if wpa ie is found else false
12698 */
12699static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12700{
12701 uint8_t eLen = 0;
12702 uint16_t remLen = ie_len;
12703 uint8_t elementId = 0;
12704
12705 while (remLen >= 2) {
12706 elementId = *ie++;
12707 eLen = *ie++;
12708 remLen -= 2;
12709 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012710 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711 return false;
12712 }
12713 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12714 /* OUI - 0x00 0X50 0XF2
12715 * WPA Information Element - 0x01
12716 * WPA version - 0x01
12717 */
12718 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12719 return true;
12720 }
12721 ie += eLen;
12722 remLen -= eLen;
12723 }
12724 return false;
12725}
12726
12727/**
12728 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12729 * @pAdapter: Pointer to adapter
12730 * @req: Pointer to security parameters
12731 *
12732 * Return: 0 for success, non-zero for failure
12733 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012734static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12735 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012736{
12737 int status = 0;
12738 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12739 ENTER();
12740
12741 /*set wpa version */
12742 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12743
12744 if (req->crypto.wpa_versions) {
12745 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12746 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12747 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12748 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12749 }
12750 }
12751
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012752 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012753
12754 /*set authentication type */
12755 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12756
12757 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012758 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759 return status;
12760 }
12761
12762 /*set key mgmt type */
12763 if (req->crypto.n_akm_suites) {
12764 status =
12765 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12766 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012767 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012768 return status;
12769 }
12770 }
12771
12772 /*set pairwise cipher type */
12773 if (req->crypto.n_ciphers_pairwise) {
12774 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12775 req->crypto.
12776 ciphers_pairwise[0],
12777 true);
12778 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012779 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012780 return status;
12781 }
12782 } else {
12783 /*Reset previous cipher suite to none */
12784 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12785 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012786 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012787 return status;
12788 }
12789 }
12790
12791 /*set group cipher type */
12792 status =
12793 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12794 false);
12795
12796 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012797 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012798 return status;
12799 }
12800#ifdef WLAN_FEATURE_11W
12801 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12802#endif
12803
12804 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12805 if (req->ie_len) {
12806 status =
12807 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12808 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012809 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012810 return status;
12811 }
12812 }
12813
12814 /*incase of WEP set default key information */
12815 if (req->key && req->key_len) {
12816 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12817 || (WLAN_CIPHER_SUITE_WEP104 ==
12818 req->crypto.ciphers_pairwise[0])
12819 ) {
12820 if (IW_AUTH_KEY_MGMT_802_1X
12821 ==
12822 (pWextState->
12823 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012824 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012825 return -EOPNOTSUPP;
12826 } else {
12827 u8 key_len = req->key_len;
12828 u8 key_idx = req->key_idx;
12829
12830 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12831 key_len)
12832 && (CSR_MAX_NUM_KEY > key_idx)
12833 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012834 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012835 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012836 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012837 Keys.
12838 KeyMaterial[key_idx][0],
12839 req->key, key_len);
12840 pWextState->roamProfile.Keys.
12841 KeyLength[key_idx] = (u8) key_len;
12842 pWextState->roamProfile.Keys.
12843 defaultIndex = (u8) key_idx;
12844 }
12845 }
12846 }
12847 }
12848
12849 return status;
12850}
12851
12852/**
12853 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12854 * @pAdapter: Pointer to adapter
12855 *
12856 * This function is used to disconnect from previous connection
12857 *
12858 * Return: 0 for success, non-zero for failure
12859 */
12860static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12861{
12862 unsigned long rc;
12863 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012864 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012865
12866 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12867
Jeff Johnson9edf9572016-10-03 15:24:49 -070012868 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012869 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12870 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12871 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012872 hdd_conn_set_connection_state(pAdapter,
12873 eConnectionState_Disconnecting);
12874 /* Issue disconnect to CSR */
12875 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012876
12877 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12878 pAdapter->sessionId,
12879 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12880 /*
12881 * Wait here instead of returning directly, this will block the
12882 * next connect command and allow processing of the scan for
12883 * ssid and the previous connect command in CSR. Else we might
12884 * hit some race conditions leading to SME and HDD out of sync.
12885 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012886 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012887 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12888 } else if (0 != status) {
12889 hdd_err("csrRoamDisconnect failure, returned %d",
12890 (int)status);
12891 pHddStaCtx->staDebugState = status;
12892 result = -EINVAL;
12893 goto disconnected;
12894 }
12895
12896 rc = wait_for_completion_timeout(
12897 &pAdapter->disconnect_comp_var,
12898 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012899 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012900 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12901 pAdapter->sessionId, pHddStaCtx->staDebugState);
12902 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 }
12904 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012905 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012906 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012907 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012909 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012910 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012911 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012912 }
12913 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012914disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012915 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12916 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917}
12918
12919/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012920 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12921 * @adapter: Pointer to the HDD adapter
12922 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012923 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012924 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012925 * This function will start reassociation if prev_bssid is set and bssid/
12926 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012927 *
Naveen Rawat07332902016-07-27 09:13:17 -070012928 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012929 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012930#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12931 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012932static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12933 struct cfg80211_connect_params *req,
12934 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012935{
Naveen Rawat07332902016-07-27 09:13:17 -070012936 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012937 const uint8_t *bssid = NULL;
12938 uint16_t channel = 0;
12939
12940 if (req->bssid)
12941 bssid = req->bssid;
12942 else if (req->bssid_hint)
12943 bssid = req->bssid_hint;
12944
12945 if (req->channel)
12946 channel = req->channel->hw_value;
12947 else if (req->channel_hint)
12948 channel = req->channel_hint->hw_value;
12949
12950 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012951 reassoc = true;
12952 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012953 channel, MAC_ADDR_ARRAY(bssid));
12954 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012955 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012956 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012957 }
Naveen Rawat07332902016-07-27 09:13:17 -070012958 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012959}
12960#else
Naveen Rawat07332902016-07-27 09:13:17 -070012961static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12962 struct cfg80211_connect_params *req,
12963 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012964{
Naveen Rawat07332902016-07-27 09:13:17 -070012965 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012966}
12967#endif
12968
12969/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12971 * @wiphy: Pointer to wiphy
12972 * @dev: Pointer to network device
12973 * @req: Pointer to cfg80211 connect request
12974 *
12975 * This function is used to start the association process
12976 *
12977 * Return: 0 for success, non-zero for failure
12978 */
12979static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12980 struct net_device *ndev,
12981 struct cfg80211_connect_params *req)
12982{
12983 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012984 u16 channel;
12985#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12986 const u8 *bssid_hint = req->bssid_hint;
12987#else
12988 const u8 *bssid_hint = NULL;
12989#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012990 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12991 hdd_context_t *pHddCtx;
12992
12993 ENTER();
12994
Anurag Chouhan6d760662016-02-20 16:05:43 +053012995 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012996 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997 return -EINVAL;
12998 }
12999
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013000 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13001 hdd_err("invalid session id: %d", pAdapter->sessionId);
13002 return -EINVAL;
13003 }
13004
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013005 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013006 TRACE_CODE_HDD_CFG80211_CONNECT,
13007 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013008 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013009 hdd_device_mode_to_string(pAdapter->device_mode),
13010 pAdapter->device_mode);
13011
Krunal Sonib4326f22016-03-10 13:05:51 -080013012 if (pAdapter->device_mode != QDF_STA_MODE &&
13013 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013014 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015 hdd_device_mode_to_string(pAdapter->device_mode),
13016 pAdapter->device_mode);
13017 return -EINVAL;
13018 }
13019
13020 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13021 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013022 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023 return -EINVAL;
13024 }
13025
13026 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013027 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013029
Naveen Rawat07332902016-07-27 09:13:17 -070013030 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013031 return status;
13032
Agrawal Ashishf156e942016-08-04 14:54:47 +053013033 /* Try disconnecting if already in connected state */
13034 status = wlan_hdd_try_disconnect(pAdapter);
13035 if (0 > status) {
13036 hdd_err("Failed to disconnect the existing connection");
13037 return -EALREADY;
13038 }
13039
13040 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013041 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013042 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013043 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013044 pAdapter->device_mode),
13045 req->channel->hw_value, HW_MODE_20_MHZ)) {
13046 hdd_err("This concurrency combination is not allowed");
13047 return -ECONNREFUSED;
13048 }
13049 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013050 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013051 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
13053 hdd_err("This concurrency combination is not allowed");
13054 return -ECONNREFUSED;
13055 }
13056 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013057
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013058 /*initialise security parameters */
13059 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
13060
13061 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013062 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 return status;
13064 }
13065
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013066 if (req->channel)
13067 channel = req->channel->hw_value;
13068 else
13069 channel = 0;
13070 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
13071 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013072 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013074 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 return status;
13076 }
13077 EXIT();
13078 return status;
13079}
13080
13081/**
13082 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
13083 * @wiphy: Pointer to wiphy
13084 * @dev: Pointer to network device
13085 * @req: Pointer to cfg80211 connect request
13086 *
13087 * Return: 0 for success, non-zero for failure
13088 */
13089static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13090 struct net_device *ndev,
13091 struct cfg80211_connect_params *req)
13092{
13093 int ret;
13094 cds_ssr_protect(__func__);
13095 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
13096 cds_ssr_unprotect(__func__);
13097
13098 return ret;
13099}
13100
13101/**
13102 * wlan_hdd_disconnect() - hdd disconnect api
13103 * @pAdapter: Pointer to adapter
13104 * @reason: Disconnect reason code
13105 *
13106 * This function is used to issue a disconnect request to SME
13107 *
13108 * Return: 0 for success, non-zero for failure
13109 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013110static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013111{
13112 int status, result = 0;
13113 unsigned long rc;
13114 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13115 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13116
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013117 ENTER();
13118
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013119 status = wlan_hdd_validate_context(pHddCtx);
13120
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013121 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123
13124 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013125 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
13127 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013128 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013129 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
13130 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13131
13132 /*issue disconnect */
13133
13134 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13135 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053013136 /*
13137 * Wait here instead of returning directly, this will block the next
13138 * connect command and allow processing of the scan for ssid and
13139 * the previous connect command in CSR. Else we might hit some
13140 * race conditions leading to SME and HDD out of sync.
13141 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013142 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013143 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013145 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013146 (int)status);
13147 pHddStaCtx->staDebugState = status;
13148 result = -EINVAL;
13149 goto disconnected;
13150 }
13151 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13152 msecs_to_jiffies
13153 (WLAN_WAIT_TIME_DISCONNECT));
13154
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013155 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013156 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157 result = -ETIMEDOUT;
13158 }
13159disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013160 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13161#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
13162 /* Sending disconnect event to userspace for kernel version < 3.11
13163 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
13164 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013165 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053013166 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
13167 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013168#endif
13169
13170 return result;
13171}
13172
13173/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013174 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
13175 * @reason: ieee80211 reason code.
13176 *
13177 * This utility function helps log string conversion of reason code.
13178 *
13179 * Return: string conversion of reason code, if match found;
13180 * "Unknown" otherwise.
13181 */
13182static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
13183{
13184 switch (reason) {
13185 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
13186 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
13187 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
13188 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
13189 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
13190 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13191 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
13192 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
13193 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
13194 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
13195 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
13196 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
13197 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
13198 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
13199 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
13200 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
13201 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
13202 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
13203 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
13204 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
13205 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
13206 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
13207 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
13208 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
13209 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
13210 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
13211 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
13212 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
13213 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
13214 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
13215 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
13216 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
13217 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
13218 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
13219 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
13220 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
13221 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
13222 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
13223 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
13224 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
13225 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
13226 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
13227 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
13228 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
13229 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
13230 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
13231 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
13232 default:
13233 return "Unknown";
13234 }
13235}
13236
13237/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13239 * @wiphy: Pointer to wiphy
13240 * @dev: Pointer to network device
13241 * @reason: Disconnect reason code
13242 *
13243 * This function is used to issue a disconnect request to SME
13244 *
13245 * Return: 0 for success, non-zero for failure
13246 */
13247static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13248 struct net_device *dev, u16 reason)
13249{
13250 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13251 int status;
13252 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13253 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13254#ifdef FEATURE_WLAN_TDLS
13255 uint8_t staIdx;
13256#endif
13257
13258 ENTER();
13259
Anurag Chouhan6d760662016-02-20 16:05:43 +053013260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013261 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013262 return -EINVAL;
13263 }
13264
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013265 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13266 hdd_err("invalid session id: %d", pAdapter->sessionId);
13267 return -EINVAL;
13268 }
13269
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013270 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 TRACE_CODE_HDD_CFG80211_DISCONNECT,
13272 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013273 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 hdd_device_mode_to_string(pAdapter->device_mode),
13275 pAdapter->device_mode, reason);
13276
13277 status = wlan_hdd_validate_context(pHddCtx);
13278
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080013279 if (hdd_is_roaming_in_progress()) {
13280 hdd_err("Roaming In Progress. Ignore!!!");
13281 return -EAGAIN;
13282 }
13283
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013284 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013285 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286
13287 /* Issue disconnect request to SME, if station is in connected state */
13288 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
13289 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
13290 eCsrRoamDisconnectReason reasonCode =
13291 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13292 hdd_scaninfo_t *pScanInfo;
13293
13294 switch (reason) {
13295 case WLAN_REASON_MIC_FAILURE:
13296 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
13297 break;
13298
13299 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
13300 case WLAN_REASON_DISASSOC_AP_BUSY:
13301 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
13302 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
13303 break;
13304
13305 case WLAN_REASON_PREV_AUTH_NOT_VALID:
13306 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
13307 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
13308 break;
13309
13310 case WLAN_REASON_DEAUTH_LEAVING:
13311 reasonCode =
13312 pHddCtx->config->
13313 gEnableDeauthToDisassocMap ?
13314 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
13315 eCSR_DISCONNECT_REASON_DEAUTH;
13316 break;
13317 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
13318 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
13319 break;
13320 default:
13321 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
13322 break;
13323 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013324 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013325 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326 pScanInfo = &pAdapter->scan_info;
13327 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013328 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013329 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053013330 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013331 eCSR_SCAN_ABORT_DEFAULT);
13332 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053013333 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013334#ifdef FEATURE_WLAN_TDLS
13335 /* First clean up the tdls peers if any */
13336 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
13337 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
13338 pAdapter->sessionId)
13339 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
13340 uint8_t *mac;
13341 mac =
13342 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013343 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
13344 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 pHddCtx->tdlsConnInfo[staIdx].staId,
13346 pAdapter->sessionId,
13347 MAC_ADDR_ARRAY(mac));
13348 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
13349 (pAdapter),
13350 pAdapter->sessionId, mac);
13351 }
13352 }
13353#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013354 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013355 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013356 hdd_info("Disconnect request from user space with reason: %s",
13357 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 status = wlan_hdd_disconnect(pAdapter, reasonCode);
13359 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013360 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013361 return -EINVAL;
13362 }
13363 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013364 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 pHddStaCtx->conn_info.connState);
13366 }
13367
13368 return status;
13369}
13370
13371/**
13372 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13373 * @wiphy: Pointer to wiphy
13374 * @dev: Pointer to network device
13375 * @reason: Disconnect reason code
13376 *
13377 * Return: 0 for success, non-zero for failure
13378 */
13379static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13380 struct net_device *dev, u16 reason)
13381{
13382 int ret;
13383 cds_ssr_protect(__func__);
13384 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13385 cds_ssr_unprotect(__func__);
13386
13387 return ret;
13388}
13389
13390/**
13391 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13392 * @pAdapter: Pointer to adapter
13393 * @param: Pointer to IBSS parameters
13394 *
13395 * This function is used to initialize the security settings in IBSS mode
13396 *
13397 * Return: 0 for success, non-zero for failure
13398 */
13399static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13400 struct cfg80211_ibss_params
13401 *params)
13402{
13403 int status = 0;
13404 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13405 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13406 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13407
13408 ENTER();
13409
13410 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013411 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 pHddStaCtx->ibss_enc_key_installed = 0;
13413
13414 if (params->ie_len && (NULL != params->ie)) {
13415 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13416 params->ie_len, WLAN_EID_RSN)) {
13417 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13418 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13419 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13420 tDot11fIEWPA dot11WPAIE;
13421 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13422 u8 *ie;
13423
13424 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13425 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13426 params->ie_len,
13427 DOT11F_EID_WPA);
13428 if (NULL != ie) {
13429 pWextState->wpaVersion =
13430 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013431 /* Unpack the WPA IE
13432 * Skip past the EID byte and length byte
13433 * and four byte WiFi OUI
13434 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013435 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13436 &ie[2 + 4],
13437 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013438 /* Extract the multicast cipher, the
13439 * encType for unicast cipher for
13440 * wpa-none is none
13441 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013442 encryptionType =
13443 hdd_translate_wpa_to_csr_encryption_type
13444 (dot11WPAIE.multicast_cipher);
13445 }
13446 }
13447
13448 status =
13449 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13450 params->ie_len);
13451
13452 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013453 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013454 return status;
13455 }
13456 }
13457
13458 pWextState->roamProfile.AuthType.authType[0] =
13459 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13460
13461 if (params->privacy) {
13462 /* Security enabled IBSS, At this time there is no information
13463 * available about the security paramters, so initialise the
13464 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13465 * The correct security parameters will be updated later in
13466 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13467 * set inorder enable privacy bit in beacons
13468 */
13469
13470 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13471 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013472 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013473 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13474 pWextState->roamProfile.EncryptionType.numEntries = 1;
13475 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13476 encryptionType;
13477 return status;
13478}
13479
13480/**
13481 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13482 * @wiphy: Pointer to wiphy
13483 * @dev: Pointer to network device
13484 * @param: Pointer to IBSS join parameters
13485 *
13486 * This function is used to create/join an IBSS network
13487 *
13488 * Return: 0 for success, non-zero for failure
13489 */
13490static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13491 struct net_device *dev,
13492 struct cfg80211_ibss_params *params)
13493{
13494 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13495 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13496 tCsrRoamProfile *pRoamProfile;
13497 int status;
13498 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13499 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013500 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013501 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013502
13503 ENTER();
13504
Anurag Chouhan6d760662016-02-20 16:05:43 +053013505 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013506 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013507 return -EINVAL;
13508 }
13509
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013510 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13511 hdd_err("invalid session id: %d", pAdapter->sessionId);
13512 return -EINVAL;
13513 }
13514
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013515 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013516 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13517 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013518 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013519 hdd_device_mode_to_string(pAdapter->device_mode),
13520 pAdapter->device_mode);
13521
13522 status = wlan_hdd_validate_context(pHddCtx);
13523
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013524 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013525 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526
13527 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013528 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013529 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13530 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13531 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13532 int indx;
13533
13534 /* Get channel number */
13535 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013536 params->
13537 chandef.
13538 chan->
13539 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013540
13541 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13542 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013543 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013544 return -EOPNOTSUPP;
13545 }
13546
13547 for (indx = 0; indx < numChans; indx++) {
13548 if (channelNum == validChan[indx]) {
13549 break;
13550 }
13551 }
13552 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013553 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 return -EINVAL;
13555 }
13556 }
13557
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013558 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013559 HW_MODE_20_MHZ)) {
13560 hdd_err("This concurrency combination is not allowed");
13561 return -ECONNREFUSED;
13562 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013563
Krunal Soni3091bcc2016-06-23 12:28:21 -070013564 status = qdf_reset_connection_update();
13565 if (!QDF_IS_STATUS_SUCCESS(status))
13566 hdd_err("ERR: clear event failed");
13567
13568 status = cds_current_connections_update(pAdapter->sessionId,
13569 channelNum,
13570 SIR_UPDATE_REASON_JOIN_IBSS);
13571 if (QDF_STATUS_E_FAILURE == status) {
13572 hdd_err("ERROR: connections update failed!!");
13573 return -EINVAL;
13574 }
13575
13576 if (QDF_STATUS_SUCCESS == status) {
13577 status = qdf_wait_for_connection_update();
13578 if (!QDF_IS_STATUS_SUCCESS(status)) {
13579 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013580 return -EINVAL;
13581 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582 }
13583
13584 /*Try disconnecting if already in connected state */
13585 status = wlan_hdd_try_disconnect(pAdapter);
13586 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013587 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 return -EALREADY;
13589 }
13590
13591 pRoamProfile = &pWextState->roamProfile;
13592
13593 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013594 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013595 return -EINVAL;
13596 }
13597
13598 /* enable selected protection checks in IBSS mode */
13599 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13600
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013601 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013602 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13603 pHddCtx->config->
13604 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013605 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 }
13607
13608 /* BSSID is provided by upper layers hence no need to AUTO generate */
13609 if (NULL != params->bssid) {
13610 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013611 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013612 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013613 return -EIO;
13614 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013615 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013616 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13617 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013618 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013619 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013620 return -EIO;
13621 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013622 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 }
13624 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13625 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13626 pRoamProfile->beaconInterval = params->beacon_interval;
13627 else {
13628 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013629 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013630 params->beacon_interval, pRoamProfile->beaconInterval);
13631 }
13632
13633 /* Set Channel */
13634 if (channelNum) {
13635 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013636 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637 pRoamProfile->ChannelInfo.numOfChannels = 1;
13638 pHddStaCtx->conn_info.operationChannel = channelNum;
13639 pRoamProfile->ChannelInfo.ChannelList =
13640 &pHddStaCtx->conn_info.operationChannel;
13641 }
13642
13643 /* Initialize security parameters */
13644 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13645 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013646 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013647 return status;
13648 }
13649
13650 /* Issue connect start */
13651 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13652 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013653 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013655 operationChannel,
13656 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013657
13658 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013659 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 return status;
13661 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013662 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663 return 0;
13664}
13665
13666/**
13667 * wlan_hdd_cfg80211_join_ibss() - join ibss
13668 * @wiphy: Pointer to wiphy
13669 * @dev: Pointer to network device
13670 * @param: Pointer to IBSS join parameters
13671 *
13672 * This function is used to create/join an IBSS network
13673 *
13674 * Return: 0 for success, non-zero for failure
13675 */
13676static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13677 struct net_device *dev,
13678 struct cfg80211_ibss_params *params)
13679{
13680 int ret = 0;
13681
13682 cds_ssr_protect(__func__);
13683 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13684 cds_ssr_unprotect(__func__);
13685
13686 return ret;
13687}
13688
13689/**
13690 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13691 * @wiphy: Pointer to wiphy
13692 * @dev: Pointer to network device
13693 *
13694 * This function is used to leave an IBSS network
13695 *
13696 * Return: 0 for success, non-zero for failure
13697 */
13698static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13699 struct net_device *dev)
13700{
13701 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13702 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13703 tCsrRoamProfile *pRoamProfile;
13704 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13705 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013706 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013707 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013708 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013709
13710 ENTER();
13711
Anurag Chouhan6d760662016-02-20 16:05:43 +053013712 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013713 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013714 return -EINVAL;
13715 }
13716
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013717 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13718 hdd_err("invalid session id: %d", pAdapter->sessionId);
13719 return -EINVAL;
13720 }
13721
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013722 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13724 pAdapter->sessionId,
13725 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13726 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013727 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013728 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013730 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013731 hdd_device_mode_to_string(pAdapter->device_mode),
13732 pAdapter->device_mode);
13733 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013734 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013735 return -EIO;
13736 }
13737
13738 pRoamProfile = &pWextState->roamProfile;
13739
13740 /* Issue disconnect only if interface type is set to IBSS */
13741 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013742 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013743 return -EINVAL;
13744 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013745 /* Clearing add IE of beacon */
13746 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13747 sizeof(tSirMacAddr));
13748 updateIE.smeSessionId = pAdapter->sessionId;
13749 updateIE.ieBufferlength = 0;
13750 updateIE.pAdditionIEBuffer = NULL;
13751 updateIE.append = true;
13752 updateIE.notify = true;
13753 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13754 &updateIE,
13755 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013756 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013757 }
13758
13759 /* Reset WNI_CFG_PROBE_RSP Flags */
13760 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761
13762 /* Issue Disconnect request */
13763 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13764 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13765 pAdapter->sessionId,
13766 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013767 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013768 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 hal_status);
13770 return -EAGAIN;
13771 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013772
13773 /* wait for mc thread to cleanup and then return to upper stack
13774 * so by the time upper layer calls the change interface, we are
13775 * all set to proceed further
13776 */
13777 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13778 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13779 if (!rc) {
13780 hdd_err("Failed to disconnect, timed out");
13781 return -ETIMEDOUT;
13782 }
13783
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013784 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013785 return 0;
13786}
13787
13788/**
13789 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13790 * @wiphy: Pointer to wiphy
13791 * @dev: Pointer to network device
13792 *
13793 * This function is used to leave an IBSS network
13794 *
13795 * Return: 0 for success, non-zero for failure
13796 */
13797static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13798 struct net_device *dev)
13799{
13800 int ret = 0;
13801
13802 cds_ssr_protect(__func__);
13803 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13804 cds_ssr_unprotect(__func__);
13805
13806 return ret;
13807}
13808
13809/**
13810 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13811 * @wiphy: Pointer to wiphy
13812 * @changed: Parameters changed
13813 *
13814 * This function is used to set the phy parameters. RTS Threshold/FRAG
13815 * Threshold/Retry Count etc.
13816 *
13817 * Return: 0 for success, non-zero for failure
13818 */
13819static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13820 u32 changed)
13821{
13822 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13823 tHalHandle hHal = pHddCtx->hHal;
13824 int status;
13825
13826 ENTER();
13827
Anurag Chouhan6d760662016-02-20 16:05:43 +053013828 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013829 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 return -EINVAL;
13831 }
13832
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013833 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13835 NO_SESSION, wiphy->rts_threshold));
13836 status = wlan_hdd_validate_context(pHddCtx);
13837
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013838 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013839 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840
13841 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13842 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13843 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13844
13845 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13846 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013847 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013848 rts_threshold);
13849 return -EINVAL;
13850 }
13851
13852 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13853 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013854 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 rts_threshold);
13856 return -EIO;
13857 }
13858
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013859 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860 }
13861
13862 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13863 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13864 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13865 wiphy->frag_threshold;
13866
13867 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13868 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013869 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013870 frag_threshold);
13871 return -EINVAL;
13872 }
13873
13874 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13875 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013876 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013877 frag_threshold);
13878 return -EIO;
13879 }
13880
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013881 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013882 }
13883
13884 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13885 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13886 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13887 wiphy->retry_short : wiphy->retry_long;
13888
13889 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13890 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013891 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013892 return -EINVAL;
13893 }
13894
13895 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13896 if (0 != sme_cfg_set_int(hHal,
13897 WNI_CFG_LONG_RETRY_LIMIT,
13898 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013899 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013900 retry_value);
13901 return -EIO;
13902 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013903 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013904 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13905 if (0 != sme_cfg_set_int(hHal,
13906 WNI_CFG_SHORT_RETRY_LIMIT,
13907 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013908 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013909 retry_value);
13910 return -EIO;
13911 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013912 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013913 }
13914 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013915 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013916 return 0;
13917}
13918
13919/**
13920 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13921 * @wiphy: Pointer to wiphy
13922 * @changed: Parameters changed
13923 *
13924 * Return: 0 for success, non-zero for failure
13925 */
13926static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13927{
13928 int ret;
13929
13930 cds_ssr_protect(__func__);
13931 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13932 cds_ssr_unprotect(__func__);
13933
13934 return ret;
13935}
13936
13937/**
13938 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13939 * key
13940 * @wiphy: Pointer to wiphy
13941 * @dev: Pointer to network device
13942 * @key_index: Key index
13943 *
13944 * Return: 0
13945 */
13946static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13947 struct net_device *netdev,
13948 u8 key_index)
13949{
13950 ENTER();
13951 return 0;
13952}
13953
13954/**
13955 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13956 * wlan_hdd_set_default_mgmt_key
13957 * @wiphy: pointer to wiphy
13958 * @netdev: pointer to net_device structure
13959 * @key_index: key index
13960 *
13961 * Return: 0 on success, error number on failure
13962 */
13963static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13964 struct net_device *netdev,
13965 u8 key_index)
13966{
13967 int ret;
13968
13969 cds_ssr_protect(__func__);
13970 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13971 cds_ssr_unprotect(__func__);
13972
13973 return ret;
13974}
13975
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976/**
13977 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13978 * @wiphy: Pointer to wiphy
13979 * @dev: Pointer to network device
13980 * @params: Pointer to tx queue parameters
13981 *
13982 * Return: 0
13983 */
13984static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13985 struct net_device *dev,
13986 struct ieee80211_txq_params *params)
13987{
13988 ENTER();
13989 return 0;
13990}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013991
13992/**
13993 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13994 * @wiphy: pointer to wiphy
13995 * @netdev: pointer to net_device structure
13996 * @params: pointer to ieee80211_txq_params
13997 *
13998 * Return: 0 on success, error number on failure
13999 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014000static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14001 struct net_device *dev,
14002 struct ieee80211_txq_params *params)
14003{
14004 int ret;
14005
14006 cds_ssr_protect(__func__);
14007 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14008 cds_ssr_unprotect(__func__);
14009
14010 return ret;
14011}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012
14013/**
14014 * __wlan_hdd_cfg80211_del_station() - delete station v2
14015 * @wiphy: Pointer to wiphy
14016 * @param: Pointer to delete station parameter
14017 *
14018 * Return: 0 for success, non-zero for failure
14019 */
14020static
14021int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14022 struct net_device *dev,
14023 struct tagCsrDelStaParams *pDelStaParams)
14024{
14025 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14026 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014027 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 hdd_hostapd_state_t *hapd_state;
14029 int status;
14030 uint8_t staId;
14031 uint8_t *mac;
14032
14033 ENTER();
14034
Anurag Chouhan6d760662016-02-20 16:05:43 +053014035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014036 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014037 return -EINVAL;
14038 }
14039
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014040 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14041 hdd_err("invalid session id: %d", pAdapter->sessionId);
14042 return -EINVAL;
14043 }
14044
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014045 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 TRACE_CODE_HDD_CFG80211_DEL_STA,
14047 pAdapter->sessionId, pAdapter->device_mode));
14048
14049 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14050 status = wlan_hdd_validate_context(pHddCtx);
14051
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014052 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014053 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054
14055 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
14056
Krunal Sonib4326f22016-03-10 13:05:51 -080014057 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
14058 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014059
14060 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14061 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014062 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014063 return 0;
14064 }
14065
Anurag Chouhanc5548422016-02-24 18:33:27 +053014066 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014067 uint16_t i;
14068 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
14069 if ((pAdapter->aStaInfo[i].isUsed) &&
14070 (!pAdapter->aStaInfo[i].
14071 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014072 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 mac,
14074 pAdapter->aStaInfo[i].
14075 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014076 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14078 hdd_ipa_wlan_evt(pAdapter,
14079 pAdapter->
14080 aStaInfo[i].
14081 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014082 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014083 mac);
14084 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014085 hdd_notice("Delete STA with MAC::"
14086 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087 MAC_ADDR_ARRAY(mac));
14088
14089 if (pHddCtx->dev_dfs_cac_status ==
14090 DFS_CAC_IN_PROGRESS)
14091 goto fn_end;
14092
Wei Song2f76f642016-11-18 16:32:53 +080014093 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014094 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053014095 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014096 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014097 hdd_softap_sta_deauth(pAdapter,
14098 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014099 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014100 pAdapter->aStaInfo[i].
14101 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014102 qdf_status =
14103 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014104 &hapd_state->
14105 qdf_sta_disassoc_event,
14106 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014107 if (!QDF_IS_STATUS_SUCCESS(
14108 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014109 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014110 }
14111 }
14112 }
14113 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014114 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014115 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014116 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014117 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014118 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014119 hdd_notice("Skip DEL STA as this is not used::"
14120 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014121 MAC_ADDR_ARRAY(mac));
14122 return -ENOENT;
14123 }
14124
14125 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14126 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014127 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014128 }
14129
14130 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
14131 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014132 hdd_notice("Skip DEL STA as deauth is in progress::"
14133 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134 MAC_ADDR_ARRAY(mac));
14135 return -ENOENT;
14136 }
14137
14138 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
14139
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014140 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014141 MAC_ADDR_ARRAY(mac));
14142
14143 /* Case: SAP in ACS selected DFS ch and client connected
14144 * Now Radar detected. Then if random channel is another
14145 * DFS ch then new CAC is initiated and no TX allowed.
14146 * So do not send any mgmt frames as it will timeout
14147 * during CAC.
14148 */
14149
14150 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
14151 goto fn_end;
14152
Wei Song2f76f642016-11-18 16:32:53 +080014153 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053014154 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
14155 (pAdapter), pAdapter->sessionId,
14156 (uint8_t *)&pDelStaParams->peerMacAddr,
14157 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014158 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014160 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 pAdapter->aStaInfo[staId].isDeauthInProgress =
14162 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014163 hdd_notice("STA removal failed for ::"
14164 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165 MAC_ADDR_ARRAY(mac));
14166 return -ENOENT;
14167 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053014168 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014169 &hapd_state->
14170 qdf_sta_disassoc_event,
14171 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014172 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014173 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014174 }
14175 }
14176 }
14177
14178fn_end:
14179 EXIT();
14180 return 0;
14181}
14182
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014183#if defined(USE_CFG80211_DEL_STA_V2)
14184/**
14185 * wlan_hdd_del_station() - delete station wrapper
14186 * @adapter: pointer to the hdd adapter
14187 *
14188 * Return: None
14189 */
14190void wlan_hdd_del_station(hdd_adapter_t *adapter)
14191{
14192 struct station_del_parameters del_sta;
14193 del_sta.mac = NULL;
14194 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
14195 del_sta.reason_code = eCsrForcedDeauthSta;
14196
14197 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
14198 &del_sta);
14199}
14200#else
14201void wlan_hdd_del_station(hdd_adapter_t *adapter)
14202{
14203 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
14204}
14205#endif
14206
14207#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208/**
14209 * wlan_hdd_cfg80211_del_station() - delete station v2
14210 * @wiphy: Pointer to wiphy
14211 * @param: Pointer to delete station parameter
14212 *
14213 * Return: 0 for success, non-zero for failure
14214 */
14215int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14216 struct net_device *dev,
14217 struct station_del_parameters *param)
14218#else
14219/**
14220 * wlan_hdd_cfg80211_del_station() - delete station
14221 * @wiphy: Pointer to wiphy
14222 * @mac: Pointer to station mac address
14223 *
14224 * Return: 0 for success, non-zero for failure
14225 */
14226#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14227int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14228 struct net_device *dev,
14229 const uint8_t *mac)
14230#else
14231int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14232 struct net_device *dev,
14233 uint8_t *mac)
14234#endif
14235#endif
14236{
14237 int ret;
14238 struct tagCsrDelStaParams delStaParams;
14239
14240 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014241#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014242 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014243 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 return -EINVAL;
14245 }
14246 wlansap_populate_del_sta_params(param->mac, param->reason_code,
14247 param->subtype, &delStaParams);
14248#else
14249 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14250 (SIR_MAC_MGMT_DEAUTH >> 4),
14251 &delStaParams);
14252#endif
14253 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
14254 cds_ssr_unprotect(__func__);
14255
14256 return ret;
14257}
14258
14259/**
14260 * __wlan_hdd_cfg80211_add_station() - add station
14261 * @wiphy: Pointer to wiphy
14262 * @mac: Pointer to station mac address
14263 * @pmksa: Pointer to add station parameter
14264 *
14265 * Return: 0 for success, non-zero for failure
14266 */
14267static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14268 struct net_device *dev,
14269 const uint8_t *mac,
14270 struct station_parameters *params)
14271{
14272 int status = -EPERM;
14273#ifdef FEATURE_WLAN_TDLS
14274 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14275 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14276 u32 mask, set;
14277
14278 ENTER();
14279
Anurag Chouhan6d760662016-02-20 16:05:43 +053014280 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014281 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014282 return -EINVAL;
14283 }
14284
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014285 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14286 hdd_err("invalid session id: %d", pAdapter->sessionId);
14287 return -EINVAL;
14288 }
14289
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014290 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014291 TRACE_CODE_HDD_CFG80211_ADD_STA,
14292 pAdapter->sessionId, params->listen_interval));
14293
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014294 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014295 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296
14297 mask = params->sta_flags_mask;
14298
14299 set = params->sta_flags_set;
14300
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014301 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014302 MAC_ADDR_ARRAY(mac));
14303
14304 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14305 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14306 status =
14307 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
14308 }
14309 }
14310#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014311 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312 return status;
14313}
14314
14315/**
14316 * wlan_hdd_cfg80211_add_station() - add station
14317 * @wiphy: Pointer to wiphy
14318 * @mac: Pointer to station mac address
14319 * @pmksa: Pointer to add station parameter
14320 *
14321 * Return: 0 for success, non-zero for failure
14322 */
14323#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14324static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14325 struct net_device *dev,
14326 const uint8_t *mac,
14327 struct station_parameters *params)
14328#else
14329static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14330 struct net_device *dev, uint8_t *mac,
14331 struct station_parameters *params)
14332#endif
14333{
14334 int ret;
14335
14336 cds_ssr_protect(__func__);
14337 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
14338 cds_ssr_unprotect(__func__);
14339
14340 return ret;
14341}
14342
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343/**
14344 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
14345 * @wiphy: Pointer to wiphy
14346 * @dev: Pointer to network device
14347 * @pmksa: Pointer to set pmksa parameter
14348 *
14349 * Return: 0 for success, non-zero for failure
14350 */
14351static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14352 struct net_device *dev,
14353 struct cfg80211_pmksa *pmksa)
14354{
14355 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14356 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14357 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014358 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014359 int status;
14360 tPmkidCacheInfo pmk_id;
14361
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014362 ENTER();
14363
Anurag Chouhan6d760662016-02-20 16:05:43 +053014364 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014365 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014366 return -EINVAL;
14367 }
14368
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014369 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14370 hdd_err("invalid session id: %d", pAdapter->sessionId);
14371 return -EINVAL;
14372 }
14373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014374 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014375 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014376 return -EINVAL;
14377 }
14378
14379 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014380 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014381 pmksa->bssid, pmksa->pmkid);
14382 return -EINVAL;
14383 }
14384
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014385 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014386 MAC_ADDR_ARRAY(pmksa->bssid));
14387
14388 status = wlan_hdd_validate_context(pHddCtx);
14389
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014390 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014391 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392
14393 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14394
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014395 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14396 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014397
14398 /* Add to the PMKSA ID Cache in CSR */
14399 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14400 &pmk_id, 1, false);
14401
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014402 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014403 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14404 pAdapter->sessionId, result));
14405
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014406 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014407 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014408}
14409
14410/**
14411 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14412 * @wiphy: Pointer to wiphy
14413 * @dev: Pointer to network device
14414 * @pmksa: Pointer to set pmksa parameter
14415 *
14416 * Return: 0 for success, non-zero for failure
14417 */
14418static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14419 struct net_device *dev,
14420 struct cfg80211_pmksa *pmksa)
14421{
14422 int ret;
14423
14424 cds_ssr_protect(__func__);
14425 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14426 cds_ssr_unprotect(__func__);
14427
14428 return ret;
14429}
14430
14431/**
14432 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14433 * @wiphy: Pointer to wiphy
14434 * @dev: Pointer to network device
14435 * @pmksa: Pointer to pmksa parameter
14436 *
14437 * Return: 0 for success, non-zero for failure
14438 */
14439static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14440 struct net_device *dev,
14441 struct cfg80211_pmksa *pmksa)
14442{
14443 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14444 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14445 tHalHandle halHandle;
14446 int status = 0;
14447
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014448 ENTER();
14449
Anurag Chouhan6d760662016-02-20 16:05:43 +053014450 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014451 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 return -EINVAL;
14453 }
14454
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014455 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14456 hdd_err("invalid session id: %d", pAdapter->sessionId);
14457 return -EINVAL;
14458 }
14459
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014460 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014461 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 return -EINVAL;
14463 }
14464
14465 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014466 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467 return -EINVAL;
14468 }
14469
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014470 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471 MAC_ADDR_ARRAY(pmksa->bssid));
14472
14473 status = wlan_hdd_validate_context(pHddCtx);
14474
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014475 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014477
14478 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14479
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014480 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014481 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14482 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014483 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014484 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014485 sme_roam_del_pmkid_from_cache(halHandle,
14486 pAdapter->sessionId, pmksa->bssid,
14487 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014488 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014489 MAC_ADDR_ARRAY(pmksa->bssid));
14490 status = -EINVAL;
14491 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014492 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014493 return status;
14494}
14495
14496/**
14497 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14498 * @wiphy: Pointer to wiphy
14499 * @dev: Pointer to network device
14500 * @pmksa: Pointer to pmksa parameter
14501 *
14502 * Return: 0 for success, non-zero for failure
14503 */
14504static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14505 struct net_device *dev,
14506 struct cfg80211_pmksa *pmksa)
14507{
14508 int ret;
14509
14510 cds_ssr_protect(__func__);
14511 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14512 cds_ssr_unprotect(__func__);
14513
14514 return ret;
14515
14516}
14517
14518/**
14519 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14520 * @wiphy: Pointer to wiphy
14521 * @dev: Pointer to network device
14522 *
14523 * Return: 0 for success, non-zero for failure
14524 */
14525static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14526 struct net_device *dev)
14527{
14528 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14529 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14530 tHalHandle halHandle;
14531 int status = 0;
14532
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014533 ENTER();
14534
Anurag Chouhan6d760662016-02-20 16:05:43 +053014535 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014536 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014537 return -EINVAL;
14538 }
14539
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014540 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14541 hdd_err("invalid session id: %d", pAdapter->sessionId);
14542 return -EINVAL;
14543 }
14544
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014545 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014546
14547 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14548 status = wlan_hdd_validate_context(pHddCtx);
14549
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014550 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552
14553 /* Retrieve halHandle */
14554 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14555
14556 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014557 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14559 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014560 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 status = -EINVAL;
14562 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014563 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014564 return status;
14565}
14566
14567/**
14568 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14569 * @wiphy: Pointer to wiphy
14570 * @dev: Pointer to network device
14571 *
14572 * Return: 0 for success, non-zero for failure
14573 */
14574static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14575 struct net_device *dev)
14576{
14577 int ret;
14578
14579 cds_ssr_protect(__func__);
14580 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14581 cds_ssr_unprotect(__func__);
14582
14583 return ret;
14584}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014585
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014586#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014587/**
14588 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14589 * @wiphy: Pointer to wiphy
14590 * @dev: Pointer to network device
14591 * @ftie: Pointer to fast transition ie parameter
14592 *
14593 * Return: 0 for success, non-zero for failure
14594 */
14595static int
14596__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14597 struct net_device *dev,
14598 struct cfg80211_update_ft_ies_params *ftie)
14599{
14600 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14601 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14602 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14603 int status;
14604
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014605 ENTER();
14606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014607 status = wlan_hdd_validate_context(hdd_ctx);
14608 if (status)
14609 return status;
14610
Anurag Chouhan6d760662016-02-20 16:05:43 +053014611 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014612 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014613 return -EINVAL;
14614 }
14615
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014616 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14617 hdd_err("invalid session id: %d", pAdapter->sessionId);
14618 return -EINVAL;
14619 }
14620
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014621 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014622 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14623 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14624 /* Added for debug on reception of Re-assoc Req. */
14625 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014626 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014627 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014628 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014629 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014630 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014631 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632
14633 /* Pass the received FT IEs to SME */
14634 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14635 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014636 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014637 return 0;
14638}
14639
14640/**
14641 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14642 * @wiphy: Pointer to wiphy
14643 * @dev: Pointer to network device
14644 * @ftie: Pointer to fast transition ie parameter
14645 *
14646 * Return: 0 for success, non-zero for failure
14647 */
14648static int
14649wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14650 struct net_device *dev,
14651 struct cfg80211_update_ft_ies_params *ftie)
14652{
14653 int ret;
14654
14655 cds_ssr_protect(__func__);
14656 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14657 cds_ssr_unprotect(__func__);
14658
14659 return ret;
14660}
14661#endif
14662
14663#ifdef WLAN_FEATURE_GTK_OFFLOAD
14664/**
14665 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14666 * @callbackContext: Callback context
14667 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14668 *
14669 * Callback rountine called upon receiving response for get offload info
14670 *
14671 * Return: none
14672 */
14673void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14674 tpSirGtkOffloadGetInfoRspParams
14675 pGtkOffloadGetInfoRsp)
14676{
14677 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14678 uint8_t tempReplayCounter[8];
14679 hdd_station_ctx_t *pHddStaCtx;
14680
14681 ENTER();
14682
14683 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014684 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685 return;
14686 }
14687
14688 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014689 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690 return;
14691 }
14692
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014693 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014694 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014695 return;
14696 }
14697
14698 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14699 /* Update replay counter */
14700 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14701 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14702
14703 {
14704 /* changing from little to big endian since supplicant
14705 * works on big endian format
14706 */
14707 int i;
14708 uint8_t *p =
14709 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14710
14711 for (i = 0; i < 8; i++) {
14712 tempReplayCounter[7 - i] = (uint8_t) p[i];
14713 }
14714 }
14715
14716 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014717 cfg80211_gtk_rekey_notify(pAdapter->dev,
14718 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014719 tempReplayCounter, GFP_KERNEL);
14720}
14721
14722/**
14723 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14724 * @wiphy: Pointer to wiphy
14725 * @dev: Pointer to network device
14726 * @data: Pointer to rekey data
14727 *
14728 * This function is used to offload GTK rekeying job to the firmware.
14729 *
14730 * Return: 0 for success, non-zero for failure
14731 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014732static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14734 struct net_device *dev,
14735 struct cfg80211_gtk_rekey_data *data)
14736{
14737 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14738 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14739 hdd_station_ctx_t *pHddStaCtx;
14740 tHalHandle hHal;
14741 int result;
14742 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014743 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014744
14745 ENTER();
14746
Anurag Chouhan6d760662016-02-20 16:05:43 +053014747 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014748 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749 return -EINVAL;
14750 }
14751
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014752 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14753 hdd_err("invalid session id: %d", pAdapter->sessionId);
14754 return -EINVAL;
14755 }
14756
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014757 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014758 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14759 pAdapter->sessionId, pAdapter->device_mode));
14760
14761 result = wlan_hdd_validate_context(pHddCtx);
14762
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014763 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014764 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014765
14766 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14767 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14768 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014769 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014770 return -EAGAIN;
14771 }
14772
14773 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14774 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14775 NL80211_KCK_LEN);
14776 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14777 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014778 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014779 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014780 {
14781 /* changing from big to little endian since driver
14782 * works on little endian format
14783 */
14784 uint8_t *p =
14785 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14786 ullKeyReplayCounter;
14787 int i;
14788
14789 for (i = 0; i < 8; i++) {
14790 p[7 - i] = data->replay_ctr[i];
14791 }
14792 }
14793
14794 if (true == pHddCtx->hdd_wlan_suspended) {
14795 /* if wlan is suspended, enable GTK offload directly from here */
14796 memcpy(&hddGtkOffloadReqParams,
14797 &pHddStaCtx->gtkOffloadReqParams,
14798 sizeof(tSirGtkOffloadParams));
14799 status =
14800 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14801 pAdapter->sessionId);
14802
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014803 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014804 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014805 status);
14806 return -EINVAL;
14807 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014808 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014810 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014812 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 return result;
14814}
14815
14816/**
14817 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14818 * @wiphy: Pointer to wiphy
14819 * @dev: Pointer to network device
14820 * @data: Pointer to rekey data
14821 *
14822 * This function is used to offload GTK rekeying job to the firmware.
14823 *
14824 * Return: 0 for success, non-zero for failure
14825 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014826static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014827int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14828 struct net_device *dev,
14829 struct cfg80211_gtk_rekey_data *data)
14830{
14831 int ret;
14832
14833 cds_ssr_protect(__func__);
14834 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14835 cds_ssr_unprotect(__func__);
14836
14837 return ret;
14838}
14839#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14840
14841/**
14842 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14843 * @wiphy: Pointer to wiphy
14844 * @dev: Pointer to network device
14845 * @param: Pointer to access control parameter
14846 *
14847 * Return: 0 for success, non-zero for failure
14848 */
14849static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14850 struct net_device *dev,
14851 const struct cfg80211_acl_data *params)
14852{
14853 int i;
14854 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14855 hdd_hostapd_state_t *pHostapdState;
14856 tsap_Config_t *pConfig;
14857 v_CONTEXT_t p_cds_context = NULL;
14858 hdd_context_t *pHddCtx;
14859 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014860 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014861
14862 ENTER();
14863
Anurag Chouhan6d760662016-02-20 16:05:43 +053014864 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014865 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014866 return -EINVAL;
14867 }
14868
14869 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014870 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014871 return -EINVAL;
14872 }
14873
14874 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14875 status = wlan_hdd_validate_context(pHddCtx);
14876
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014877 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879
14880 p_cds_context = pHddCtx->pcds_context;
14881 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14882
14883 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014884 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 return -EINVAL;
14886 }
14887
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014888 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014889 params->n_acl_entries);
14890
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014891 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014892 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14893 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014894 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014895 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14896
14897 /* default value */
14898 pConfig->num_accept_mac = 0;
14899 pConfig->num_deny_mac = 0;
14900
14901 /**
14902 * access control policy
14903 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14904 * listed in hostapd.deny file.
14905 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14906 * listed in hostapd.accept file.
14907 */
14908 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14909 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14910 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14911 params->acl_policy) {
14912 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14913 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014914 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014915 params->acl_policy);
14916 return -ENOTSUPP;
14917 }
14918
14919 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14920 pConfig->num_accept_mac = params->n_acl_entries;
14921 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014922 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14923 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014924 MAC_ADDR_ARRAY(
14925 params->mac_addrs[i].addr));
14926
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014927 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014928 params->mac_addrs[i].addr,
14929 sizeof(qcmacaddr));
14930 }
14931 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14932 pConfig->num_deny_mac = params->n_acl_entries;
14933 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014934 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14935 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014936 MAC_ADDR_ARRAY(
14937 params->mac_addrs[i].addr));
14938
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014939 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014940 params->mac_addrs[i].addr,
14941 sizeof(qcmacaddr));
14942 }
14943 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014944 qdf_status = wlansap_set_mac_acl(
14945 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014946 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014947 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014948 return -EINVAL;
14949 }
14950 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014951 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014952 hdd_device_mode_to_string(pAdapter->device_mode),
14953 pAdapter->device_mode);
14954 return -EINVAL;
14955 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014956 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957 return 0;
14958}
14959
14960/**
14961 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14962 * __wlan_hdd_cfg80211_set_mac_acl
14963 * @wiphy: pointer to wiphy structure
14964 * @dev: pointer to net_device
14965 * @params: pointer to cfg80211_acl_data
14966 *
14967 * Return; 0 on success, error number otherwise
14968 */
14969static int
14970wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14971 struct net_device *dev,
14972 const struct cfg80211_acl_data *params)
14973{
14974 int ret;
14975
14976 cds_ssr_protect(__func__);
14977 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14978 cds_ssr_unprotect(__func__);
14979
14980 return ret;
14981}
14982
14983#ifdef WLAN_NL80211_TESTMODE
14984#ifdef FEATURE_WLAN_LPHB
14985/**
14986 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14987 * @pHddCtx: Pointer to hdd context
14988 * @lphbInd: Pointer to low power heart beat indication parameter
14989 *
14990 * Return: none
14991 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014992static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14993 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014994{
14995 struct sk_buff *skb;
14996
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014997 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014998
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014999 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015000 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015001
15002 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015003 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015004 return;
15005 }
15006
15007 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15008 wiphy, sizeof(tSirLPHBInd),
15009 GFP_ATOMIC);
15010 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015011 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012 return;
15013 }
15014
15015 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015016 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015017 goto nla_put_failure;
15018 }
15019 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015020 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015021 goto nla_put_failure;
15022 }
15023 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015024 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025 goto nla_put_failure;
15026 }
15027 cfg80211_testmode_event(skb, GFP_ATOMIC);
15028 return;
15029
15030nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015031 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 kfree_skb(skb);
15033
15034 return;
15035}
15036#endif /* FEATURE_WLAN_LPHB */
15037
15038/**
15039 * __wlan_hdd_cfg80211_testmode() - test mode
15040 * @wiphy: Pointer to wiphy
15041 * @data: Data pointer
15042 * @len: Data length
15043 *
15044 * Return: 0 for success, non-zero for failure
15045 */
15046static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15047 void *data, int len)
15048{
15049 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
15050 int err;
15051 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15052
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015053 ENTER();
15054
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015055 err = wlan_hdd_validate_context(pHddCtx);
15056 if (err)
15057 return err;
15058
15059 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
15060 len, wlan_hdd_tm_policy);
15061 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015062 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015063 return err;
15064 }
15065
15066 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015067 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015068 return -EINVAL;
15069 }
15070
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015071 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015072 TRACE_CODE_HDD_CFG80211_TESTMODE,
15073 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015074 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
15075#ifdef FEATURE_WLAN_LPHB
15076 /* Low Power Heartbeat configuration request */
15077 case WLAN_HDD_TM_CMD_WLAN_HB:
15078 {
15079 int buf_len;
15080 void *buf;
15081 tSirLPHBReq *hb_params = NULL;
15082 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015083 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015084
15085 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015086 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087 return -EINVAL;
15088 }
15089
15090 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15091 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15092
15093 hb_params_temp = (tSirLPHBReq *) buf;
15094 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
15095 && (hb_params_temp->params.lphbTcpParamReq.
15096 timePeriodSec == 0))
15097 return -EINVAL;
15098
15099 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015100 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015101 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015102 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015103 return -ENOMEM;
15104 }
15105
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015106 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015107 smeStatus =
15108 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
15109 hb_params,
15110 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015111 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015112 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015113 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015114 }
15115 return 0;
15116 }
15117#endif /* FEATURE_WLAN_LPHB */
15118
15119#if defined(QCA_WIFI_FTM)
15120 case WLAN_HDD_TM_CMD_WLAN_FTM:
15121 {
15122 int buf_len;
15123 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015124 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015126 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015127 return -EINVAL;
15128 }
15129
15130 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15131 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15132
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015133 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015134
15135 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
15136
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015137 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015138 err = -EBUSY;
15139 break;
15140 }
15141#endif
15142
15143 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015144 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015145 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
15146 return -EOPNOTSUPP;
15147 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015148 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015149 return err;
15150}
15151
15152/**
15153 * wlan_hdd_cfg80211_testmode() - test mode
15154 * @wiphy: Pointer to wiphy
15155 * @dev: Pointer to network device
15156 * @data: Data pointer
15157 * @len: Data length
15158 *
15159 * Return: 0 for success, non-zero for failure
15160 */
15161static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15162#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
15163 struct wireless_dev *wdev,
15164#endif
15165 void *data, int len)
15166{
15167 int ret;
15168
15169 cds_ssr_protect(__func__);
15170 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
15171 cds_ssr_unprotect(__func__);
15172
15173 return ret;
15174}
15175
15176#if defined(QCA_WIFI_FTM)
15177/**
15178 * wlan_hdd_testmode_rx_event() - test mode rx event handler
15179 * @buf: Pointer to buffer
15180 * @buf_len: Buffer length
15181 *
15182 * Return: none
15183 */
15184void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
15185{
15186 struct sk_buff *skb;
15187 hdd_context_t *hdd_ctx;
15188
15189 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015190 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015191 return;
15192 }
15193
Anurag Chouhan6d760662016-02-20 16:05:43 +053015194 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015195 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015196 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015197 return;
15198 }
15199
15200 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
15201 buf_len, GFP_KERNEL);
15202 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015203 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015204 return;
15205 }
15206
15207 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
15208 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
15209 goto nla_put_failure;
15210
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015211 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015212
15213 cfg80211_testmode_event(skb, GFP_KERNEL);
15214 return;
15215
15216nla_put_failure:
15217 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015218 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015219}
15220#endif
15221#endif /* CONFIG_NL80211_TESTMODE */
15222
15223#ifdef QCA_HT_2040_COEX
15224/**
15225 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15226 * @wiphy: Pointer to wiphy
15227 * @dev: Pointer to network device
15228 * @chandef: Pointer to channel definition parameter
15229 *
15230 * Return: 0 for success, non-zero for failure
15231 */
15232static int
15233__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15234 struct net_device *dev,
15235 struct cfg80211_chan_def *chandef)
15236{
15237 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15238 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015239 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015240 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053015241 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015242
Anurag Chouhan6d760662016-02-20 16:05:43 +053015243 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015244 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015245 return -EINVAL;
15246 }
15247
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015248 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15249 hdd_err("invalid session id: %d", pAdapter->sessionId);
15250 return -EINVAL;
15251 }
15252
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015253 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15254 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053015255 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015256 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015257
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015258 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015259 sme_get_config_param(pHddCtx->hHal, &sme_config);
15260 switch (chandef->width) {
15261 case NL80211_CHAN_WIDTH_20:
15262 if (sme_config.csrConfig.channelBondingMode24GHz !=
15263 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15264 sme_config.csrConfig.channelBondingMode24GHz =
15265 eCSR_INI_SINGLE_CHANNEL_CENTERED;
15266 sme_update_config(pHddCtx->hHal, &sme_config);
15267 cbModeChange = true;
15268 }
15269 break;
15270
15271 case NL80211_CHAN_WIDTH_40:
15272 if (sme_config.csrConfig.channelBondingMode24GHz ==
15273 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15274 if (NL80211_CHAN_HT40MINUS ==
15275 cfg80211_get_chandef_type(chandef))
15276 sme_config.csrConfig.channelBondingMode24GHz =
15277 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
15278 else
15279 sme_config.csrConfig.channelBondingMode24GHz =
15280 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
15281 sme_update_config(pHddCtx->hHal, &sme_config);
15282 cbModeChange = true;
15283 }
15284 break;
15285
15286 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015287 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015288 return -EINVAL;
15289 }
15290
15291 if (!cbModeChange)
15292 return 0;
15293
Krunal Sonib4326f22016-03-10 13:05:51 -080015294 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 return 0;
15296
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015297 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298 sme_config.csrConfig.channelBondingMode24GHz);
15299
15300 /* Change SAP ht2040 mode */
15301 status = hdd_set_sap_ht2040_mode(pAdapter,
15302 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015303 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015304 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015305 return -EINVAL;
15306 }
15307
15308 return 0;
15309}
15310
15311/**
15312 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15313 * @wiphy: Pointer to wiphy
15314 * @dev: Pointer to network device
15315 * @chandef: Pointer to channel definition parameter
15316 *
15317 * Return: 0 for success, non-zero for failure
15318 */
15319static int
15320wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15321 struct net_device *dev,
15322 struct cfg80211_chan_def *chandef)
15323{
15324 int ret;
15325
15326 cds_ssr_protect(__func__);
15327 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
15328 cds_ssr_unprotect(__func__);
15329
15330 return ret;
15331}
15332#endif
15333
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015334#ifdef CHANNEL_SWITCH_SUPPORTED
15335/**
15336 * __wlan_hdd_cfg80211_channel_switch()- function to switch
15337 * channel in SAP/GO
15338 * @wiphy: wiphy pointer
15339 * @dev: dev pointer.
15340 * @csa_params: Change channel params
15341 *
15342 * This function is called to switch channel in SAP/GO
15343 *
15344 * Return: 0 if success else return non zero
15345 */
15346static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15347 struct net_device *dev,
15348 struct cfg80211_csa_settings *csa_params)
15349{
15350 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15351 hdd_context_t *hdd_ctx;
15352 uint8_t channel;
15353 uint16_t freq;
15354 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080015355 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015356
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015357 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015358 csa_params->chandef.chan->center_freq);
15359
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015360 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
15361 hdd_err("invalid session id: %d", adapter->sessionId);
15362 return -EINVAL;
15363 }
15364
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015365 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15366 ret = wlan_hdd_validate_context(hdd_ctx);
15367
15368 if (0 != ret)
15369 return ret;
15370
Krunal Sonib4326f22016-03-10 13:05:51 -080015371 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
15372 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015373 return -ENOTSUPP;
15374
15375 freq = csa_params->chandef.chan->center_freq;
15376 channel = cds_freq_to_chan(freq);
15377
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053015378 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
15379
15380 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015381 return ret;
15382}
15383
15384/**
15385 * wlan_hdd_cfg80211_channel_switch()- function to switch
15386 * channel in SAP/GO
15387 * @wiphy: wiphy pointer
15388 * @dev: dev pointer.
15389 * @csa_params: Change channel params
15390 *
15391 * This function is called to switch channel in SAP/GO
15392 *
15393 * Return: 0 if success else return non zero
15394 */
15395static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15396 struct net_device *dev,
15397 struct cfg80211_csa_settings *csa_params)
15398{
15399 int ret;
15400
15401 cds_ssr_protect(__func__);
15402 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15403 cds_ssr_unprotect(__func__);
15404 return ret;
15405}
15406#endif
15407
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015408/**
15409 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15410 * translation from NL to policy manager type
15411 * @type: Generic connection mode type defined in NL
15412 *
15413 *
15414 * This function provides the type translation
15415 *
15416 * Return: cds_con_mode enum
15417 */
15418enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15419 enum nl80211_iftype type)
15420{
15421 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15422 switch (type) {
15423 case NL80211_IFTYPE_STATION:
15424 mode = CDS_STA_MODE;
15425 break;
15426 case NL80211_IFTYPE_P2P_CLIENT:
15427 mode = CDS_P2P_CLIENT_MODE;
15428 break;
15429 case NL80211_IFTYPE_P2P_GO:
15430 mode = CDS_P2P_GO_MODE;
15431 break;
15432 case NL80211_IFTYPE_AP:
15433 mode = CDS_SAP_MODE;
15434 break;
15435 case NL80211_IFTYPE_ADHOC:
15436 mode = CDS_IBSS_MODE;
15437 break;
15438 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015439 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015440 type);
15441 }
15442 return mode;
15443}
15444
15445/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015446 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15447 * @wiphy: Handle to struct wiphy to get handle to module context.
15448 * @chandef: Contains information about the capture channel to be set.
15449 *
15450 * This interface is called if and only if monitor mode interface alone is
15451 * active.
15452 *
15453 * Return: 0 success or error code on failure.
15454 */
15455static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15456 struct cfg80211_chan_def *chandef)
15457{
15458 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15459 hdd_adapter_t *adapter;
15460 hdd_station_ctx_t *sta_ctx;
15461 struct hdd_mon_set_ch_info *ch_info;
15462 QDF_STATUS status;
15463 tHalHandle hal_hdl;
15464 struct qdf_mac_addr bssid;
15465 tCsrRoamProfile roam_profile;
15466 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015467 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015468 int ret;
15469 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15470
15471 ENTER();
15472
15473 ret = wlan_hdd_validate_context(hdd_ctx);
15474 if (ret)
15475 return ret;
15476
15477 hal_hdl = hdd_ctx->hHal;
15478
15479 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15480 if (!adapter)
15481 return -EIO;
15482
15483 hdd_info("%s: set monitor mode Channel %d and freq %d",
15484 adapter->dev->name, chan_num, chandef->chan->center_freq);
15485
15486 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15487 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015488 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15489 roam_profile.ChannelInfo.numOfChannels = 1;
15490 roam_profile.phyMode = ch_info->phy_mode;
15491 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015492 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015493
15494 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15495 QDF_MAC_ADDR_SIZE);
15496
15497 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015498 /*
15499 * CDS api expects secondary channel for calculating
15500 * the channel params
15501 */
15502 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15503 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15504 if (chan_num >= 1 && chan_num <= 5)
15505 sec_ch = chan_num + 4;
15506 else if (chan_num >= 6 && chan_num <= 13)
15507 sec_ch = chan_num - 4;
15508 }
15509 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015510 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15511 &roam_profile);
15512 if (status) {
15513 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15514 status);
15515 ret = qdf_status_to_os_return(status);
15516 return ret;
15517 }
15518 EXIT();
15519 return 0;
15520}
15521
15522/**
15523 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15524 * @wiphy: Handle to struct wiphy to get handle to module context.
15525 * @chandef: Contains information about the capture channel to be set.
15526 *
15527 * This interface is called if and only if monitor mode interface alone is
15528 * active.
15529 *
15530 * Return: 0 success or error code on failure.
15531 */
15532static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15533 struct cfg80211_chan_def *chandef)
15534{
15535 int ret;
15536
15537 cds_ssr_protect(__func__);
15538 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15539 cds_ssr_unprotect(__func__);
15540 return ret;
15541}
15542
15543/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015544 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15545 * @adapter: pointer to adapter
15546 *
15547 * Wrapper function to clear link layer stats.
15548 * return - void
15549 */
15550void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15551{
15552 tSirLLStatsClearReq link_layer_stats_clear_req;
15553 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15554
Mukul Sharma491021c2016-09-29 21:39:19 +053015555 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15556 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015557 link_layer_stats_clear_req.stopReq = 0;
15558 link_layer_stats_clear_req.reqId = 1;
15559 link_layer_stats_clear_req.staId = adapter->sessionId;
15560 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15561
15562 return;
15563}
15564
15565/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015566 * struct cfg80211_ops - cfg80211_ops
15567 *
15568 * @add_virtual_intf: Add virtual interface
15569 * @del_virtual_intf: Delete virtual interface
15570 * @change_virtual_intf: Change virtual interface
15571 * @change_station: Change station
15572 * @add_beacon: Add beacon in sap mode
15573 * @del_beacon: Delete beacon in sap mode
15574 * @set_beacon: Set beacon in sap mode
15575 * @start_ap: Start ap
15576 * @change_beacon: Change beacon
15577 * @stop_ap: Stop ap
15578 * @change_bss: Change bss
15579 * @add_key: Add key
15580 * @get_key: Get key
15581 * @del_key: Delete key
15582 * @set_default_key: Set default key
15583 * @set_channel: Set channel
15584 * @scan: Scan
15585 * @connect: Connect
15586 * @disconnect: Disconnect
15587 * @join_ibss = Join ibss
15588 * @leave_ibss = Leave ibss
15589 * @set_wiphy_params = Set wiphy params
15590 * @set_tx_power = Set tx power
15591 * @get_tx_power = get tx power
15592 * @remain_on_channel = Remain on channel
15593 * @cancel_remain_on_channel = Cancel remain on channel
15594 * @mgmt_tx = Tx management frame
15595 * @mgmt_tx_cancel_wait = Cancel management tx wait
15596 * @set_default_mgmt_key = Set default management key
15597 * @set_txq_params = Set tx queue parameters
15598 * @get_station = Get station
15599 * @set_power_mgmt = Set power management
15600 * @del_station = Delete station
15601 * @add_station = Add station
15602 * @set_pmksa = Set pmksa
15603 * @del_pmksa = Delete pmksa
15604 * @flush_pmksa = Flush pmksa
15605 * @update_ft_ies = Update FT IEs
15606 * @tdls_mgmt = Tdls management
15607 * @tdls_oper = Tdls operation
15608 * @set_rekey_data = Set rekey data
15609 * @sched_scan_start = Scheduled scan start
15610 * @sched_scan_stop = Scheduled scan stop
15611 * @resume = Resume wlan
15612 * @suspend = Suspend wlan
15613 * @set_mac_acl = Set mac acl
15614 * @testmode_cmd = Test mode command
15615 * @set_ap_chanwidth = Set AP channel bandwidth
15616 * @dump_survey = Dump survey
15617 * @key_mgmt_set_pmk = Set pmk key management
15618 */
15619static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15620 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15621 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15622 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15623 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015624 .start_ap = wlan_hdd_cfg80211_start_ap,
15625 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15626 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015627 .change_bss = wlan_hdd_cfg80211_change_bss,
15628 .add_key = wlan_hdd_cfg80211_add_key,
15629 .get_key = wlan_hdd_cfg80211_get_key,
15630 .del_key = wlan_hdd_cfg80211_del_key,
15631 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15632 .scan = wlan_hdd_cfg80211_scan,
15633 .connect = wlan_hdd_cfg80211_connect,
15634 .disconnect = wlan_hdd_cfg80211_disconnect,
15635 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15636 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15637 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15638 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15639 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15640 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15641 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15642 .mgmt_tx = wlan_hdd_mgmt_tx,
15643 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15644 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15645 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015646 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015647 .get_station = wlan_hdd_cfg80211_get_station,
15648 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15649 .del_station = wlan_hdd_cfg80211_del_station,
15650 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015651 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15652 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15653 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015654#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015655 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15656#endif
15657#ifdef FEATURE_WLAN_TDLS
15658 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15659 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15660#endif
15661#ifdef WLAN_FEATURE_GTK_OFFLOAD
15662 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15663#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15664#ifdef FEATURE_WLAN_SCAN_PNO
15665 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15666 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15667#endif /*FEATURE_WLAN_SCAN_PNO */
15668 .resume = wlan_hdd_cfg80211_resume_wlan,
15669 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15670 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15671#ifdef WLAN_NL80211_TESTMODE
15672 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15673#endif
15674#ifdef QCA_HT_2040_COEX
15675 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15676#endif
15677 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015678#ifdef CHANNEL_SWITCH_SUPPORTED
15679 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15680#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015681 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015682#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15683 defined(CFG80211_ABORT_SCAN)
15684 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15685#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015686};