blob: d108e8a4b850998e36f99ae93b897f0f18f990a3 [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"
Paul Zhang3a210c52016-12-08 10:18:12 +080077#ifdef WLAN_UMAC_CONVERGENCE
78#include "wlan_cfg80211.h"
79#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080080#include <cdp_txrx_handle.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
Ravi Joshideb5a8d2015-11-09 19:11:43 -080096#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053097#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070098#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070099#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530100#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800101
Leo Changfdb45c32016-10-28 11:09:23 -0700102#include <cdp_txrx_cmn.h>
103#include <cdp_txrx_misc.h>
104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define g_mode_rates_size (12)
106#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
108 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
109
110/*
111 * Android CTS verifier needs atleast this much wait time (in msec)
112 */
113#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
114
115/*
116 * Refer @tCfgProtection structure for definition of the bit map.
117 * below value is obtained by setting the following bit-fields.
118 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
119 */
120#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
121
122#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700123 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 .center_freq = (freq), \
125 .hw_value = (chan), \
126 .flags = (flag), \
127 .max_antenna_gain = 0, \
128 .max_power = 30, \
129}
130
131#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
137 .max_power = 30, \
138}
139
140#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
141 { \
142 .bitrate = rate, \
143 .hw_value = rate_id, \
144 .flags = flag, \
145 }
146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
148#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
150#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
Agrawal Ashish65634612016-08-18 13:24:32 +0530152#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
153 mode <= DFS_MODE_DEPRIORITIZE))
154#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
155 || (channel >= 36 && channel <= 184))
156
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530158#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160static const u32 hdd_cipher_suites[] = {
161 WLAN_CIPHER_SUITE_WEP40,
162 WLAN_CIPHER_SUITE_WEP104,
163 WLAN_CIPHER_SUITE_TKIP,
164#ifdef FEATURE_WLAN_ESE
165#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
166#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
167 WLAN_CIPHER_SUITE_BTK,
168 WLAN_CIPHER_SUITE_KRK,
169 WLAN_CIPHER_SUITE_CCMP,
170#else
171 WLAN_CIPHER_SUITE_CCMP,
172#endif
173#ifdef FEATURE_WLAN_WAPI
174 WLAN_CIPHER_SUITE_SMS4,
175#endif
176#ifdef WLAN_FEATURE_11W
177 WLAN_CIPHER_SUITE_AES_CMAC,
178#endif
179};
180
Abhishek Singhf512bf32016-05-04 16:47:46 +0530181static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 HDD2GHZCHAN(2412, 1, 0),
183 HDD2GHZCHAN(2417, 2, 0),
184 HDD2GHZCHAN(2422, 3, 0),
185 HDD2GHZCHAN(2427, 4, 0),
186 HDD2GHZCHAN(2432, 5, 0),
187 HDD2GHZCHAN(2437, 6, 0),
188 HDD2GHZCHAN(2442, 7, 0),
189 HDD2GHZCHAN(2447, 8, 0),
190 HDD2GHZCHAN(2452, 9, 0),
191 HDD2GHZCHAN(2457, 10, 0),
192 HDD2GHZCHAN(2462, 11, 0),
193 HDD2GHZCHAN(2467, 12, 0),
194 HDD2GHZCHAN(2472, 13, 0),
195 HDD2GHZCHAN(2484, 14, 0),
196};
197
Abhishek Singhf512bf32016-05-04 16:47:46 +0530198static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 HDD5GHZCHAN(5180, 36, 0),
200 HDD5GHZCHAN(5200, 40, 0),
201 HDD5GHZCHAN(5220, 44, 0),
202 HDD5GHZCHAN(5240, 48, 0),
203 HDD5GHZCHAN(5260, 52, 0),
204 HDD5GHZCHAN(5280, 56, 0),
205 HDD5GHZCHAN(5300, 60, 0),
206 HDD5GHZCHAN(5320, 64, 0),
207 HDD5GHZCHAN(5500, 100, 0),
208 HDD5GHZCHAN(5520, 104, 0),
209 HDD5GHZCHAN(5540, 108, 0),
210 HDD5GHZCHAN(5560, 112, 0),
211 HDD5GHZCHAN(5580, 116, 0),
212 HDD5GHZCHAN(5600, 120, 0),
213 HDD5GHZCHAN(5620, 124, 0),
214 HDD5GHZCHAN(5640, 128, 0),
215 HDD5GHZCHAN(5660, 132, 0),
216 HDD5GHZCHAN(5680, 136, 0),
217 HDD5GHZCHAN(5700, 140, 0),
218 HDD5GHZCHAN(5720, 144, 0),
219 HDD5GHZCHAN(5745, 149, 0),
220 HDD5GHZCHAN(5765, 153, 0),
221 HDD5GHZCHAN(5785, 157, 0),
222 HDD5GHZCHAN(5805, 161, 0),
223 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 HDD5GHZCHAN(5852, 170, 0),
225 HDD5GHZCHAN(5855, 171, 0),
226 HDD5GHZCHAN(5860, 172, 0),
227 HDD5GHZCHAN(5865, 173, 0),
228 HDD5GHZCHAN(5870, 174, 0),
229 HDD5GHZCHAN(5875, 175, 0),
230 HDD5GHZCHAN(5880, 176, 0),
231 HDD5GHZCHAN(5885, 177, 0),
232 HDD5GHZCHAN(5890, 178, 0),
233 HDD5GHZCHAN(5895, 179, 0),
234 HDD5GHZCHAN(5900, 180, 0),
235 HDD5GHZCHAN(5905, 181, 0),
236 HDD5GHZCHAN(5910, 182, 0),
237 HDD5GHZCHAN(5915, 183, 0),
238 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239};
240
241static struct ieee80211_rate g_mode_rates[] = {
242 HDD_G_MODE_RATETAB(10, 0x1, 0),
243 HDD_G_MODE_RATETAB(20, 0x2, 0),
244 HDD_G_MODE_RATETAB(55, 0x4, 0),
245 HDD_G_MODE_RATETAB(110, 0x8, 0),
246 HDD_G_MODE_RATETAB(60, 0x10, 0),
247 HDD_G_MODE_RATETAB(90, 0x20, 0),
248 HDD_G_MODE_RATETAB(120, 0x40, 0),
249 HDD_G_MODE_RATETAB(180, 0x80, 0),
250 HDD_G_MODE_RATETAB(240, 0x100, 0),
251 HDD_G_MODE_RATETAB(360, 0x200, 0),
252 HDD_G_MODE_RATETAB(480, 0x400, 0),
253 HDD_G_MODE_RATETAB(540, 0x800, 0),
254};
255
256static struct ieee80211_rate a_mode_rates[] = {
257 HDD_G_MODE_RATETAB(60, 0x10, 0),
258 HDD_G_MODE_RATETAB(90, 0x20, 0),
259 HDD_G_MODE_RATETAB(120, 0x40, 0),
260 HDD_G_MODE_RATETAB(180, 0x80, 0),
261 HDD_G_MODE_RATETAB(240, 0x100, 0),
262 HDD_G_MODE_RATETAB(360, 0x200, 0),
263 HDD_G_MODE_RATETAB(480, 0x400, 0),
264 HDD_G_MODE_RATETAB(540, 0x800, 0),
265};
266
267static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530268 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700270 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
278 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
279 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
280 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
281 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
282 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
283 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
284};
285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530287 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700289 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290 .bitrates = a_mode_rates,
291 .n_bitrates = a_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
297 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
298 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
299 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
300 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
301 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
302 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
303 .vht_cap.vht_supported = 1,
304};
305
306/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800307 * TX/RX direction for each kind of interface
308 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309static const struct ieee80211_txrx_stypes
310 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
311 [NL80211_IFTYPE_STATION] = {
312 .tx = 0xffff,
313 .rx = BIT(SIR_MAC_MGMT_ACTION) |
314 BIT(SIR_MAC_MGMT_PROBE_REQ),
315 },
316 [NL80211_IFTYPE_AP] = {
317 .tx = 0xffff,
318 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
319 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_PROBE_REQ) |
321 BIT(SIR_MAC_MGMT_DISASSOC) |
322 BIT(SIR_MAC_MGMT_AUTH) |
323 BIT(SIR_MAC_MGMT_DEAUTH) |
324 BIT(SIR_MAC_MGMT_ACTION),
325 },
326 [NL80211_IFTYPE_ADHOC] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_P2P_CLIENT] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ACTION) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ),
340 },
341 [NL80211_IFTYPE_P2P_GO] = {
342 /* This is also same as for SoftAP */
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ) |
347 BIT(SIR_MAC_MGMT_DISASSOC) |
348 BIT(SIR_MAC_MGMT_AUTH) |
349 BIT(SIR_MAC_MGMT_DEAUTH) |
350 BIT(SIR_MAC_MGMT_ACTION),
351 },
352};
353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354/* Interface limits and combinations registered by the driver */
355
356/* STA ( + STA ) combination */
357static const struct ieee80211_iface_limit
358 wlan_hdd_sta_iface_limit[] = {
359 {
360 .max = 3, /* p2p0 is a STA as well */
361 .types = BIT(NL80211_IFTYPE_STATION),
362 },
363};
364
365/* ADHOC (IBSS) limit */
366static const struct ieee80211_iface_limit
367 wlan_hdd_adhoc_iface_limit[] = {
368 {
369 .max = 1,
370 .types = BIT(NL80211_IFTYPE_STATION),
371 },
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_ADHOC),
375 },
376};
377
378/* AP ( + AP ) combination */
379static const struct ieee80211_iface_limit
380 wlan_hdd_ap_iface_limit[] = {
381 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530382 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 .types = BIT(NL80211_IFTYPE_AP),
384 },
385};
386
387/* P2P limit */
388static const struct ieee80211_iface_limit
389 wlan_hdd_p2p_iface_limit[] = {
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
393 },
394 {
395 .max = 1,
396 .types = BIT(NL80211_IFTYPE_P2P_GO),
397 },
398};
399
400static const struct ieee80211_iface_limit
401 wlan_hdd_sta_ap_iface_limit[] = {
402 {
403 /* We need 1 extra STA interface for OBSS scan when SAP starts
404 * with HT40 in STA+SAP concurrency mode
405 */
406 .max = (1 + SAP_MAX_OBSS_STA_CNT),
407 .types = BIT(NL80211_IFTYPE_STATION),
408 },
409 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530410 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 .types = BIT(NL80211_IFTYPE_AP),
412 },
413};
414
415/* STA + P2P combination */
416static const struct ieee80211_iface_limit
417 wlan_hdd_sta_p2p_iface_limit[] = {
418 {
419 /* One reserved for dedicated P2PDEV usage */
420 .max = 2,
421 .types = BIT(NL80211_IFTYPE_STATION)
422 },
423 {
424 /* Support for two identical (GO + GO or CLI + CLI)
425 * or dissimilar (GO + CLI) P2P interfaces
426 */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
429 },
430};
431
432/* STA + AP + P2PGO combination */
433static const struct ieee80211_iface_limit
434wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
435 /* Support for AP+P2PGO interfaces */
436 {
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_STATION)
439 },
440 {
441 .max = 1,
442 .types = BIT(NL80211_IFTYPE_P2P_GO)
443 },
444 {
445 .max = 1,
446 .types = BIT(NL80211_IFTYPE_AP)
447 }
448};
449
450/* SAP + P2P combination */
451static const struct ieee80211_iface_limit
452wlan_hdd_sap_p2p_iface_limit[] = {
453 {
454 /* 1 dedicated for p2p0 which is a STA type */
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_STATION)
457 },
458 {
459 /* The p2p interface in SAP+P2P can be GO/CLI.
460 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
461 */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
464 },
465 {
466 /* SAP+GO to support only one SAP interface */
467 .max = 1,
468 .types = BIT(NL80211_IFTYPE_AP)
469 }
470};
471
472/* P2P + P2P combination */
473static const struct ieee80211_iface_limit
474wlan_hdd_p2p_p2p_iface_limit[] = {
475 {
476 /* 1 dedicated for p2p0 which is a STA type */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_STATION)
479 },
480 {
481 /* The p2p interface in P2P+P2P can be GO/CLI.
482 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
483 */
484 .max = 2,
485 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
486 },
487};
488
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700489static const struct ieee80211_iface_limit
490 wlan_hdd_mon_iface_limit[] = {
491 {
492 .max = 3, /* Monitor interface */
493 .types = BIT(NL80211_IFTYPE_MONITOR),
494 },
495};
496
497static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800498 wlan_hdd_iface_combination[] = {
499 /* STA */
500 {
501 .limits = wlan_hdd_sta_iface_limit,
502 .num_different_channels = 2,
503 .max_interfaces = 3,
504 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
505 },
506 /* ADHOC */
507 {
508 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700509 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 .max_interfaces = 2,
511 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
512 },
513 /* AP */
514 {
515 .limits = wlan_hdd_ap_iface_limit,
516 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530517 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
519 },
520 /* P2P */
521 {
522 .limits = wlan_hdd_p2p_iface_limit,
523 .num_different_channels = 2,
524 .max_interfaces = 2,
525 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
526 },
527 /* STA + AP */
528 {
529 .limits = wlan_hdd_sta_ap_iface_limit,
530 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
533 .beacon_int_infra_match = true,
534 },
535 /* STA + P2P */
536 {
537 .limits = wlan_hdd_sta_p2p_iface_limit,
538 .num_different_channels = 2,
539 /* one interface reserved for P2PDEV dedicated usage */
540 .max_interfaces = 4,
541 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
542 .beacon_int_infra_match = true,
543 },
544 /* STA + P2P GO + SAP */
545 {
546 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
547 /* we can allow 3 channels for three different persona
548 * but due to firmware limitation, allow max 2 concrnt channels.
549 */
550 .num_different_channels = 2,
551 /* one interface reserved for P2PDEV dedicated usage */
552 .max_interfaces = 4,
553 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
554 .beacon_int_infra_match = true,
555 },
556 /* SAP + P2P */
557 {
558 .limits = wlan_hdd_sap_p2p_iface_limit,
559 .num_different_channels = 2,
560 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
561 .max_interfaces = 3,
562 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
563 .beacon_int_infra_match = true,
564 },
565 /* P2P + P2P */
566 {
567 .limits = wlan_hdd_p2p_p2p_iface_limit,
568 .num_different_channels = 2,
569 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
570 .max_interfaces = 3,
571 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
572 .beacon_int_infra_match = true,
573 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530574 /* Monitor */
575 {
576 .limits = wlan_hdd_mon_iface_limit,
577 .max_interfaces = 3,
578 .num_different_channels = 2,
579 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
580 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530584struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586#ifdef WLAN_NL80211_TESTMODE
587enum wlan_hdd_tm_attr {
588 WLAN_HDD_TM_ATTR_INVALID = 0,
589 WLAN_HDD_TM_ATTR_CMD = 1,
590 WLAN_HDD_TM_ATTR_DATA = 2,
591 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
592 WLAN_HDD_TM_ATTR_TYPE = 4,
593 /* keep last */
594 WLAN_HDD_TM_ATTR_AFTER_LAST,
595 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
596};
597
598enum wlan_hdd_tm_cmd {
599 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
600 WLAN_HDD_TM_CMD_WLAN_HB = 1,
601};
602
603#define WLAN_HDD_TM_DATA_MAX_LEN 5000
604
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530605enum wlan_hdd_vendor_ie_access_policy {
606 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
607 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
608};
609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
611 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
612 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
613 .len = WLAN_HDD_TM_DATA_MAX_LEN},
614};
615#endif /* WLAN_NL80211_TESTMODE */
616
617#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
618static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
619 .flags = WIPHY_WOWLAN_MAGIC_PKT,
620 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
621 .pattern_min_len = 1,
622 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
623};
624#endif
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530627 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
628 * @flags: Pointer to the flags to Add channel switch flag.
629 *
630 * This Function adds Channel Switch support flag, if channel switch is
631 * supported by kernel.
632 * Return: void.
633 */
634#ifdef CHANNEL_SWITCH_SUPPORTED
635static inline void hdd_add_channel_switch_support(uint32_t *flags)
636{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800637 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530638 return;
639}
640#else
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
643 return;
644}
645#endif
646
Manikandan Mohan22b83722015-12-15 15:03:23 -0800647#ifdef FEATURE_WLAN_TDLS
648
649/* TDLS capabilities params */
650#define PARAM_MAX_TDLS_SESSION \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
652#define PARAM_TDLS_FEATURE_SUPPORT \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
654
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
657 * @wiphy: WIPHY structure pointer
658 * @wdev: Wireless device structure pointer
659 * @data: Pointer to the data received
660 * @data_len: Length of the data received
661 *
662 * This function provides TDLS capabilities
663 *
664 * Return: 0 on success and errno on failure
665 */
666static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
667 struct wireless_dev *wdev,
668 const void *data,
669 int data_len)
670{
671 int status;
672 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
673 struct sk_buff *skb;
674 uint32_t set = 0;
675
Jeff Johnson1f61b612016-02-12 16:28:33 -0800676 ENTER_DEV(wdev->netdev);
677
Anurag Chouhan6d760662016-02-20 16:05:43 +0530678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 hdd_err("Command not allowed in FTM mode");
680 return -EPERM;
681 }
682
683 status = wlan_hdd_validate_context(hdd_ctx);
684 if (status)
685 return status;
686
687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
688 NLMSG_HDRLEN);
689 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700690 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 goto fail;
692 }
693
694 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
697 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701 } else {
702 set = set | WIFI_TDLS_SUPPORT;
703 set = set | (hdd_ctx->config->fTDLSExternalControl ?
704 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
705 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
706 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
709 hdd_ctx->max_num_tdls_sta) ||
710 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
711 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700712 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 goto fail;
714 }
715 }
716 return cfg80211_vendor_cmd_reply(skb);
717fail:
718 if (skb)
719 kfree_skb(skb);
720 return -EINVAL;
721}
722
723/**
724 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
725 * @wiphy: WIPHY structure pointer
726 * @wdev: Wireless device structure pointer
727 * @data: Pointer to the data received
728 * @data_len: Length of the data received
729 *
730 * This function provides TDLS capabilities
731 *
732 * Return: 0 on success and errno on failure
733 */
734static int
735wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
736 struct wireless_dev *wdev,
737 const void *data,
738 int data_len)
739{
740 int ret;
741
742 cds_ssr_protect(__func__);
743 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
744 data, data_len);
745 cds_ssr_unprotect(__func__);
746
747 return ret;
748}
749#endif
750
751#ifdef QCA_HT_2040_COEX
752static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
753#endif
754
755#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
756/*
757 * FUNCTION: wlan_hdd_send_avoid_freq_event
758 * This is called when wlan driver needs to send vendor specific
759 * avoid frequency range event to userspace
760 */
761int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
762 tHddAvoidFreqList *pAvoidFreqList)
763{
764 struct sk_buff *vendor_event;
765
766 ENTER();
767
768 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700769 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 return -EINVAL;
771 }
772
773 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700774 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return -EINVAL;
776 }
777
778 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
779 NULL,
780 sizeof(tHddAvoidFreqList),
781 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
782 GFP_KERNEL);
783 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700784 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 return -EINVAL;
786 }
787
788 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
789 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
790
791 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
792
793 EXIT();
794 return 0;
795}
796#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
797
798/* vendor specific events */
799static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
800#ifdef FEATURE_WLAN_CH_AVOID
801 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
806 },
807#endif /* FEATURE_WLAN_CH_AVOID */
808
809#ifdef WLAN_FEATURE_NAN
810 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_NAN
815 },
816#endif
817
818#ifdef WLAN_FEATURE_STATS_EXT
819 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
824 },
825#endif /* WLAN_FEATURE_STATS_EXT */
826#ifdef FEATURE_WLAN_EXTSCAN
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
832 },
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
840 .
841 vendor_id
842 =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .
853 subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd
863 =
864 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
865 },
866 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
867 .
868 vendor_id
869 =
870 QCA_NL80211_VENDOR_ID,
871 .subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
875 .vendor_id =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
881 .
882 vendor_id
883 =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .
912 subcmd =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd
922 =
923 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
924 },
925 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
926 .
927 vendor_id
928 =
929 QCA_NL80211_VENDOR_ID,
930 .
931 subcmd
932 =
933 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
938 },
939 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
940 .vendor_id = QCA_NL80211_VENDOR_ID,
941 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
942 },
943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
982#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
983 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
990 .vendor_id = QCA_NL80211_VENDOR_ID,
991 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
992 },
993#ifdef WLAN_FEATURE_ROAM_OFFLOAD
994 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
999 },
1000#endif
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1030 },
1031#ifdef FEATURE_WLAN_EXTSCAN
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1047 },
1048 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1051 },
1052#endif /* FEATURE_WLAN_EXTSCAN */
1053 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1056 },
1057#ifdef WLAN_FEATURE_MEMDUMP
1058 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1061 },
1062#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001063#ifdef WLAN_FEATURE_TSF
1064 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1067 },
1068#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1072 },
1073 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1076 },
1077 /* OCB events */
1078 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1081 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001082#ifdef FEATURE_LFR_SUBNET_DETECTION
1083 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1084 .vendor_id = QCA_NL80211_VENDOR_ID,
1085 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1086 },
1087#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001088
1089#ifdef WLAN_FEATURE_NAN_DATAPATH
1090 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1093 },
1094#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001095
1096 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1099 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301100 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1101 .vendor_id = QCA_NL80211_VENDOR_ID,
1102 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1103 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301104 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1105 .vendor_id = QCA_NL80211_VENDOR_ID,
1106 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1107 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001108#ifdef WLAN_UMAC_CONVERGENCE
1109 COMMON_VENDOR_EVENTS
1110#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111};
1112
1113/**
1114 * __is_driver_dfs_capable() - get driver DFS capability
1115 * @wiphy: pointer to wireless wiphy structure.
1116 * @wdev: pointer to wireless_dev structure.
1117 * @data: Pointer to the data to be passed via vendor interface
1118 * @data_len:Length of the data to be passed
1119 *
1120 * This function is called by userspace to indicate whether or not
1121 * the driver supports DFS offload.
1122 *
1123 * Return: 0 on success, negative errno on failure
1124 */
1125static int __is_driver_dfs_capable(struct wiphy *wiphy,
1126 struct wireless_dev *wdev,
1127 const void *data,
1128 int data_len)
1129{
1130 u32 dfs_capability = 0;
1131 struct sk_buff *temp_skbuff;
1132 int ret_val;
1133 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1134
Jeff Johnson1f61b612016-02-12 16:28:33 -08001135 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136
1137 ret_val = wlan_hdd_validate_context(hdd_ctx);
1138 if (ret_val)
1139 return ret_val;
1140
Anurag Chouhan6d760662016-02-20 16:05:43 +05301141 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 hdd_err("Command not allowed in FTM mode");
1143 return -EPERM;
1144 }
1145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147
1148 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1149 NLMSG_HDRLEN);
1150
1151 if (temp_skbuff != NULL) {
1152 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1153 dfs_capability);
1154 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001155 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 kfree_skb(temp_skbuff);
1157
1158 return ret_val;
1159 }
1160
1161 return cfg80211_vendor_cmd_reply(temp_skbuff);
1162 }
1163
Jeff Johnson020db452016-06-29 14:37:26 -07001164 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 return -ENOMEM;
1166}
1167
1168/**
1169 * is_driver_dfs_capable() - get driver DFS capability
1170 * @wiphy: pointer to wireless wiphy structure.
1171 * @wdev: pointer to wireless_dev structure.
1172 * @data: Pointer to the data to be passed via vendor interface
1173 * @data_len:Length of the data to be passed
1174 *
1175 * This function is called by userspace to indicate whether or not
1176 * the driver supports DFS offload. This is an SSR-protected
1177 * wrapper function.
1178 *
1179 * Return: 0 on success, negative errno on failure
1180 */
1181static int is_driver_dfs_capable(struct wiphy *wiphy,
1182 struct wireless_dev *wdev,
1183 const void *data,
1184 int data_len)
1185{
1186 int ret;
1187
1188 cds_ssr_protect(__func__);
1189 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1190 cds_ssr_unprotect(__func__);
1191
1192 return ret;
1193}
1194
1195/**
1196 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1197 *
1198 * @adapter: SAP adapter pointer
1199 *
1200 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1201 * radio. So in case of DFS MCC scenario override current SAP given config
1202 * to follow concurrent SAP DFS config
1203 *
1204 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1205 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1207{
1208 hdd_adapter_t *con_sap_adapter;
1209 tsap_Config_t *sap_config, *con_sap_config;
1210 int con_ch;
1211
1212 /*
1213 * Check if AP+AP case, once primary AP chooses a DFS
1214 * channel secondary AP should always follow primary APs channel
1215 */
1216 if (!cds_concurrent_beaconing_sessions_running())
1217 return 0;
1218
1219 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1220 if (!con_sap_adapter)
1221 return 0;
1222
1223 sap_config = &adapter->sessionCtx.ap.sapConfig;
1224 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1225 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1226
1227 if (!CDS_IS_DFS_CH(con_ch))
1228 return 0;
1229
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001232 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 sap_config->channel = con_ch;
1234
1235 if (con_sap_config->acs_cfg.acs_mode == true) {
1236 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1237 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001238 hdd_err("Primary AP channel config error");
1239 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 con_ch, con_sap_config->acs_cfg.pri_ch,
1241 con_sap_config->acs_cfg.ht_sec_ch);
1242 return -EINVAL;
1243 }
1244 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1245 * MCC restriction. So free ch list allocated in do_acs
1246 * func for Sec AP and realloc for Pri AP ch list size
1247 */
1248 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252 &con_sap_config->acs_cfg,
1253 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 sizeof(uint8_t) *
1256 con_sap_config->acs_cfg.ch_list_count);
1257 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001258 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 return -ENOMEM;
1260 }
1261
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301262 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 con_sap_config->acs_cfg.ch_list,
1264 con_sap_config->acs_cfg.ch_list_count);
1265
1266 } else {
1267 sap_config->acs_cfg.pri_ch = con_ch;
1268 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1269 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1270 }
1271
1272 return con_ch;
1273}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274
1275/**
1276 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1277 * @sap_cfg: pointer to SAP config struct
1278 *
1279 * This function sets the default ACS start and end channel for the given band
1280 * and also parses the given ACS channel list.
1281 *
1282 * Return: None
1283 */
1284
1285static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1286 bool vht_enabled)
1287{
1288 int i;
1289 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001303 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1304 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 }
1306
1307 if (ht_enabled)
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1309
1310 if (vht_enabled)
1311 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1312
1313
1314 /* Parse ACS Chan list from hostapd */
1315 if (!sap_cfg->acs_cfg.ch_list)
1316 return;
1317
1318 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1319 sap_cfg->acs_cfg.end_ch =
1320 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1321 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301322 /* avoid channel as start channel */
1323 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1324 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001325 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1326 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1327 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1328 }
1329}
1330
1331
1332static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1333
1334/**
1335 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1336 * @adapter: pointer to SAP adapter struct
1337 *
1338 * This function starts the ACS procedure if there are no
1339 * constraints like MBSSID DFS restrictions.
1340 *
1341 * Return: Status of ACS Start procedure
1342 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301343int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344{
1345
1346 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1347 tsap_Config_t *sap_config;
1348 tpWLAN_SAPEventCB acs_event_callback;
1349 int status;
1350
1351 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301352 if (hdd_ctx->acs_policy.acs_channel)
1353 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1354 else
1355 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356
1357 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001358 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001360
1361 if (status > 0) {
1362 /*notify hostapd about channel override */
1363 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1364 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1365 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 }
Jeff Johnson68755312017-02-10 11:46:55 -08001367
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1369 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001370 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 return -EINVAL;
1372 }
1373
1374 acs_event_callback = hdd_hostapd_sap_event_cb;
1375
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301376 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301377 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301378 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 acs_event_callback, sap_config, adapter->dev);
1382
1383
1384 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001385 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 return -EINVAL;
1387 }
bings394afdd2017-01-09 11:22:38 +08001388 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1389 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1391
1392 return 0;
1393}
1394
1395/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301396 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1397 * @ap_adapter: AP adapter
1398 * @nol: Non-occupancy list
1399 * @nol_len: Length of NOL
1400 *
1401 * Get the NOL for SAP
1402 *
1403 * Return: Zero on success, non-zero on failure
1404 */
1405static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1406 uint32_t *nol_len)
1407{
1408 QDF_STATUS ret;
1409
1410 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1411 nol, nol_len);
1412 if (QDF_IS_STATUS_ERROR(ret))
1413 return -EINVAL;
1414
1415 return 0;
1416}
1417
1418/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301419 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1420 * @hdd_ctx: hdd context
1421 * @acs_chan_params: external acs channel params
1422 * @sap_config: SAP config
1423 *
1424 * This API provides unsorted pcl list.
1425 * this list is a subset of the valid channel list given by hostapd.
1426 * if channel is not present in pcl, weightage will be given as zero
1427 *
1428 * Return: Zero on success, non-zero on failure
1429 */
1430static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1431 struct hdd_vendor_acs_chan_params *acs_chan_params,
1432 tsap_Config_t *sap_config)
1433{
1434 int i, j;
1435
1436 for (i = 0; i < acs_chan_params->channel_count; i++) {
1437 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1438 if (acs_chan_params->channel_list[i] ==
1439 sap_config->acs_cfg.pcl_channels[j]) {
1440 acs_chan_params->vendor_pcl_list[i] =
1441 sap_config->acs_cfg.pcl_channels[j];
1442 acs_chan_params->vendor_weight_list[i] =
1443 sap_config->acs_cfg.
1444 pcl_channels_weight_list[j];
1445 break;
1446 } else {
1447 acs_chan_params->vendor_pcl_list[i] =
1448 acs_chan_params->channel_list[i];
1449 acs_chan_params->vendor_weight_list[i] = 0;
1450 }
1451 }
1452 }
1453 if (hdd_ctx->unsafe_channel_count == 0)
1454 return;
1455 /* Update unsafe channel weight as zero */
1456 for (i = 0; i < acs_chan_params->channel_count; i++) {
1457 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1458 if (acs_chan_params->channel_list[i] ==
1459 hdd_ctx->unsafe_channel_list[j]) {
1460 acs_chan_params->vendor_weight_list[i] = 0;
1461 }
1462 }
1463 }
1464}
1465
1466/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301467 * hdd_update_reg_chan_info : This API contructs channel info
1468 * for all the given channel
1469 * @adapter: pointer to SAP adapter struct
1470 * @channel_count: channel count
1471 * @channel_list: channel list
1472 *
1473 * Return: Status of of channel information updation
1474 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301475static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301476 uint32_t channel_count,
1477 uint8_t *channel_list)
1478{
1479 int i;
1480 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301481 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301482 uint8_t bw_offset = 0, chan = 0;
1483 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1484 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1485
1486 /* memory allocation */
1487 sap_config->channel_info = qdf_mem_malloc(
1488 sizeof(struct hdd_channel_info) *
1489 channel_count);
1490 if (!sap_config->channel_info) {
1491 hdd_err("memory allocation failed");
1492 return -ENOMEM;
1493
1494 }
1495 for (i = 0; i < channel_count; i++) {
1496 icv = &sap_config->channel_info[i];
1497 chan = channel_list[i];
1498
1499 if (chan == 0)
1500 continue;
1501
1502 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1503 bw_offset = 1 << BW_40_OFFSET_BIT;
1504 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1505 bw_offset = 1 << BW_20_OFFSET_BIT;
1506 icv->freq = cds_get_channel_freq(chan);
1507 icv->ieee_chan_number = chan;
1508 icv->max_reg_power = cds_get_channel_reg_power(chan);
1509
1510 /* filling demo values */
1511 icv->max_radio_power = HDD_MAX_TX_POWER;
1512 icv->min_radio_power = HDD_MIN_TX_POWER;
1513 /* not supported in current driver */
1514 icv->max_antenna_gain = 0;
1515
1516 icv->reg_class_id = wlan_hdd_find_opclass(
1517 WLAN_HDD_GET_HAL_CTX(adapter),
1518 chan, bw_offset);
1519
1520 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1521 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1522 cds_set_channel_params(chan, 0, &ch_params);
1523 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1524 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1525 }
1526 icv->flags = 0;
1527 icv->flags = cds_get_vendor_reg_flags(chan,
1528 sap_config->acs_cfg.ch_width,
1529 sap_config->acs_cfg.is_ht_enabled,
1530 sap_config->acs_cfg.is_vht_enabled,
1531 hdd_ctx->config->enable_sub_20_channel_width);
1532
1533 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1534 icv->freq, icv->flags,
1535 icv->flagext, icv->ieee_chan_number,
1536 icv->max_reg_power, icv->max_radio_power,
1537 icv->min_radio_power, icv->reg_class_id,
1538 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1539 icv->vht_center_freq_seg1);
1540 }
1541 return 0;
1542}
1543
1544/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1545#define CHAN_INFO_ATTR_FLAGS \
1546 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1547#define CHAN_INFO_ATTR_FLAG_EXT \
1548 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1549#define CHAN_INFO_ATTR_FREQ \
1550 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1551#define CHAN_INFO_ATTR_MAX_REG_POWER \
1552 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1553#define CHAN_INFO_ATTR_MAX_POWER \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1555#define CHAN_INFO_ATTR_MIN_POWER \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1557#define CHAN_INFO_ATTR_REG_CLASS_ID \
1558 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1559#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1560 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1561#define CHAN_INFO_ATTR_VHT_SEG_0 \
1562 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1563#define CHAN_INFO_ATTR_VHT_SEG_1 \
1564 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1565
1566/**
1567 * hdd_cfg80211_update_channel_info() - add channel info attributes
1568 * @skb: pointer to sk buff
1569 * @hdd_ctx: pointer to hdd station context
1570 * @idx: attribute index
1571 *
1572 * Return: Success(0) or reason code for failure
1573 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301574static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301575hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1576 tsap_Config_t *sap_config, int idx)
1577{
1578 struct nlattr *nla_attr, *channel;
1579 struct hdd_channel_info *icv;
1580 int i;
1581
1582 nla_attr = nla_nest_start(skb, idx);
1583 if (!nla_attr)
1584 goto fail;
1585
1586 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1587 channel = nla_nest_start(skb, i);
1588 if (!channel)
1589 goto fail;
1590
1591 icv = &sap_config->channel_info[i];
1592 if (!icv) {
1593 hdd_err("channel info not found");
1594 goto fail;
1595 }
1596 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1597 icv->freq) ||
1598 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1599 icv->flags) ||
1600 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1601 icv->flagext) ||
1602 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1603 icv->max_reg_power) ||
1604 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1605 icv->max_radio_power) ||
1606 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1607 icv->min_radio_power) ||
1608 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1609 icv->reg_class_id) ||
1610 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1611 icv->max_antenna_gain) ||
1612 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1613 icv->vht_center_freq_seg0) ||
1614 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1615 icv->vht_center_freq_seg1)) {
1616 hdd_err("put fail");
1617 goto fail;
1618 }
1619 nla_nest_end(skb, channel);
1620 }
1621 nla_nest_end(skb, nla_attr);
1622 return 0;
1623fail:
1624 hdd_err("nl channel update failed");
1625 return -EINVAL;
1626}
1627#undef CHAN_INFO_ATTR_FLAGS
1628#undef CHAN_INFO_ATTR_FLAG_EXT
1629#undef CHAN_INFO_ATTR_FREQ
1630#undef CHAN_INFO_ATTR_MAX_REG_POWER
1631#undef CHAN_INFO_ATTR_MAX_POWER
1632#undef CHAN_INFO_ATTR_MIN_POWER
1633#undef CHAN_INFO_ATTR_REG_CLASS_ID
1634#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1635#undef CHAN_INFO_ATTR_VHT_SEG_0
1636#undef CHAN_INFO_ATTR_VHT_SEG_1
1637
1638/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301639 * hdd_cfg80211_update_pcl() - add pcl info attributes
1640 * @skb: pointer to sk buff
1641 * @hdd_ctx: pointer to hdd station context
1642 * @idx: attribute index
1643 * @vendor_pcl_list: PCL list
1644 * @vendor_weight_list: PCL weights
1645 *
1646 * Return: Success(0) or reason code for failure
1647 */
1648static int32_t
1649hdd_cfg80211_update_pcl(struct sk_buff *skb,
1650 uint8_t ch_list_count, int idx,
1651 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1652{
1653 struct nlattr *nla_attr, *channel;
1654 int i;
1655
1656 nla_attr = nla_nest_start(skb, idx);
1657
1658 if (!nla_attr)
1659 goto fail;
1660
1661 for (i = 0; i < ch_list_count; i++) {
1662 channel = nla_nest_start(skb, i);
1663 if (!channel)
1664 goto fail;
1665 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1666 vendor_pcl_list[i]) ||
1667 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1668 vendor_weight_list[i])) {
1669 hdd_err("put fail");
1670 goto fail;
1671 }
1672 nla_nest_end(skb, channel);
1673 }
1674 nla_nest_end(skb, nla_attr);
1675
1676 return 0;
1677fail:
1678 hdd_err("updating pcl list failed");
1679 return -EINVAL;
1680}
1681
1682static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1683{
1684 /* Get scan band */
1685 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1686 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1687 *band = eCSR_BAND_24;
1688 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1689 *band = eCSR_BAND_5G;
1690 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1691 *band = eCSR_BAND_ALL;
1692 }
1693 /* Auto is not supported currently */
1694 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1695 hdd_err("invalid band");
1696 *band = eCSR_BAND_24;
1697 }
1698}
1699
1700void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1701 uint8_t reason)
1702{
1703 struct sk_buff *skb;
1704 tsap_Config_t *sap_config;
1705 uint32_t channel_count = 0, status;
1706 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1707 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1708 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1709 struct hdd_vendor_acs_chan_params acs_chan_params;
1710 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1711 eCsrBand band = eCSR_BAND_24;
1712 eCsrPhyMode phy_mode;
1713
1714 if (!hdd_ctx) {
1715 hdd_err("HDD context is NULL");
1716 return;
1717 }
1718
1719 ENTER();
1720 sap_config = &adapter->sessionCtx.ap.sapConfig;
1721
1722 /* Get valid channels for SAP */
1723 wlan_hdd_sap_get_valid_channellist(adapter,
1724 &channel_count, channel_list);
1725
1726 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1727 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1728 /* Get phymode */
1729 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1730
1731 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1732 &(adapter->wdev),
1733 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1734 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1735 GFP_KERNEL);
1736
1737 if (!skb) {
1738 hdd_err("cfg80211_vendor_event_alloc failed");
1739 return;
1740 }
1741 /*
1742 * Application expects pcl to be a subset of channel list
1743 * Remove all channels which are not in channel list from pcl
1744 * and add weight as zero
1745 */
1746 acs_chan_params.channel_count = channel_count;
1747 acs_chan_params.channel_list = channel_list;
1748 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1749 acs_chan_params.vendor_weight_list = vendor_weight_list;
1750
1751 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1752 sap_config);
1753 /* Update values in NL buffer */
1754 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1755 reason) ||
1756 nla_put_u8(skb,
1757 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1758 false) ||
1759 nla_put_u8(skb,
1760 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1761 true) ||
1762 nla_put_u8(skb,
1763 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1764 true) ||
1765 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1766 sap_config->acs_cfg.ch_width) ||
1767 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1768 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1769 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1770 band) ||
1771 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1772 phy_mode) ||
1773 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1774 channel_count, channel_list)) {
1775 hdd_err("nla put fail");
1776 goto fail;
1777 }
1778 status = hdd_cfg80211_update_pcl(skb, channel_count,
1779 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1780 vendor_pcl_list, vendor_weight_list);
1781
1782 if (status != 0)
1783 goto fail;
1784
1785 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1786 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1787
1788 if (status != 0)
1789 goto fail;
1790
1791 cfg80211_vendor_event(skb, GFP_KERNEL);
1792 return;
1793fail:
1794 if (skb)
1795 kfree_skb(skb);
1796}
1797
1798static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1799{
1800 struct hdd_external_acs_timer_context *timer_context;
1801
1802 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1803 return 0;
1804
1805 hdd_notice("Starting vendor app based ACS");
1806 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1807 timer_context->adapter = adapter;
1808
1809 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1810 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1811 QDF_TIMER_TYPE_SW,
1812 hdd_acs_response_timeout_handler, timer_context);
1813 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1814 return 0;
1815}
1816
1817/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1819 * @wiphy: Linux wiphy struct pointer
1820 * @wdev: Linux wireless device struct pointer
1821 * @data: ACS information from hostapd
1822 * @data_len: ACS information length
1823 *
1824 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1825 * and starts ACS procedure.
1826 *
1827 * Return: ACS procedure start status
1828 */
1829
1830static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1831 struct wireless_dev *wdev,
1832 const void *data, int data_len)
1833{
1834 struct net_device *ndev = wdev->netdev;
1835 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1836 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1837 tsap_Config_t *sap_config;
1838 struct sk_buff *temp_skbuff;
1839 int status = -EINVAL, i = 0;
1840 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1841 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301842 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843
1844 /* ***Note*** Donot set SME config related to ACS operation here because
1845 * ACS operation is not synchronouse and ACS for Second AP may come when
1846 * ACS operation for first AP is going on. So only do_acs is split to
1847 * seperate start_acs routine. Also SME-PMAC struct that is used to
1848 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1849 * config shall be set only from start_acs.
1850 */
1851
1852 /* nla_policy Policy template. Policy not applied as some attributes are
1853 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1854 *
1855 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1856 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1857 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1858 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1859 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1860 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1861 */
1862
Jeff Johnson1f61b612016-02-12 16:28:33 -08001863 ENTER_DEV(ndev);
1864
Anurag Chouhan6d760662016-02-20 16:05:43 +05301865 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866 hdd_err("Command not allowed in FTM mode");
1867 return -EPERM;
1868 }
1869
Kapil Gupta8878ad92017-02-13 11:56:04 +05301870 if (hdd_ctx->config->force_sap_acs &&
1871 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001872 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 return -EPERM;
1874 }
1875
1876 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301877 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301879
Naveen Rawat64e477e2016-05-20 10:34:56 -07001880 if (cds_is_sub_20_mhz_enabled()) {
1881 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1882 status = -EINVAL;
1883 goto out;
1884 }
1885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301887 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888
1889 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1890 NULL);
1891 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001892 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893 goto out;
1894 }
1895
1896 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001897 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 goto out;
1899 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301900 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1901 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902
1903 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1904 ht_enabled =
1905 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1906 else
1907 ht_enabled = 0;
1908
1909 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1910 ht40_enabled =
1911 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1912 else
1913 ht40_enabled = 0;
1914
1915 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1916 vht_enabled =
1917 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1918 else
1919 vht_enabled = 0;
1920
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301921 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1922 vht_enabled = 0;
1923 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1924 }
1925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1927 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1928 } else {
1929 if (ht_enabled && ht40_enabled)
1930 ch_width = 40;
1931 else
1932 ch_width = 20;
1933 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301934
1935 /* this may be possible, when sap_force_11n_for_11ac is set */
1936 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1937 if (ht_enabled && ht40_enabled)
1938 ch_width = 40;
1939 else
1940 ch_width = 20;
1941 }
1942
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 if (ch_width == 80)
1944 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1945 else if (ch_width == 40)
1946 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1947 else
1948 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1949
1950 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1951 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1952 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1953 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1954 * since it contains the frequency values of the channels in
1955 * the channel list.
1956 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1957 * is present
1958 */
1959 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1960 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1961 sap_config->acs_cfg.ch_list_count = nla_len(
1962 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1963 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301964 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 sizeof(uint8_t) *
1966 sap_config->acs_cfg.ch_list_count);
1967 if (sap_config->acs_cfg.ch_list == NULL)
1968 goto out;
1969
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301970 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 sap_config->acs_cfg.ch_list_count);
1972 }
1973 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1974 uint32_t *freq =
1975 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1976 sap_config->acs_cfg.ch_list_count = nla_len(
1977 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1978 sizeof(uint32_t);
1979 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301980 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 sap_config->acs_cfg.ch_list_count);
1982 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001983 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 status = -ENOMEM;
1985 goto out;
1986 }
1987
1988 /* convert frequency to channel */
1989 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1990 sap_config->acs_cfg.ch_list[i] =
1991 ieee80211_frequency_to_channel(freq[i]);
1992 }
1993 }
1994
1995 hdd_debug("get pcl for DO_ACS vendor command");
1996
1997 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001998 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301999 sap_config->acs_cfg.pcl_channels,
2000 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302001 sap_config->acs_cfg.pcl_channels_weight_list,
2002 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302003 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002004 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302007 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2008 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07002009 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 vht_enabled = 1;
2011 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2012 sap_config->acs_cfg.ch_width =
2013 hdd_ctx->config->vhtChannelWidth;
2014 /* No VHT80 in 2.4G so perform ACS accordingly */
2015 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302016 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302018 ch_width = 40;
2019 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 }
2021
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302022 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2023
Jeff Johnson020db452016-06-29 14:37:26 -07002024 hdd_notice("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2026 ch_width, ht_enabled, vht_enabled,
2027 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2028
Kapil Gupta8878ad92017-02-13 11:56:04 +05302029 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2030 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07002033 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 sap_config->acs_cfg.ch_list_count);
2035 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07002036 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 }
2038 sap_config->acs_cfg.acs_mode = true;
2039 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002040 /* ***Note*** Completion variable usage is not allowed
2041 * here since ACS scan operation may take max 2.2 sec
2042 * for 5G band:
2043 * 9 Active channel X 40 ms active scan time +
2044 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2046 * for this long. So we split up the scanning part.
2047 */
2048 set_bit(ACS_PENDING, &adapter->event_flags);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302049 hdd_notice("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 status = 0;
2051 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302052 /* Check if vendor specific acs is enabled */
2053 if (hdd_ctx->config->vendor_acs_support) {
2054 sap_config->acs_cfg.hw_mode = hw_mode;
2055 hdd_create_acs_timer(adapter);
2056 hdd_update_acs_timer_reason(adapter,
2057 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2058 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2059 wlan_sap_set_vendor_acs(
2060 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2061 true);
2062 else
2063 wlan_sap_set_vendor_acs(
2064 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2065 false);
2066
2067 } else
2068 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002069 }
2070
2071out:
2072 if (0 == status) {
2073 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2074 NLMSG_HDRLEN);
2075 if (temp_skbuff != NULL)
2076 return cfg80211_vendor_cmd_reply(temp_skbuff);
2077 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002078 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2080
2081 return status;
2082}
2083
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002084/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2086 * @wiphy: Linux wiphy struct pointer
2087 * @wdev: Linux wireless device struct pointer
2088 * @data: ACS information from hostapd
2089 * @data_len: ACS information len
2090 *
2091 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2092 * and starts ACS procedure.
2093 *
2094 * Return: ACS procedure start status
2095 */
2096
2097static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2098 struct wireless_dev *wdev,
2099 const void *data, int data_len)
2100{
2101 int ret;
2102
2103 cds_ssr_protect(__func__);
2104 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2105 cds_ssr_unprotect(__func__);
2106
2107 return ret;
2108}
2109
2110/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002111 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2112 * @adapter: Pointer to adapter struct
2113 *
2114 * This function handle cleanup of what was done in DO_ACS, including free
2115 * memory.
2116 *
2117 * Return: void
2118 */
2119
2120void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2121{
2122 if (adapter == NULL)
2123 return;
2124 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2125 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2126 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2127 }
2128}
2129
2130/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2132 * @work: Linux workqueue struct pointer for ACS work
2133 *
2134 * This function starts the ACS procedure which was marked pending when an ACS
2135 * procedure was in progress for a concurrent SAP interface.
2136 *
2137 * Return: None
2138 */
2139
2140static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2141{
2142 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2143 acs_pending_work.work);
2144 wlan_hdd_cfg80211_start_acs(adapter);
2145}
2146
2147/**
2148 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2149 * @adapter: Pointer to SAP adapter struct
2150 * @pri_channel: SAP ACS procedure selected Primary channel
2151 * @sec_channel: SAP ACS procedure selected secondary channel
2152 *
2153 * This is a callback function from SAP module on ACS procedure is completed.
2154 * This function send the ACS selected channel information to hostapd
2155 *
2156 * Return: None
2157 */
2158
2159void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2160{
2161 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2162 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2163 struct sk_buff *vendor_event;
2164 int ret_val;
2165 hdd_adapter_t *con_sap_adapter;
2166 uint16_t ch_width;
2167
2168 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002169 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2171 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2172 GFP_KERNEL);
2173
2174 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002175 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 return;
2177 }
2178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 ret_val = nla_put_u8(vendor_event,
2180 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2181 sap_cfg->acs_cfg.pri_ch);
2182 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002183 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 kfree_skb(vendor_event);
2185 return;
2186 }
2187
2188 ret_val = nla_put_u8(vendor_event,
2189 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2190 sap_cfg->acs_cfg.ht_sec_ch);
2191 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002192 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 kfree_skb(vendor_event);
2194 return;
2195 }
2196
2197 ret_val = nla_put_u8(vendor_event,
2198 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2199 sap_cfg->acs_cfg.vht_seg0_center_ch);
2200 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002201 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 kfree_skb(vendor_event);
2203 return;
2204 }
2205
2206 ret_val = nla_put_u8(vendor_event,
2207 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2208 sap_cfg->acs_cfg.vht_seg1_center_ch);
2209 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002210 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002211 kfree_skb(vendor_event);
2212 return;
2213 }
2214
2215 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2216 ch_width = 80;
2217 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2218 ch_width = 40;
2219 else
2220 ch_width = 20;
2221
2222 ret_val = nla_put_u16(vendor_event,
2223 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2224 ch_width);
2225 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002226 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 kfree_skb(vendor_event);
2228 return;
2229 }
2230 if (sap_cfg->acs_cfg.pri_ch > 14)
2231 ret_val = nla_put_u8(vendor_event,
2232 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2233 QCA_ACS_MODE_IEEE80211A);
2234 else
2235 ret_val = nla_put_u8(vendor_event,
2236 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2237 QCA_ACS_MODE_IEEE80211G);
2238
2239 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002240 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 kfree_skb(vendor_event);
2242 return;
2243 }
2244
Jeff Johnson46b40792016-06-29 14:03:14 -07002245 hdd_notice("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2247 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2248 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2249
2250 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2251 /* ***Note*** As already mentioned Completion variable usage is not
2252 * allowed here since ACS scan operation may take max 2.2 sec.
2253 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2254 * operation.
2255 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2256 * when Primary AP ACS is complete and secondary AP ACS is started here
2257 * immediately, Primary AP start_bss may come inbetween ACS operation
2258 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2259 * delay. This path and below constraint will be removed on sessionizing
2260 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2261 * As per design constraint user space control application must take
2262 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2263 * this code path. Sec AP hostapd should be started after Primary AP
2264 * start beaconing which can be confirmed by getchannel iwpriv command
2265 */
2266
2267 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2268 if (con_sap_adapter &&
2269 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2271 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 /* Lets give 500ms for OBSS + START_BSS to complete */
2273 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2274 msecs_to_jiffies(500));
2275 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2276 }
2277
2278 return;
2279}
2280
2281static int
2282__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2283 struct wireless_dev *wdev,
2284 const void *data,
2285 int data_len)
2286{
2287 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2288 struct sk_buff *skb = NULL;
2289 uint32_t fset = 0;
2290 int ret;
2291
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002292 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302293
Anurag Chouhan6d760662016-02-20 16:05:43 +05302294 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295 hdd_err("Command not allowed in FTM mode");
2296 return -EPERM;
2297 }
2298
2299 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302300 if (ret)
2301 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302
2303 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002304 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002305 fset |= WIFI_FEATURE_INFRA;
2306 }
2307 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002308 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309 fset |= WIFI_FEATURE_INFRA_5G;
2310 }
2311#ifdef WLAN_FEATURE_P2P
2312 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2313 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002314 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 fset |= WIFI_FEATURE_P2P;
2316 }
2317#endif
2318 fset |= WIFI_FEATURE_SOFT_AP;
2319
2320 /* HOTSPOT is a supplicant feature, enable it by default */
2321 fset |= WIFI_FEATURE_HOTSPOT;
2322
2323#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302324 if (pHddCtx->config->extscan_enabled &&
2325 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002326 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2328 }
2329#endif
2330 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002331 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 fset |= WIFI_FEATURE_NAN;
2333 }
2334 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002335 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 fset |= WIFI_FEATURE_D2D_RTT;
2337 fset |= WIFI_FEATURE_D2AP_RTT;
2338 }
2339#ifdef FEATURE_WLAN_SCAN_PNO
2340 if (pHddCtx->config->configPNOScanSupport &&
2341 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002342 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 fset |= WIFI_FEATURE_PNO;
2344 }
2345#endif
2346 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2347#ifdef FEATURE_WLAN_TDLS
2348 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2349 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002350 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 fset |= WIFI_FEATURE_TDLS;
2352 }
2353 if (sme_is_feature_supported_by_fw(TDLS) &&
2354 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2355 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002356 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2358 }
2359#endif
2360#ifdef WLAN_AP_STA_CONCURRENCY
2361 fset |= WIFI_FEATURE_AP_STA;
2362#endif
2363 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002364 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365
2366 if (hdd_link_layer_stats_supported())
2367 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2368
2369 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2370 NLMSG_HDRLEN);
2371 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002372 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 return -EINVAL;
2374 }
Jeff Johnson020db452016-06-29 14:37:26 -07002375 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 goto nla_put_failure;
2379 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302380 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302381 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382nla_put_failure:
2383 kfree_skb(skb);
2384 return -EINVAL;
2385}
2386
2387/**
2388 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2389 * @wiphy: pointer to wireless wiphy structure.
2390 * @wdev: pointer to wireless_dev structure.
2391 * @data: Pointer to the data to be passed via vendor interface
2392 * @data_len:Length of the data to be passed
2393 *
2394 * Return: Return the Success or Failure code.
2395 */
2396static int
2397wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2398 struct wireless_dev *wdev,
2399 const void *data, int data_len)
2400{
2401 int ret = 0;
2402
2403 cds_ssr_protect(__func__);
2404 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2405 data, data_len);
2406 cds_ssr_unprotect(__func__);
2407
2408 return ret;
2409}
2410
2411/**
2412 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2413 * @wiphy: pointer to wireless wiphy structure.
2414 * @wdev: pointer to wireless_dev structure.
2415 * @data: Pointer to the data to be passed via vendor interface
2416 * @data_len:Length of the data to be passed
2417 *
2418 * Set the MAC address that is to be used for scanning.
2419 *
2420 * Return: Return the Success or Failure code.
2421 */
2422static int
2423__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2424 struct wireless_dev *wdev,
2425 const void *data,
2426 int data_len)
2427{
2428 tpSirScanMacOui pReqMsg = NULL;
2429 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2430 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302431 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002432 int ret;
2433
Jeff Johnson1f61b612016-02-12 16:28:33 -08002434 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435
Anurag Chouhan6d760662016-02-20 16:05:43 +05302436 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 hdd_err("Command not allowed in FTM mode");
2438 return -EPERM;
2439 }
2440
2441 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302442 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444
2445 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002446 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 return -ENOTSUPP;
2448 }
2449
2450 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2451 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002452 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 return -EINVAL;
2454 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302455 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 return -ENOMEM;
2459 }
2460 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002461 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462 goto fail;
2463 }
2464 nla_memcpy(&pReqMsg->oui[0],
2465 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2466 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002467 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 pReqMsg->oui[1], pReqMsg->oui[2]);
2469 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302470 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002471 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 goto fail;
2473 }
2474 return 0;
2475fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302476 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 return -EINVAL;
2478}
2479
2480/**
2481 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2482 * @wiphy: pointer to wireless wiphy structure.
2483 * @wdev: pointer to wireless_dev structure.
2484 * @data: Pointer to the data to be passed via vendor interface
2485 * @data_len:Length of the data to be passed
2486 *
2487 * Set the MAC address that is to be used for scanning. This is an
2488 * SSR-protecting wrapper function.
2489 *
2490 * Return: Return the Success or Failure code.
2491 */
2492static int
2493wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2494 struct wireless_dev *wdev,
2495 const void *data,
2496 int data_len)
2497{
2498 int ret;
2499
2500 cds_ssr_protect(__func__);
2501 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2502 data, data_len);
2503 cds_ssr_unprotect(__func__);
2504
2505 return ret;
2506}
2507
2508/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302509 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2510 * @wiphy: pointer phy adapter
2511 * @wdev: pointer to wireless device structure
2512 * @data: pointer to data buffer
2513 * @data_len: length of data
2514 *
2515 * This routine will give concurrency matrix
2516 *
2517 * Return: int status code
2518 */
2519static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2520 struct wireless_dev *wdev,
2521 const void *data,
2522 int data_len)
2523{
2524 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2525 uint8_t i, feature_sets, max_feature_sets;
2526 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2527 struct sk_buff *reply_skb;
2528 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2529 int ret;
2530
2531 ENTER_DEV(wdev->netdev);
2532
2533 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2534 hdd_err("Command not allowed in FTM mode");
2535 return -EPERM;
2536 }
2537
2538 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302539 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302540 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302541
2542 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2543 data, data_len, NULL)) {
2544 hdd_err("Invalid ATTR");
2545 return -EINVAL;
2546 }
2547
2548 /* Parse and fetch max feature set */
2549 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2550 hdd_err("Attr max feature set size failed");
2551 return -EINVAL;
2552 }
2553 max_feature_sets = nla_get_u32(tb[
2554 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2555 hdd_info("Max feature set size: %d", max_feature_sets);
2556
2557 /* Fill feature combination matrix */
2558 feature_sets = 0;
2559 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002560 WIFI_FEATURE_P2P;
2561 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2562 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302563 /* Add more feature combinations here */
2564
2565 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002566 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302567 hdd_info("Feature set matrix");
2568 for (i = 0; i < feature_sets; i++)
2569 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2570
2571 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2572 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2573 if (!reply_skb) {
2574 hdd_err("Feature set matrix: buffer alloc fail");
2575 return -ENOMEM;
2576 }
2577
2578 if (nla_put_u32(reply_skb,
2579 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2580 feature_sets) ||
2581 nla_put(reply_skb,
2582 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2583 sizeof(u32) * feature_sets,
2584 feature_set_matrix)) {
2585 hdd_err("nla put fail");
2586 kfree_skb(reply_skb);
2587 return -EINVAL;
2588 }
2589 return cfg80211_vendor_cmd_reply(reply_skb);
2590}
2591
2592/**
2593 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2594 * @wiphy: pointer to wireless wiphy structure.
2595 * @wdev: pointer to wireless_dev structure.
2596 * @data: Pointer to the data to be passed via vendor interface
2597 * @data_len:Length of the data to be passed
2598 *
2599 * Retrieves the concurrency feature set matrix
2600 *
2601 * Return: 0 on success, negative errno on failure
2602 */
2603static int
2604wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2605 struct wireless_dev *wdev,
2606 const void *data,
2607 int data_len)
2608{
2609 int ret;
2610
2611 cds_ssr_protect(__func__);
2612 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2613 data, data_len);
2614 cds_ssr_unprotect(__func__);
2615
2616 return ret;
2617}
2618
2619/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2621 * @feature_flags: pointer to the byte array of features.
2622 * @feature: Feature to be turned ON in the byte array.
2623 *
2624 * Return: None
2625 *
2626 * This is called to turn ON or SET the feature flag for the requested feature.
2627 **/
2628#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002629static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2630 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631{
2632 uint32_t index;
2633 uint8_t bit_mask;
2634
2635 index = feature / NUM_BITS_IN_BYTE;
2636 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2637 feature_flags[index] |= bit_mask;
2638}
2639
2640/**
2641 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2642 * @wiphy: pointer to wireless wiphy structure.
2643 * @wdev: pointer to wireless_dev structure.
2644 * @data: Pointer to the data to be passed via vendor interface
2645 * @data_len:Length of the data to be passed
2646 *
2647 * This is called when wlan driver needs to send supported feature set to
2648 * supplicant upon a request/query from the supplicant.
2649 *
2650 * Return: Return the Success or Failure code.
2651 **/
2652#define MAX_CONCURRENT_CHAN_ON_24G 2
2653#define MAX_CONCURRENT_CHAN_ON_5G 2
2654static int
2655__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2656 struct wireless_dev *wdev,
2657 const void *data, int data_len)
2658{
2659 struct sk_buff *skb = NULL;
2660 uint32_t dbs_capability = 0;
2661 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302662 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 int ret_val;
2664
2665 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2666 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2667
Jeff Johnson1f61b612016-02-12 16:28:33 -08002668 ENTER_DEV(wdev->netdev);
2669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2671 if (ret_val)
2672 return ret_val;
2673
Anurag Chouhan6d760662016-02-20 16:05:43 +05302674 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 hdd_err("Command not allowed in FTM mode");
2676 return -EPERM;
2677 }
2678
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002679 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002680 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 wlan_hdd_cfg80211_set_feature(feature_flags,
2682 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2683 }
2684
2685 wlan_hdd_cfg80211_set_feature(feature_flags,
2686 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2687 if (wma_is_scan_simultaneous_capable())
2688 wlan_hdd_cfg80211_set_feature(feature_flags,
2689 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002690
2691 if (wma_is_p2p_lo_capable())
2692 wlan_hdd_cfg80211_set_feature(feature_flags,
2693 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2694
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2696 NLMSG_HDRLEN);
2697
2698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 return -ENOMEM;
2701 }
2702
2703 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2704 sizeof(feature_flags), feature_flags))
2705 goto nla_put_failure;
2706
2707 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302708 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 if (one_by_one_dbs)
2710 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2711
2712 if (two_by_two_dbs)
2713 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2714
2715 if (!one_by_one_dbs && !two_by_two_dbs)
2716 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2717 } else {
2718 hdd_err("wma_get_dbs_hw_mode failed");
2719 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2720 }
2721
2722 hdd_info("dbs_capability is %d", dbs_capability);
2723
2724 if (nla_put_u32(skb,
2725 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2726 MAX_CONCURRENT_CHAN_ON_24G))
2727 goto nla_put_failure;
2728
2729 if (nla_put_u32(skb,
2730 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2731 MAX_CONCURRENT_CHAN_ON_5G))
2732 goto nla_put_failure;
2733
2734 return cfg80211_vendor_cmd_reply(skb);
2735
2736nla_put_failure:
2737 kfree_skb(skb);
2738 return -EINVAL;
2739}
2740
2741/**
2742 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2743 * @wiphy: pointer to wireless wiphy structure.
2744 * @wdev: pointer to wireless_dev structure.
2745 * @data: Pointer to the data to be passed via vendor interface
2746 * @data_len:Length of the data to be passed
2747 *
2748 * This is called when wlan driver needs to send supported feature set to
2749 * supplicant upon a request/query from the supplicant.
2750 *
2751 * Return: Return the Success or Failure code.
2752 */
2753static int
2754wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2755 struct wireless_dev *wdev,
2756 const void *data, int data_len)
2757{
2758 int ret;
2759
2760 cds_ssr_protect(__func__);
2761 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2762 data, data_len);
2763 cds_ssr_unprotect(__func__);
2764
2765 return ret;
2766}
2767
2768
2769/**
2770 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2771 * @wiphy: The wiphy structure
2772 * @wdev: The wireless device
2773 * @data: Data passed by framework
2774 * @data_len: Parameters to be configured passed as data
2775 *
2776 * The roaming related parameters are configured by the framework
2777 * using this interface.
2778 *
2779 * Return: Return either success or failure code.
2780 */
2781static int
2782__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2783 struct wireless_dev *wdev, const void *data, int data_len)
2784{
2785 struct net_device *dev = wdev->netdev;
2786 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2787 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2788 uint8_t session_id;
2789 struct roam_ext_params roam_params;
2790 uint32_t cmd_type, req_id;
2791 struct nlattr *curr_attr;
2792 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2793 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2794 int rem, i;
2795 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002796 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 int ret;
2798
Jeff Johnson1f61b612016-02-12 16:28:33 -08002799 ENTER_DEV(dev);
2800
Anurag Chouhan6d760662016-02-20 16:05:43 +05302801 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002802 hdd_err("Command not allowed in FTM mode");
2803 return -EPERM;
2804 }
2805
2806 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302807 if (ret)
2808 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809
2810 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2811 data, data_len,
2812 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002813 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 return -EINVAL;
2815 }
2816 /* Parse and fetch Command Type*/
2817 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002818 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 goto fail;
2820 }
2821 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302822 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2824 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002825 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 goto fail;
2827 }
2828 req_id = nla_get_u32(
2829 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002830 hdd_debug("Req Id (%d)", req_id);
2831 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 switch (cmd_type) {
2833 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2834 i = 0;
2835 nla_for_each_nested(curr_attr,
2836 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2837 rem) {
2838 if (nla_parse(tb2,
2839 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2840 nla_data(curr_attr), nla_len(curr_attr),
2841 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002842 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 goto fail;
2844 }
2845 /* Parse and Fetch allowed SSID list*/
2846 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002847 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 goto fail;
2849 }
2850 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2851 /*
2852 * Upper Layers include a null termination character.
2853 * Check for the actual permissible length of SSID and
2854 * also ensure not to copy the NULL termination
2855 * character to the driver buffer.
2856 */
2857 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2858 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2859 nla_memcpy(
2860 roam_params.ssid_allowed_list[i].ssId,
2861 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2862 buf_len - 1);
2863 roam_params.ssid_allowed_list[i].length =
2864 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002865 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866 roam_params.ssid_allowed_list[i].length,
2867 roam_params.ssid_allowed_list[i].ssId,
2868 roam_params.ssid_allowed_list[i].length);
2869 i++;
2870 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002871 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 }
2873 }
2874 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002875 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876 roam_params.num_ssid_allowed_list);
2877 sme_update_roam_params(pHddCtx->hHal, session_id,
2878 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2879 break;
2880 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2881 /* Parse and fetch 5G Boost Threshold */
2882 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002883 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 goto fail;
2885 }
2886 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2887 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002888 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 roam_params.raise_rssi_thresh_5g);
2890 /* Parse and fetch 5G Penalty Threshold */
2891 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002892 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 goto fail;
2894 }
2895 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2896 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002897 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 roam_params.drop_rssi_thresh_5g);
2899 /* Parse and fetch 5G Boost Factor */
2900 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002901 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902 goto fail;
2903 }
2904 roam_params.raise_factor_5g = nla_get_u32(
2905 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002906 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 roam_params.raise_factor_5g);
2908 /* Parse and fetch 5G Penalty factor */
2909 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002910 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 goto fail;
2912 }
2913 roam_params.drop_factor_5g = nla_get_u32(
2914 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002915 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 roam_params.drop_factor_5g);
2917 /* Parse and fetch 5G Max Boost */
2918 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002919 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 goto fail;
2921 }
2922 roam_params.max_raise_rssi_5g = nla_get_u32(
2923 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002924 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 roam_params.max_raise_rssi_5g);
2926 /* Parse and fetch Rssi Diff */
2927 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002928 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 goto fail;
2930 }
2931 roam_params.rssi_diff = nla_get_s32(
2932 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002933 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 roam_params.rssi_diff);
2935 /* Parse and fetch Alert Rssi Threshold */
2936 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002937 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002938 goto fail;
2939 }
2940 roam_params.alert_rssi_threshold = nla_get_u32(
2941 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002942 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 roam_params.alert_rssi_threshold);
2944 sme_update_roam_params(pHddCtx->hHal, session_id,
2945 roam_params,
2946 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2947 break;
2948 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2949 /* Parse and fetch Activate Good Rssi Roam */
2950 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 goto fail;
2953 }
2954 roam_params.good_rssi_roam = nla_get_s32(
2955 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002956 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 roam_params.good_rssi_roam);
2958 sme_update_roam_params(pHddCtx->hHal, session_id,
2959 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2960 break;
2961 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2962 /* Parse and fetch number of preferred BSSID */
2963 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002964 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 goto fail;
2966 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002967 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002969 if (count > MAX_BSSID_FAVORED) {
2970 hdd_err("Preferred BSSID count %u exceeds max %u",
2971 count, MAX_BSSID_FAVORED);
2972 goto fail;
2973 }
2974 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 i = 0;
2976 nla_for_each_nested(curr_attr,
2977 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2978 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002979
2980 if (i == count) {
2981 hdd_warn("Ignoring excess Preferred BSSID");
2982 break;
2983 }
2984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 if (nla_parse(tb2,
2986 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2987 nla_data(curr_attr), nla_len(curr_attr),
2988 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002989 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 goto fail;
2991 }
2992 /* Parse and fetch MAC address */
2993 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002994 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 goto fail;
2996 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002997 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302999 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003000 hdd_debug(MAC_ADDRESS_STR,
3001 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 /* Parse and fetch preference factor*/
3003 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003004 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 goto fail;
3006 }
3007 roam_params.bssid_favored_factor[i] = nla_get_u32(
3008 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003009 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 roam_params.bssid_favored_factor[i]);
3011 i++;
3012 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003013 if (i < count)
3014 hdd_warn("Num Preferred BSSID %u less than expected %u",
3015 i, count);
3016 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 sme_update_roam_params(pHddCtx->hHal, session_id,
3018 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3019 break;
3020 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3021 /* Parse and fetch number of blacklist BSSID */
3022 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003023 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 goto fail;
3025 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003026 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003028 if (count > MAX_BSSID_AVOID_LIST) {
3029 hdd_err("Blacklist BSSID count %u exceeds max %u",
3030 count, MAX_BSSID_AVOID_LIST);
3031 goto fail;
3032 }
3033 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 i = 0;
3035 nla_for_each_nested(curr_attr,
3036 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3037 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003038
3039 if (i == count) {
3040 hdd_warn("Ignoring excess Blacklist BSSID");
3041 break;
3042 }
3043
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044 if (nla_parse(tb2,
3045 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3046 nla_data(curr_attr), nla_len(curr_attr),
3047 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003048 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 goto fail;
3050 }
3051 /* Parse and fetch MAC address */
3052 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003053 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 goto fail;
3055 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003056 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303058 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003059 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003061 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003062 i++;
3063 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003064 if (i < count)
3065 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3066 i, count);
3067 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068 sme_update_roam_params(pHddCtx->hHal, session_id,
3069 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3070 break;
3071 }
3072 return 0;
3073fail:
3074 return -EINVAL;
3075}
3076
3077/**
3078 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3079 * @wiphy: pointer to wireless wiphy structure.
3080 * @wdev: pointer to wireless_dev structure.
3081 * @data: Pointer to the data to be passed via vendor interface
3082 * @data_len:Length of the data to be passed
3083 *
3084 * Return: Return the Success or Failure code.
3085 */
3086static int
3087wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3088 struct wireless_dev *wdev,
3089 const void *data,
3090 int data_len)
3091{
3092 int ret;
3093
3094 cds_ssr_protect(__func__);
3095 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3096 data, data_len);
3097 cds_ssr_unprotect(__func__);
3098
3099 return ret;
3100}
3101
3102static const struct nla_policy
3103wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3104 +1] = {
3105 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3106};
3107
3108/**
3109 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3110 * @hdd_ctx: HDD context
3111 * @device_mode: device mode
3112 * Return: bool
3113 */
3114static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003115 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116{
3117 hdd_adapter_t *adapter;
3118 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3119 hdd_ap_ctx_t *ap_ctx;
3120 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303121 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303123 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 &adapter_node);
3125
3126 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303127 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 adapter = adapter_node->pAdapter;
3129
3130 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003131 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003132 ap_ctx =
3133 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3134
3135 /*
3136 * if there is SAP already running on DFS channel,
3137 * do not disable scan on dfs channels. Note that
3138 * with SAP on DFS, there cannot be conurrency on
3139 * single radio. But then we can have multiple
3140 * radios !!
3141 */
3142 if (CHANNEL_STATE_DFS ==
3143 cds_get_channel_state(
3144 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003145 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 return true;
3147 }
3148 }
3149
3150 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003151 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152 sta_ctx =
3153 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3154
3155 /*
3156 * if STA is already connected on DFS channel,
3157 * do not disable scan on dfs channels
3158 */
3159 if (hdd_conn_is_connected(sta_ctx) &&
3160 (CHANNEL_STATE_DFS ==
3161 cds_get_channel_state(
3162 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003163 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 return true;
3165 }
3166 }
3167
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303168 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169 adapter_node,
3170 &next);
3171 adapter_node = next;
3172 }
3173
3174 return false;
3175}
3176
3177/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003178 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3179 * @hdd_ctx: HDD context within host driver
3180 * @adapter: Adapter pointer
3181 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3182 *
3183 * Loops through devices to see who is operating on DFS channels
3184 * and then disables/enables DFS channels by calling SME API.
3185 * Fails the disable request if any device is active on a DFS channel.
3186 *
3187 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003189
3190int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3191 hdd_adapter_t *adapter,
3192 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303195 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197
3198 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3199 if (no_dfs_flag) {
3200 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003201 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202
3203 if (true == status)
3204 return -EOPNOTSUPP;
3205
3206 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003207 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208
3209 if (true == status)
3210 return -EOPNOTSUPP;
3211 }
3212
3213 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3214
3215 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3216
3217 /*
3218 * call the SME API to tunnel down the new channel list
3219 * to the firmware
3220 */
3221 status = sme_handle_dfs_chan_scan(
3222 h_hal, hdd_ctx->config->enableDFSChnlScan);
3223
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303224 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 ret_val = 0;
3226
3227 /*
3228 * Clear the SME scan cache also. Note that the
3229 * clearing of scan results is independent of session;
3230 * so no need to iterate over
3231 * all sessions
3232 */
3233 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303234 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 ret_val = -EPERM;
3236 }
3237
3238 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003239 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 ret_val = 0;
3241 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003242 return ret_val;
3243}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003245/**
3246 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3247 * @wiphy: corestack handler
3248 * @wdev: wireless device
3249 * @data: data
3250 * @data_len: data length
3251 * Return: success(0) or reason code for failure
3252 */
3253static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3254 struct wireless_dev *wdev,
3255 const void *data,
3256 int data_len)
3257{
3258 struct net_device *dev = wdev->netdev;
3259 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3260 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3262 int ret_val;
3263 uint32_t no_dfs_flag = 0;
3264
Jeff Johnson1f61b612016-02-12 16:28:33 -08003265 ENTER_DEV(dev);
3266
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003267 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303268 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003269 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003270
3271 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3272 data, data_len,
3273 wlan_hdd_set_no_dfs_flag_config_policy)) {
3274 hdd_err("invalid attr");
3275 return -EINVAL;
3276 }
3277
3278 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3279 hdd_err("attr dfs flag failed");
3280 return -EINVAL;
3281 }
3282
3283 no_dfs_flag = nla_get_u32(
3284 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3285
Jeff Johnson020db452016-06-29 14:37:26 -07003286 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003287
3288 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003289 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003290 return -EINVAL;
3291 }
3292
3293 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3294 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 return ret_val;
3296}
3297
3298/**
3299 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3300 *
3301 * @wiphy: wiphy device pointer
3302 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003303 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 * @data_len: Buffer length
3305 *
3306 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3307 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3308 *
3309 * Return: EOK or other error codes.
3310 */
3311
3312static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3313 struct wireless_dev *wdev,
3314 const void *data,
3315 int data_len)
3316{
3317 int ret;
3318
3319 cds_ssr_protect(__func__);
3320 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3321 data, data_len);
3322 cds_ssr_unprotect(__func__);
3323
3324 return ret;
3325}
3326
Manikandan Mohan80dea792016-04-28 16:36:48 -07003327static const struct nla_policy
3328wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3329 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3330};
3331
3332/**
3333 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3334 * @wiphy: wiphy device pointer
3335 * @wdev: wireless device pointer
3336 * @data: Vendor command data buffer
3337 * @data_len: Buffer length
3338 *
3339 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3340 * setup WISA Mode features.
3341 *
3342 * Return: Success(0) or reason code for failure
3343 */
3344static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3345 struct wireless_dev *wdev, const void *data, int data_len)
3346{
3347 struct net_device *dev = wdev->netdev;
3348 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3349 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3350 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3351 struct sir_wisa_params wisa;
3352 int ret_val;
3353 QDF_STATUS status;
3354 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003355 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3356 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003357
3358 ENTER_DEV(dev);
3359 ret_val = wlan_hdd_validate_context(hdd_ctx);
3360 if (ret_val)
3361 goto err;
3362
3363 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3364 hdd_err("Command not allowed in FTM mode");
3365 return -EPERM;
3366 }
3367
3368 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3369 wlan_hdd_wisa_cmd_policy)) {
3370 hdd_err("Invalid WISA cmd attributes");
3371 ret_val = -EINVAL;
3372 goto err;
3373 }
3374 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3375 hdd_err("Invalid WISA mode");
3376 ret_val = -EINVAL;
3377 goto err;
3378 }
3379
3380 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3381 hdd_info("WISA Mode: %d", wisa_mode);
3382 wisa.mode = wisa_mode;
3383 wisa.vdev_id = adapter->sessionId;
3384 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003385 if (!QDF_IS_STATUS_SUCCESS(status)) {
3386 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003387 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003388 }
3389 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003390 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003391 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3392 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003393 adapter->sessionId),
3394 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003395err:
3396 EXIT();
3397 return ret_val;
3398}
3399
3400/**
3401 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3402 * @wiphy: corestack handler
3403 * @wdev: wireless device
3404 * @data: data
3405 * @data_len: data length
3406 *
3407 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3408 * setup WISA mode features.
3409 *
3410 * Return: Success(0) or reason code for failure
3411 */
3412static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3413 struct wireless_dev *wdev,
3414 const void *data,
3415 int data_len)
3416{
3417 int ret;
3418
3419 cds_ssr_protect(__func__);
3420 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3421 cds_ssr_unprotect(__func__);
3422
3423 return ret;
3424}
3425
Anurag Chouhan96919482016-07-13 16:36:57 +05303426/*
3427 * define short names for the global vendor params
3428 * used by __wlan_hdd_cfg80211_get_station_cmd()
3429 */
3430#define STATION_INVALID \
3431 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3432#define STATION_INFO \
3433 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3434#define STATION_ASSOC_FAIL_REASON \
3435 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3436#define STATION_MAX \
3437 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3438
3439static const struct nla_policy
3440hdd_get_station_policy[STATION_MAX + 1] = {
3441 [STATION_INFO] = {.type = NLA_FLAG},
3442 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3443};
3444
3445/**
3446 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3447 * @hdd_ctx: HDD context within host driver
3448 * @wdev: wireless device
3449 *
3450 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3451 * Validate cmd attributes and send the station info to upper layers.
3452 *
3453 * Return: Success(0) or reason code for failure
3454 */
3455static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3456 hdd_adapter_t *adapter)
3457{
3458 struct sk_buff *skb = NULL;
3459 uint32_t nl_buf_len;
3460 hdd_station_ctx_t *hdd_sta_ctx;
3461
3462 nl_buf_len = NLMSG_HDRLEN;
3463 nl_buf_len += sizeof(uint32_t);
3464 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3465
3466 if (!skb) {
3467 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3468 return -ENOMEM;
3469 }
3470
3471 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3472
3473 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3474 hdd_sta_ctx->conn_info.assoc_status_code)) {
3475 hdd_err("put fail");
3476 goto fail;
3477 }
3478 return cfg80211_vendor_cmd_reply(skb);
3479fail:
3480 if (skb)
3481 kfree_skb(skb);
3482 return -EINVAL;
3483}
3484
3485/**
3486 * hdd_map_auth_type() - transform auth type specific to
3487 * vendor command
3488 * @auth_type: csr auth type
3489 *
3490 * Return: Success(0) or reason code for failure
3491 */
3492static int hdd_convert_auth_type(uint32_t auth_type)
3493{
3494 uint32_t ret_val;
3495
3496 switch (auth_type) {
3497 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3498 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3499 break;
3500 case eCSR_AUTH_TYPE_SHARED_KEY:
3501 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3502 break;
3503 case eCSR_AUTH_TYPE_WPA:
3504 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3505 break;
3506 case eCSR_AUTH_TYPE_WPA_PSK:
3507 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3508 break;
3509 case eCSR_AUTH_TYPE_AUTOSWITCH:
3510 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3511 break;
3512 case eCSR_AUTH_TYPE_WPA_NONE:
3513 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3514 break;
3515 case eCSR_AUTH_TYPE_RSN:
3516 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3517 break;
3518 case eCSR_AUTH_TYPE_RSN_PSK:
3519 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3520 break;
3521 case eCSR_AUTH_TYPE_FT_RSN:
3522 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3523 break;
3524 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3525 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3526 break;
3527 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3528 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3529 break;
3530 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3531 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3532 break;
3533 case eCSR_AUTH_TYPE_CCKM_WPA:
3534 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3535 break;
3536 case eCSR_AUTH_TYPE_CCKM_RSN:
3537 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3538 break;
3539 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3540 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3541 break;
3542 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3543 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3544 break;
3545 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3546 case eCSR_AUTH_TYPE_FAILED:
3547 case eCSR_AUTH_TYPE_NONE:
3548 default:
3549 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3550 break;
3551 }
3552 return ret_val;
3553}
3554
3555/**
3556 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3557 * vendor command
3558 * @dot11mode: dot11mode
3559 *
3560 * Return: Success(0) or reason code for failure
3561 */
3562static int hdd_convert_dot11mode(uint32_t dot11mode)
3563{
3564 uint32_t ret_val;
3565
3566 switch (dot11mode) {
3567 case eCSR_CFG_DOT11_MODE_11A:
3568 ret_val = QCA_WLAN_802_11_MODE_11A;
3569 break;
3570 case eCSR_CFG_DOT11_MODE_11B:
3571 ret_val = QCA_WLAN_802_11_MODE_11B;
3572 break;
3573 case eCSR_CFG_DOT11_MODE_11G:
3574 ret_val = QCA_WLAN_802_11_MODE_11G;
3575 break;
3576 case eCSR_CFG_DOT11_MODE_11N:
3577 ret_val = QCA_WLAN_802_11_MODE_11N;
3578 break;
3579 case eCSR_CFG_DOT11_MODE_11AC:
3580 ret_val = QCA_WLAN_802_11_MODE_11AC;
3581 break;
3582 case eCSR_CFG_DOT11_MODE_AUTO:
3583 case eCSR_CFG_DOT11_MODE_ABG:
3584 default:
3585 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3586 }
3587 return ret_val;
3588}
3589
3590/**
3591 * hdd_add_tx_bitrate() - add tx bitrate attribute
3592 * @skb: pointer to sk buff
3593 * @hdd_sta_ctx: pointer to hdd station context
3594 * @idx: attribute index
3595 *
3596 * Return: Success(0) or reason code for failure
3597 */
3598static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3599 hdd_station_ctx_t *hdd_sta_ctx,
3600 int idx)
3601{
3602 struct nlattr *nla_attr;
3603 uint32_t bitrate, bitrate_compat;
3604
3605 nla_attr = nla_nest_start(skb, idx);
3606 if (!nla_attr)
3607 goto fail;
3608 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3609 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3610
3611 /* report 16-bit bitrate only if we can */
3612 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3613 if (bitrate > 0 &&
3614 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3615 hdd_err("put fail");
3616 goto fail;
3617 }
3618 if (bitrate_compat > 0 &&
3619 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3620 hdd_err("put fail");
3621 goto fail;
3622 }
3623 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3624 hdd_sta_ctx->conn_info.txrate.nss)) {
3625 hdd_err("put fail");
3626 goto fail;
3627 }
3628 nla_nest_end(skb, nla_attr);
3629 return 0;
3630fail:
3631 return -EINVAL;
3632}
3633
3634/**
3635 * hdd_add_sta_info() - add station info attribute
3636 * @skb: pointer to sk buff
3637 * @hdd_sta_ctx: pointer to hdd station context
3638 * @idx: attribute index
3639 *
3640 * Return: Success(0) or reason code for failure
3641 */
3642static int32_t hdd_add_sta_info(struct sk_buff *skb,
3643 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3644{
3645 struct nlattr *nla_attr;
3646
3647 nla_attr = nla_nest_start(skb, idx);
3648 if (!nla_attr)
3649 goto fail;
3650 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3651 (hdd_sta_ctx->conn_info.signal + 100))) {
3652 hdd_err("put fail");
3653 goto fail;
3654 }
3655 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3656 goto fail;
3657 nla_nest_end(skb, nla_attr);
3658 return 0;
3659fail:
3660 return -EINVAL;
3661}
3662
3663/**
3664 * hdd_add_survey_info() - add survey info attribute
3665 * @skb: pointer to sk buff
3666 * @hdd_sta_ctx: pointer to hdd station context
3667 * @idx: attribute index
3668 *
3669 * Return: Success(0) or reason code for failure
3670 */
3671static int32_t hdd_add_survey_info(struct sk_buff *skb,
3672 hdd_station_ctx_t *hdd_sta_ctx,
3673 int idx)
3674{
3675 struct nlattr *nla_attr;
3676
3677 nla_attr = nla_nest_start(skb, idx);
3678 if (!nla_attr)
3679 goto fail;
3680 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3681 hdd_sta_ctx->conn_info.freq) ||
3682 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3683 (hdd_sta_ctx->conn_info.noise + 100))) {
3684 hdd_err("put fail");
3685 goto fail;
3686 }
3687 nla_nest_end(skb, nla_attr);
3688 return 0;
3689fail:
3690 return -EINVAL;
3691}
3692
3693/**
3694 * hdd_add_link_standard_info() - add link info attribute
3695 * @skb: pointer to sk buff
3696 * @hdd_sta_ctx: pointer to hdd station context
3697 * @idx: attribute index
3698 *
3699 * Return: Success(0) or reason code for failure
3700 */
3701static int32_t
3702hdd_add_link_standard_info(struct sk_buff *skb,
3703 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3704{
3705 struct nlattr *nla_attr;
3706
3707 nla_attr = nla_nest_start(skb, idx);
3708 if (!nla_attr)
3709 goto fail;
3710 if (nla_put(skb,
3711 NL80211_ATTR_SSID,
3712 hdd_sta_ctx->conn_info.SSID.SSID.length,
3713 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3714 hdd_err("put fail");
3715 goto fail;
3716 }
3717 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3718 goto fail;
3719 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3720 goto fail;
3721 nla_nest_end(skb, nla_attr);
3722 return 0;
3723fail:
3724 return -EINVAL;
3725}
3726
3727/**
3728 * hdd_add_ap_standard_info() - add ap info attribute
3729 * @skb: pointer to sk buff
3730 * @hdd_sta_ctx: pointer to hdd station context
3731 * @idx: attribute index
3732 *
3733 * Return: Success(0) or reason code for failure
3734 */
3735static int32_t
3736hdd_add_ap_standard_info(struct sk_buff *skb,
3737 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3738{
3739 struct nlattr *nla_attr;
3740
3741 nla_attr = nla_nest_start(skb, idx);
3742 if (!nla_attr)
3743 goto fail;
3744 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3745 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3746 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3747 &hdd_sta_ctx->conn_info.vht_caps)) {
3748 hdd_err("put fail");
3749 goto fail;
3750 }
3751 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3752 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3753 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3754 &hdd_sta_ctx->conn_info.ht_caps)) {
3755 hdd_err("put fail");
3756 goto fail;
3757 }
3758 nla_nest_end(skb, nla_attr);
3759 return 0;
3760fail:
3761 return -EINVAL;
3762}
3763
3764/**
3765 * hdd_get_station_info() - send BSS information to supplicant
3766 * @hdd_ctx: pointer to hdd context
3767 * @adapter: pointer to adapter
3768 *
3769 * Return: 0 if success else error status
3770 */
3771static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3772 hdd_adapter_t *adapter)
3773{
3774 struct sk_buff *skb = NULL;
3775 uint8_t *tmp_hs20 = NULL;
3776 uint32_t nl_buf_len;
3777 hdd_station_ctx_t *hdd_sta_ctx;
3778
3779 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3780
3781 nl_buf_len = NLMSG_HDRLEN;
3782 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3783 sizeof(hdd_sta_ctx->conn_info.freq) +
3784 sizeof(hdd_sta_ctx->conn_info.noise) +
3785 sizeof(hdd_sta_ctx->conn_info.signal) +
3786 (sizeof(uint32_t) * 2) +
3787 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3788 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3789 sizeof(hdd_sta_ctx->conn_info.authType) +
3790 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3791 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3792 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3793 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3794 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3795 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3796 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3797 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3798 1);
3799 }
3800 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3801 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3802 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3803 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3804
3805
3806 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3807 if (!skb) {
3808 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3809 return -ENOMEM;
3810 }
3811
3812 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3813 LINK_INFO_STANDARD_NL80211_ATTR)) {
3814 hdd_err("put fail");
3815 goto fail;
3816 }
3817 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3818 AP_INFO_STANDARD_NL80211_ATTR)) {
3819 hdd_err("put fail");
3820 goto fail;
3821 }
3822 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3823 hdd_sta_ctx->conn_info.roam_count) ||
3824 nla_put_u32(skb, INFO_AKM,
3825 hdd_convert_auth_type(
3826 hdd_sta_ctx->conn_info.authType)) ||
3827 nla_put_u32(skb, WLAN802_11_MODE,
3828 hdd_convert_dot11mode(
3829 hdd_sta_ctx->conn_info.dot11Mode))) {
3830 hdd_err("put fail");
3831 goto fail;
3832 }
3833 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3834 if (nla_put(skb, HT_OPERATION,
3835 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3836 &hdd_sta_ctx->conn_info.ht_operation)) {
3837 hdd_err("put fail");
3838 goto fail;
3839 }
3840 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3841 if (nla_put(skb, VHT_OPERATION,
3842 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3843 &hdd_sta_ctx->conn_info.vht_operation)) {
3844 hdd_err("put fail");
3845 goto fail;
3846 }
3847 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3848 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3849 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3850 tmp_hs20 + 1)) {
3851 hdd_err("put fail");
3852 goto fail;
3853 }
3854
3855 return cfg80211_vendor_cmd_reply(skb);
3856fail:
3857 if (skb)
3858 kfree_skb(skb);
3859 return -EINVAL;
3860}
3861
3862/**
3863 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3864 * @wiphy: corestack handler
3865 * @wdev: wireless device
3866 * @data: data
3867 * @data_len: data length
3868 *
3869 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3870 * Validate cmd attributes and send the station info to upper layers.
3871 *
3872 * Return: Success(0) or reason code for failure
3873 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303874static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303875__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3876 struct wireless_dev *wdev,
3877 const void *data,
3878 int data_len)
3879{
3880 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3881 struct net_device *dev = wdev->netdev;
3882 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3883 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3884 int32_t status;
3885
3886 ENTER_DEV(dev);
3887 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3888 hdd_err("Command not allowed in FTM mode");
3889 status = -EPERM;
3890 goto out;
3891 }
3892
3893 status = wlan_hdd_validate_context(hdd_ctx);
3894 if (0 != status)
3895 goto out;
3896
3897
3898 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3899 data, data_len, NULL);
3900 if (status) {
3901 hdd_err("Invalid ATTR");
3902 goto out;
3903 }
3904
3905 /* Parse and fetch Command Type*/
3906 if (tb[STATION_INFO]) {
3907 status = hdd_get_station_info(hdd_ctx, adapter);
3908 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3909 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3910 } else {
3911 hdd_err("get station info cmd type failed");
3912 status = -EINVAL;
3913 goto out;
3914 }
3915 EXIT();
3916out:
3917 return status;
3918}
3919
3920/**
3921 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3922 * @wiphy: corestack handler
3923 * @wdev: wireless device
3924 * @data: data
3925 * @data_len: data length
3926 *
3927 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3928 * Validate cmd attributes and send the station info to upper layers.
3929 *
3930 * Return: Success(0) or reason code for failure
3931 */
3932static int32_t
3933hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3934 struct wireless_dev *wdev,
3935 const void *data,
3936 int data_len)
3937{
3938 int ret;
3939
3940 cds_ssr_protect(__func__);
3941 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3942 cds_ssr_unprotect(__func__);
3943
3944 return ret;
3945}
3946
3947/*
3948 * undef short names defined for get station command
3949 * used by __wlan_hdd_cfg80211_get_station_cmd()
3950 */
3951#undef STATION_INVALID
3952#undef STATION_INFO
3953#undef STATION_ASSOC_FAIL_REASON
3954#undef STATION_MAX
3955
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003956#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3957/**
3958 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3959 * @wiphy: pointer to wireless wiphy structure.
3960 * @wdev: pointer to wireless_dev structure.
3961 * @data: Pointer to the Key data
3962 * @data_len:Length of the data passed
3963 *
3964 * This is called when wlan driver needs to save the keys received via
3965 * vendor specific command.
3966 *
3967 * Return: Return the Success or Failure code.
3968 */
3969static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3970 struct wireless_dev *wdev,
3971 const void *data, int data_len)
3972{
3973 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3974 struct net_device *dev = wdev->netdev;
3975 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3976 hdd_context_t *hdd_ctx_ptr;
3977 int status;
3978
Jeff Johnson1f61b612016-02-12 16:28:33 -08003979 ENTER_DEV(dev);
3980
Anurag Chouhan6d760662016-02-20 16:05:43 +05303981 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982 hdd_err("Command not allowed in FTM mode");
3983 return -EPERM;
3984 }
3985
3986 if ((data == NULL) || (data_len == 0) ||
3987 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003988 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989 return -EINVAL;
3990 }
3991
3992 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3993 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003994 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 return -EINVAL;
3996 }
3997
3998 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303999 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4002 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004003 true,
4004 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304005 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4006 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4008 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4009 return 0;
4010}
4011
4012/**
4013 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4014 * @wiphy: pointer to wireless wiphy structure.
4015 * @wdev: pointer to wireless_dev structure.
4016 * @data: Pointer to the Key data
4017 * @data_len:Length of the data passed
4018 *
4019 * This is called when wlan driver needs to save the keys received via
4020 * vendor specific command.
4021 *
4022 * Return: Return the Success or Failure code.
4023 */
4024static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4025 struct wireless_dev *wdev,
4026 const void *data, int data_len)
4027{
4028 int ret;
4029
4030 cds_ssr_protect(__func__);
4031 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4032 cds_ssr_unprotect(__func__);
4033
4034 return ret;
4035}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004036#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037
4038static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4039 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4040 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4041 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004042 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043};
4044
4045/**
4046 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4047 * @wiphy: pointer to wireless wiphy structure.
4048 * @wdev: pointer to wireless_dev structure.
4049 * @data: Pointer to the data to be passed via vendor interface
4050 * @data_len:Length of the data to be passed
4051 *
4052 * This is called when wlan driver needs to send wifi driver related info
4053 * (driver/fw version) to the user space application upon request.
4054 *
4055 * Return: Return the Success or Failure code.
4056 */
4057static int
4058__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4059 struct wireless_dev *wdev,
4060 const void *data, int data_len)
4061{
4062 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4063 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004064 tSirVersionString driver_version;
4065 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004068 struct sk_buff *reply_skb;
4069 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004070
Jeff Johnson1f61b612016-02-12 16:28:33 -08004071 ENTER_DEV(wdev->netdev);
4072
Anurag Chouhan6d760662016-02-20 16:05:43 +05304073 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004074 hdd_err("Command not allowed in FTM mode");
4075 return -EPERM;
4076 }
4077
4078 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304079 if (status)
4080 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081
4082 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4083 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004084 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004085 return -EINVAL;
4086 }
4087
4088 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004089 hdd_err("Rcvd req for Driver version");
4090 strlcpy(driver_version, QWLAN_VERSIONSTR,
4091 sizeof(driver_version));
4092 skb_len += strlen(driver_version) + 1;
4093 count++;
4094 }
4095
4096 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4097 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4099 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004100 snprintf(firmware_version, sizeof(firmware_version),
4101 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4102 skb_len += strlen(firmware_version) + 1;
4103 count++;
4104 }
4105
4106 if (count == 0) {
4107 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 return -EINVAL;
4109 }
4110
Ryan Hsu7ac88852016-04-28 10:20:34 -07004111 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4112 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004115 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 return -ENOMEM;
4117 }
4118
Ryan Hsu7ac88852016-04-28 10:20:34 -07004119 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4120 if (nla_put_string(reply_skb,
4121 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4122 driver_version))
4123 goto error_nla_fail;
4124 }
4125
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304126 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004127 if (nla_put_string(reply_skb,
4128 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4129 firmware_version))
4130 goto error_nla_fail;
4131 }
4132
4133 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4134 if (nla_put_u32(reply_skb,
4135 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4136 hdd_ctx->radio_index))
4137 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 }
4139
4140 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004141
4142error_nla_fail:
4143 hdd_err("nla put fail");
4144 kfree_skb(reply_skb);
4145 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146}
4147
4148/**
4149 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4150 * @wiphy: pointer to wireless wiphy structure.
4151 * @wdev: pointer to wireless_dev structure.
4152 * @data: Pointer to the data to be passed via vendor interface
4153 * @data_len:Length of the data to be passed
4154 *
4155 * This is called when wlan driver needs to send wifi driver related info
4156 * (driver/fw version) to the user space application upon request.
4157 *
4158 * Return: Return the Success or Failure code.
4159 */
4160static int
4161wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4162 struct wireless_dev *wdev,
4163 const void *data, int data_len)
4164{
4165 int ret;
4166
4167 cds_ssr_protect(__func__);
4168 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4169 cds_ssr_unprotect(__func__);
4170
4171 return ret;
4172}
4173
4174/**
4175 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4176 * @wiphy: pointer to wireless wiphy structure.
4177 * @wdev: pointer to wireless_dev structure.
4178 * @data: Pointer to the data to be passed via vendor interface
4179 * @data_len:Length of the data to be passed
4180 *
4181 * This is called by userspace to know the supported logger features
4182 *
4183 * Return: Return the Success or Failure code.
4184 */
4185static int
4186__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4187 struct wireless_dev *wdev,
4188 const void *data, int data_len)
4189{
4190 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4191 int status;
4192 uint32_t features;
4193 struct sk_buff *reply_skb = NULL;
4194
Jeff Johnson1f61b612016-02-12 16:28:33 -08004195 ENTER_DEV(wdev->netdev);
4196
Anurag Chouhan6d760662016-02-20 16:05:43 +05304197 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004198 hdd_err("Command not allowed in FTM mode");
4199 return -EPERM;
4200 }
4201
4202 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304203 if (status)
4204 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004205
4206 features = 0;
4207
4208 if (hdd_is_memdump_supported())
4209 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4210 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4211 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4212 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4213
4214 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4215 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4216 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004217 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218 return -ENOMEM;
4219 }
4220
Jeff Johnson020db452016-06-29 14:37:26 -07004221 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4223 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004224 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 kfree_skb(reply_skb);
4226 return -EINVAL;
4227 }
4228
4229 return cfg80211_vendor_cmd_reply(reply_skb);
4230}
4231
4232/**
4233 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4234 * @wiphy: pointer to wireless wiphy structure.
4235 * @wdev: pointer to wireless_dev structure.
4236 * @data: Pointer to the data to be passed via vendor interface
4237 * @data_len:Length of the data to be passed
4238 *
4239 * This is called by userspace to know the supported logger features
4240 *
4241 * Return: Return the Success or Failure code.
4242 */
4243static int
4244wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4245 struct wireless_dev *wdev,
4246 const void *data, int data_len)
4247{
4248 int ret;
4249
4250 cds_ssr_protect(__func__);
4251 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4252 data, data_len);
4253 cds_ssr_unprotect(__func__);
4254
4255 return ret;
4256}
4257
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004258#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259/**
4260 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304261 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262 * @bssid: pointer to bssid of roamed AP.
4263 * @req_rsn_ie: Pointer to request RSN IE
4264 * @req_rsn_len: Length of the request RSN IE
4265 * @rsp_rsn_ie: Pointer to response RSN IE
4266 * @rsp_rsn_len: Length of the response RSN IE
4267 * @roam_info_ptr: Pointer to the roaming related information
4268 *
4269 * This is called when wlan driver needs to send the roaming and
4270 * authorization information after roaming.
4271 *
4272 * The information that would be sent is the request RSN IE, response
4273 * RSN IE and BSSID of the newly roamed AP.
4274 *
4275 * If the Authorized status is authenticated, then additional parameters
4276 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4277 * supplicant.
4278 *
4279 * The supplicant upon receiving this event would ignore the legacy
4280 * cfg80211_roamed call and use the entire information from this event.
4281 * The cfg80211_roamed should still co-exist since the kernel will
4282 * make use of the parameters even if the supplicant ignores it.
4283 *
4284 * Return: Return the Success or Failure code.
4285 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304286int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004287 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4288 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4289{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304290 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004291 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004292 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 ENTER();
4294
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304295 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004298 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004299 !roam_info_ptr->roamSynchInProgress)
4300 return 0;
4301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304303 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4305 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4306 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004307 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4309 GFP_KERNEL);
4310
4311 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004312 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 return -EINVAL;
4314 }
4315
4316 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4317 ETH_ALEN, bssid) ||
4318 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4319 req_rsn_len, req_rsn_ie) ||
4320 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4321 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004322 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323 goto nla_put_failure;
4324 }
Jeff Johnson020db452016-06-29 14:37:26 -07004325 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004326 if (roam_info_ptr->synchAuthStatus ==
4327 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004328 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004329 if (nla_put_u8(skb,
4330 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4331 hdd_err("nla put fail");
4332 goto nla_put_failure;
4333 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004334 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4335 /* if FT or CCKM connection: dont send replay counter */
4336 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4337 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4338 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4339 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4340 nla_put(skb,
4341 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4342 SIR_REPLAY_CTR_LEN,
4343 roam_info_ptr->replay_ctr)) {
4344 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004345 hdd_err("failed to send replay counter.");
4346 goto nla_put_failure;
4347 }
4348 if (nla_put(skb,
4349 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4350 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4351 nla_put(skb,
4352 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4353 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4354 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 goto nla_put_failure;
4356 }
4357 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004358 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4360 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 goto nla_put_failure;
4363 }
4364 }
4365
Jeff Johnson020db452016-06-29 14:37:26 -07004366 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004367 roam_info_ptr->subnet_change_status);
4368
4369 /*
4370 * Add subnet change status if subnet has changed
4371 * 0 = unchanged
4372 * 1 = changed
4373 * 2 = unknown
4374 */
4375 if (roam_info_ptr->subnet_change_status) {
4376 if (nla_put_u8(skb,
4377 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4378 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004379 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004380 goto nla_put_failure;
4381 }
4382 }
4383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 cfg80211_vendor_event(skb, GFP_KERNEL);
4385 return 0;
4386
4387nla_put_failure:
4388 kfree_skb(skb);
4389 return -EINVAL;
4390}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004391#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392
4393static const struct nla_policy
4394wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4395
4396 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4397 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4398 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304399 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304400 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4401 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004402 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4403 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4404 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4405 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4406 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304407 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408};
4409
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304411 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4412 *
4413 * @adapter: Pointer to HDD adapter
4414 * @ie_data: Pointer to Scan IEs buffer
4415 * @ie_len: Length of Scan IEs
4416 *
4417 * Return: 0 on success; error number otherwise
4418 */
4419static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4420 uint8_t *ie_data, uint8_t ie_len)
4421{
4422 hdd_scaninfo_t *scan_info = NULL;
4423 scan_info = &adapter->scan_info;
4424
4425 if (scan_info->default_scan_ies) {
4426 qdf_mem_free(scan_info->default_scan_ies);
4427 scan_info->default_scan_ies = NULL;
4428 }
4429
4430 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4431 if (!scan_info->default_scan_ies)
4432 return -ENOMEM;
4433
4434 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4435 scan_info->default_scan_ies_len = ie_len;
4436 return 0;
4437}
4438
4439/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004440 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4441 * vendor command
4442 *
4443 * @wiphy: wiphy device pointer
4444 * @wdev: wireless device pointer
4445 * @data: Vendor command data buffer
4446 * @data_len: Buffer length
4447 *
4448 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4449 *
4450 * Return: Error code.
4451 */
4452static int
4453__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4454 struct wireless_dev *wdev,
4455 const void *data,
4456 int data_len)
4457{
4458 struct net_device *dev = wdev->netdev;
4459 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4460 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4461 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4462 int ret_val = 0;
4463 u32 modulated_dtim;
4464 u16 stats_avg_factor;
4465 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304466 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004467 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004468 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304469 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304470 int attr_len;
4471 int access_policy = 0;
4472 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4473 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304474 uint16_t scan_ie_len = 0;
4475 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304476 struct sir_set_tx_rx_aggregation_size request;
4477 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004478 uint8_t retry, delay;
4479 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304480 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304481
Jeff Johnson1f61b612016-02-12 16:28:33 -08004482 ENTER_DEV(dev);
4483
Anurag Chouhan6d760662016-02-20 16:05:43 +05304484 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485 hdd_err("Command not allowed in FTM mode");
4486 return -EPERM;
4487 }
4488
4489 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304490 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492
4493 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4494 data, data_len,
4495 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004496 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 return -EINVAL;
4498 }
4499
Krunal Sonie3531942016-04-12 17:43:53 -07004500 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4501 ftm_capab = nla_get_u32(tb[
4502 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4503 hdd_ctx->config->fine_time_meas_cap =
4504 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4505 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304506 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004507 hdd_ctx->config->fine_time_meas_cap);
4508 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4509 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4510 hdd_ctx->config->fine_time_meas_cap);
4511 }
4512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4514 modulated_dtim = nla_get_u32(
4515 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4516
4517 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4518 adapter->sessionId,
4519 modulated_dtim);
4520
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304521 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 ret_val = -EPERM;
4523 }
4524
Kapil Gupta6213c012016-09-02 19:39:09 +05304525 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4526 qpower = nla_get_u8(
4527 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4528 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4529 ret_val = -EINVAL;
4530 }
4531
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004532 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4533 stats_avg_factor = nla_get_u16(
4534 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4535 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4536 adapter->sessionId,
4537 stats_avg_factor);
4538
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304539 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540 ret_val = -EPERM;
4541 }
4542
4543
4544 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4545 guard_time = nla_get_u32(
4546 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4547 status = sme_configure_guard_time(hdd_ctx->hHal,
4548 adapter->sessionId,
4549 guard_time);
4550
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304551 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 ret_val = -EPERM;
4553 }
4554
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304555 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4556 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4557 attr_len = nla_len(
4558 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4559 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4560 hdd_info("Invalid value. attr_len %d",
4561 attr_len);
4562 return -EINVAL;
4563 }
4564
4565 nla_memcpy(&vendor_ie,
4566 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4567 attr_len);
4568 vendor_ie_present = true;
4569 hdd_info("Access policy vendor ie present.attr_len %d",
4570 attr_len);
4571 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4572 &vendor_ie[0], attr_len);
4573 }
4574
4575 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4576 access_policy = (int) nla_get_u32(
4577 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4578 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4579 (access_policy >
4580 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4581 hdd_info("Invalid value. access_policy %d",
4582 access_policy);
4583 return -EINVAL;
4584 }
4585 access_policy_present = true;
4586 hdd_info("Access policy present. access_policy %d",
4587 access_policy);
4588 }
4589
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004590 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4591 retry = nla_get_u8(tb[
4592 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4593 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4594 CFG_NON_AGG_RETRY_MAX : retry;
4595 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4596 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4597 retry, PDEV_CMD);
4598 }
4599
4600 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4601 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4602 retry = retry > CFG_AGG_RETRY_MAX ?
4603 CFG_AGG_RETRY_MAX : retry;
4604
4605 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4606 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4607 CFG_AGG_RETRY_MIN : retry;
4608 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4609 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4610 retry, PDEV_CMD);
4611 }
4612
4613 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4614 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4615 retry = retry > CFG_MGMT_RETRY_MAX ?
4616 CFG_MGMT_RETRY_MAX : retry;
4617 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4618 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4619 retry, PDEV_CMD);
4620 }
4621
4622 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4623 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4624 retry = retry > CFG_CTRL_RETRY_MAX ?
4625 CFG_CTRL_RETRY_MAX : retry;
4626 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4627 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4628 retry, PDEV_CMD);
4629 }
4630
4631 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4632 delay = nla_get_u8(tb[
4633 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4634 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4635 CFG_PROPAGATION_DELAY_MAX : delay;
4636 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4637 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4638 delay, PDEV_CMD);
4639 }
4640
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304641 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4642 tx_fail_count = nla_get_u32(
4643 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4644 if (tx_fail_count) {
4645 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4646 adapter->sessionId, tx_fail_count);
4647 if (QDF_STATUS_SUCCESS != status) {
4648 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4649 status);
4650 return -EINVAL;
4651 }
4652 }
4653 }
4654
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304655 if (vendor_ie_present && access_policy_present) {
4656 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4657 access_policy =
4658 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304659 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304660 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304661 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304662
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304663 hdd_info("calling sme_update_access_policy_vendor_ie");
4664 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4665 adapter->sessionId, &vendor_ie[0],
4666 access_policy);
4667 if (QDF_STATUS_SUCCESS != status) {
4668 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304669 return -EINVAL;
4670 }
4671 }
4672
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304673 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4674 set_value = nla_get_u8(
4675 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4676 hdd_info("set_value: %d", set_value);
4677 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4678 }
4679
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304680 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4681 scan_ie_len = nla_len(
4682 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4683 hdd_info("Received default scan IE of len %d session %d device mode %d",
4684 scan_ie_len, adapter->sessionId,
4685 adapter->device_mode);
4686 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4687 scan_ie = (uint8_t *) nla_data(tb
4688 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304689
4690 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4691 scan_ie_len))
4692 hdd_err("Failed to save default scan IEs");
4693
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304694 if (adapter->device_mode == QDF_STA_MODE) {
4695 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4696 adapter->sessionId, scan_ie,
4697 scan_ie_len);
4698 if (QDF_STATUS_SUCCESS != status)
4699 ret_val = -EPERM;
4700 }
4701 } else
4702 ret_val = -EPERM;
4703 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304704
4705 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4706 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4707 /* if one is specified, both must be specified */
4708 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4709 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4710 hdd_err("Both TX and RX MPDU Aggregation required");
4711 return -EINVAL;
4712 }
4713
4714 request.tx_aggregation_size = nla_get_u8(
4715 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4716 request.rx_aggregation_size = nla_get_u8(
4717 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4718 request.vdev_id = adapter->sessionId;
4719
4720 if (request.tx_aggregation_size >=
4721 CFG_TX_AGGREGATION_SIZE_MIN &&
4722 request.tx_aggregation_size <=
4723 CFG_TX_AGGREGATION_SIZE_MAX &&
4724 request.rx_aggregation_size >=
4725 CFG_RX_AGGREGATION_SIZE_MIN &&
4726 request.rx_aggregation_size <=
4727 CFG_RX_AGGREGATION_SIZE_MAX) {
4728 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4729 if (qdf_status != QDF_STATUS_SUCCESS) {
4730 hdd_err("failed to set aggr sizes err %d",
4731 qdf_status);
4732 ret_val = -EPERM;
4733 }
4734 } else {
4735 hdd_err("TX %d RX %d MPDU aggr size not in range",
4736 request.tx_aggregation_size,
4737 request.rx_aggregation_size);
4738 ret_val = -EINVAL;
4739 }
4740 }
4741
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304742 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4743 uint8_t ignore_assoc_disallowed;
4744
4745 ignore_assoc_disallowed
4746 = nla_get_u8(tb[
4747 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4748 hdd_info("Set ignore_assoc_disallowed value - %d",
4749 ignore_assoc_disallowed);
4750 if ((ignore_assoc_disallowed <
4751 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4752 (ignore_assoc_disallowed >
4753 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4754 return -EPERM;
4755
4756 sme_update_session_param(hdd_ctx->hHal,
4757 adapter->sessionId,
4758 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4759 ignore_assoc_disallowed);
4760 }
4761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 return ret_val;
4763}
4764
4765/**
4766 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4767 * vendor command
4768 *
4769 * @wiphy: wiphy device pointer
4770 * @wdev: wireless device pointer
4771 * @data: Vendor command data buffer
4772 * @data_len: Buffer length
4773 *
4774 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4775 *
4776 * Return: EOK or other error codes.
4777 */
4778static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4779 struct wireless_dev *wdev,
4780 const void *data,
4781 int data_len)
4782{
4783 int ret;
4784
4785 cds_ssr_protect(__func__);
4786 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4787 data, data_len);
4788 cds_ssr_unprotect(__func__);
4789
4790 return ret;
4791}
4792
4793static const struct
4794nla_policy
4795qca_wlan_vendor_wifi_logger_start_policy
4796[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4797 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4798 = {.type = NLA_U32 },
4799 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4800 = {.type = NLA_U32 },
4801 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4802 = {.type = NLA_U32 },
4803};
4804
4805/**
4806 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4807 * or disable the collection of packet statistics from the firmware
4808 * @wiphy: WIPHY structure pointer
4809 * @wdev: Wireless device structure pointer
4810 * @data: Pointer to the data received
4811 * @data_len: Length of the data received
4812 *
4813 * This function enables or disables the collection of packet statistics from
4814 * the firmware
4815 *
4816 * Return: 0 on success and errno on failure
4817 */
4818static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4819 struct wireless_dev *wdev,
4820 const void *data,
4821 int data_len)
4822{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304823 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4825 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4826 struct sir_wifi_start_log start_log;
4827
Jeff Johnson1f61b612016-02-12 16:28:33 -08004828 ENTER_DEV(wdev->netdev);
4829
Anurag Chouhan6d760662016-02-20 16:05:43 +05304830 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 hdd_err("Command not allowed in FTM mode");
4832 return -EPERM;
4833 }
4834
4835 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304836 if (status)
4837 return status;
4838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839
4840 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4841 data, data_len,
4842 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004843 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004844 return -EINVAL;
4845 }
4846
4847 /* Parse and fetch ring id */
4848 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004849 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004850 return -EINVAL;
4851 }
4852 start_log.ring_id = nla_get_u32(
4853 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004854 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004855
4856 /* Parse and fetch verbose level */
4857 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004858 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859 return -EINVAL;
4860 }
4861 start_log.verbose_level = nla_get_u32(
4862 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004863 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004864
4865 /* Parse and fetch flag */
4866 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004867 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004868 return -EINVAL;
4869 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304870 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304872 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304874 /* size is buff size which can be set using iwpriv command*/
4875 start_log.size = 0;
4876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4878
4879 if (start_log.ring_id == RING_ID_WAKELOCK) {
4880 /* Start/stop wakelock events */
4881 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4882 cds_set_wakelock_logging(true);
4883 else
4884 cds_set_wakelock_logging(false);
4885 return 0;
4886 }
4887
4888 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304889 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004890 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891 status);
4892 return -EINVAL;
4893 }
4894 return 0;
4895}
4896
4897/**
4898 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4899 * or disable the collection of packet statistics from the firmware
4900 * @wiphy: WIPHY structure pointer
4901 * @wdev: Wireless device structure pointer
4902 * @data: Pointer to the data received
4903 * @data_len: Length of the data received
4904 *
4905 * This function is used to enable or disable the collection of packet
4906 * statistics from the firmware
4907 *
4908 * Return: 0 on success and errno on failure
4909 */
4910static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4911 struct wireless_dev *wdev,
4912 const void *data,
4913 int data_len)
4914{
4915 int ret = 0;
4916
4917 cds_ssr_protect(__func__);
4918 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4919 wdev, data, data_len);
4920 cds_ssr_unprotect(__func__);
4921
4922 return ret;
4923}
4924
4925static const struct
4926nla_policy
4927qca_wlan_vendor_wifi_logger_get_ring_data_policy
4928[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4929 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4930 = {.type = NLA_U32 },
4931};
4932
4933/**
4934 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4935 * @wiphy: WIPHY structure pointer
4936 * @wdev: Wireless device structure pointer
4937 * @data: Pointer to the data received
4938 * @data_len: Length of the data received
4939 *
4940 * This function is used to flush or retrieve the per packet statistics from
4941 * the driver
4942 *
4943 * Return: 0 on success and errno on failure
4944 */
4945static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4946 struct wireless_dev *wdev,
4947 const void *data,
4948 int data_len)
4949{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304950 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004951 uint32_t ring_id;
4952 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4953 struct nlattr *tb
4954 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4955
Jeff Johnson1f61b612016-02-12 16:28:33 -08004956 ENTER_DEV(wdev->netdev);
4957
Anurag Chouhan6d760662016-02-20 16:05:43 +05304958 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 hdd_err("Command not allowed in FTM mode");
4960 return -EPERM;
4961 }
4962
4963 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304964 if (status)
4965 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004966
4967 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4968 data, data_len,
4969 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004970 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 return -EINVAL;
4972 }
4973
4974 /* Parse and fetch ring id */
4975 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004976 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004977 return -EINVAL;
4978 }
4979
4980 ring_id = nla_get_u32(
4981 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4982
4983 if (ring_id == RING_ID_PER_PACKET_STATS) {
4984 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004985 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304986 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4987 /*
4988 * As part of DRIVER ring ID, flush both driver and fw logs.
4989 * For other Ring ID's driver doesn't have any rings to flush
4990 */
4991 hdd_notice("Bug report triggered by framework");
4992
4993 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4994 WLAN_LOG_INDICATOR_FRAMEWORK,
4995 WLAN_LOG_REASON_CODE_UNUSED,
4996 true, false);
4997 if (QDF_STATUS_SUCCESS != status) {
4998 hdd_err("Failed to trigger bug report");
4999 return -EINVAL;
5000 }
5001 } else {
5002 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5003 WLAN_LOG_INDICATOR_FRAMEWORK,
5004 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006 return 0;
5007}
5008
5009/**
5010 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5011 * @wiphy: WIPHY structure pointer
5012 * @wdev: Wireless device structure pointer
5013 * @data: Pointer to the data received
5014 * @data_len: Length of the data received
5015 *
5016 * This function is used to flush or retrieve the per packet statistics from
5017 * the driver
5018 *
5019 * Return: 0 on success and errno on failure
5020 */
5021static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5022 struct wireless_dev *wdev,
5023 const void *data,
5024 int data_len)
5025{
5026 int ret = 0;
5027
5028 cds_ssr_protect(__func__);
5029 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5030 wdev, data, data_len);
5031 cds_ssr_unprotect(__func__);
5032
5033 return ret;
5034}
5035
5036#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5037/**
5038 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5039 * @hdd_ctx: HDD context
5040 * @request_id: [input] request id
5041 * @pattern_id: [output] pattern id
5042 *
5043 * This function loops through request id to pattern id array
5044 * if the slot is available, store the request id and return pattern id
5045 * if entry exists, return the pattern id
5046 *
5047 * Return: 0 on success and errno on failure
5048 */
5049static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5050 uint32_t request_id,
5051 uint8_t *pattern_id)
5052{
5053 uint32_t i;
5054
5055 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5056 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5057 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5058 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5059 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5060 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5061 return 0;
5062 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5063 request_id) {
5064 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5065 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5066 return 0;
5067 }
5068 }
5069 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5070 return -EINVAL;
5071}
5072
5073/**
5074 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5075 * @hdd_ctx: HDD context
5076 * @request_id: [input] request id
5077 * @pattern_id: [output] pattern id
5078 *
5079 * This function loops through request id to pattern id array
5080 * reset request id to 0 (slot available again) and
5081 * return pattern id
5082 *
5083 * Return: 0 on success and errno on failure
5084 */
5085static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5086 uint32_t request_id,
5087 uint8_t *pattern_id)
5088{
5089 uint32_t i;
5090
5091 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5092 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5093 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5094 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5095 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5096 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5097 return 0;
5098 }
5099 }
5100 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5101 return -EINVAL;
5102}
5103
5104
5105/*
5106 * define short names for the global vendor params
5107 * used by __wlan_hdd_cfg80211_offloaded_packets()
5108 */
5109#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5110#define PARAM_REQUEST_ID \
5111 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5112#define PARAM_CONTROL \
5113 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5114#define PARAM_IP_PACKET \
5115 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5116#define PARAM_SRC_MAC_ADDR \
5117 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5118#define PARAM_DST_MAC_ADDR \
5119 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5120#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5121
5122/**
5123 * wlan_hdd_add_tx_ptrn() - add tx pattern
5124 * @adapter: adapter pointer
5125 * @hdd_ctx: hdd context
5126 * @tb: nl attributes
5127 *
5128 * This function reads the NL attributes and forms a AddTxPtrn message
5129 * posts it to SME.
5130 *
5131 */
5132static int
5133wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5134 struct nlattr **tb)
5135{
5136 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305137 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005138 uint32_t request_id, ret, len;
5139 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305140 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005141 uint16_t eth_type = htons(ETH_P_IP);
5142
5143 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005144 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005145 return -ENOTSUPP;
5146 }
5147
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305148 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005150 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005151 return -ENOMEM;
5152 }
5153
5154 /* Parse and fetch request Id */
5155 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005156 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005157 goto fail;
5158 }
5159
5160 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5161 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005162 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005163 return -EINVAL;
5164 }
Jeff Johnson77848112016-06-29 14:52:06 -07005165 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166
5167 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005168 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005169 goto fail;
5170 }
5171 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005172 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005174 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005175 goto fail;
5176 }
5177
5178 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005179 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005180 goto fail;
5181 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005182 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305183 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005184 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005185 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005186
Anurag Chouhanc5548422016-02-24 18:33:27 +05305187 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005188 &adapter->macAddressCurrent)) {
5189 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005190 goto fail;
5191 }
5192
5193 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005194 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 goto fail;
5196 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305197 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005198 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 MAC_ADDR_ARRAY(dst_addr.bytes));
5200
5201 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005202 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 goto fail;
5204 }
5205 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005206 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207
5208 if (add_req->ucPtrnSize < 0 ||
5209 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5210 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005211 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212 add_req->ucPtrnSize);
5213 goto fail;
5214 }
5215
5216 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305217 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305218 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305219 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305220 QDF_MAC_ADDR_SIZE);
5221 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305222 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 len += 2;
5224
5225 /*
5226 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5227 * ------------------------------------------------------------
5228 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5229 * ------------------------------------------------------------
5230 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305231 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232 nla_data(tb[PARAM_IP_PACKET]),
5233 add_req->ucPtrnSize);
5234 add_req->ucPtrnSize += len;
5235
5236 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5237 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 goto fail;
5240 }
5241 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005242 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
5244 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305245 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005246 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 goto fail;
5248 }
5249
5250 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305251 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 return 0;
5253
5254fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305255 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 return -EINVAL;
5257}
5258
5259/**
5260 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5261 * @adapter: adapter pointer
5262 * @hdd_ctx: hdd context
5263 * @tb: nl attributes
5264 *
5265 * This function reads the NL attributes and forms a DelTxPtrn message
5266 * posts it to SME.
5267 *
5268 */
5269static int
5270wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5271 struct nlattr **tb)
5272{
5273 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305274 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 uint32_t request_id, ret;
5276 uint8_t pattern_id = 0;
5277
5278 /* Parse and fetch request Id */
5279 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005280 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 return -EINVAL;
5282 }
5283 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5284 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005285 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 return -EINVAL;
5287 }
5288
5289 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5290 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005291 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 return -EINVAL;
5293 }
5294
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305295 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005296 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005297 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005298 return -ENOMEM;
5299 }
5300
Anurag Chouhanc5548422016-02-24 18:33:27 +05305301 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005302 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005303 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005304 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005305 request_id, del_req->ucPtrnId);
5306
5307 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305308 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005309 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005310 goto fail;
5311 }
5312
5313 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305314 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005315 return 0;
5316
5317fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305318 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319 return -EINVAL;
5320}
5321
5322
5323/**
5324 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5325 * @wiphy: Pointer to wireless phy
5326 * @wdev: Pointer to wireless device
5327 * @data: Pointer to data
5328 * @data_len: Data length
5329 *
5330 * Return: 0 on success, negative errno on failure
5331 */
5332static int
5333__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5334 struct wireless_dev *wdev,
5335 const void *data,
5336 int data_len)
5337{
5338 struct net_device *dev = wdev->netdev;
5339 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5340 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5341 struct nlattr *tb[PARAM_MAX + 1];
5342 uint8_t control;
5343 int ret;
5344 static const struct nla_policy policy[PARAM_MAX + 1] = {
5345 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5346 [PARAM_CONTROL] = { .type = NLA_U32 },
5347 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305348 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305350 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 [PARAM_PERIOD] = { .type = NLA_U32 },
5352 };
5353
Jeff Johnson1f61b612016-02-12 16:28:33 -08005354 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355
Anurag Chouhan6d760662016-02-20 16:05:43 +05305356 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 hdd_err("Command not allowed in FTM mode");
5358 return -EPERM;
5359 }
5360
5361 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305362 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364
5365 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005366 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 return -ENOTSUPP;
5368 }
5369
5370 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005371 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 return -EINVAL;
5373 }
5374
5375 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005376 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 return -EINVAL;
5378 }
5379 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005380 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381
5382 if (control == WLAN_START_OFFLOADED_PACKETS)
5383 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005384 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005386
5387 hdd_err("Invalid control: %d", control);
5388
5389 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390}
5391
5392/*
5393 * done with short names for the global vendor params
5394 * used by __wlan_hdd_cfg80211_offloaded_packets()
5395 */
5396#undef PARAM_MAX
5397#undef PARAM_REQUEST_ID
5398#undef PARAM_CONTROL
5399#undef PARAM_IP_PACKET
5400#undef PARAM_SRC_MAC_ADDR
5401#undef PARAM_DST_MAC_ADDR
5402#undef PARAM_PERIOD
5403
5404/**
5405 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5406 * @wiphy: wiphy structure pointer
5407 * @wdev: Wireless device structure pointer
5408 * @data: Pointer to the data received
5409 * @data_len: Length of @data
5410 *
5411 * Return: 0 on success; errno on failure
5412 */
5413static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5414 struct wireless_dev *wdev,
5415 const void *data,
5416 int data_len)
5417{
5418 int ret = 0;
5419
5420 cds_ssr_protect(__func__);
5421 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5422 wdev, data, data_len);
5423 cds_ssr_unprotect(__func__);
5424
5425 return ret;
5426}
5427#endif
5428
5429/*
5430 * define short names for the global vendor params
5431 * used by __wlan_hdd_cfg80211_monitor_rssi()
5432 */
5433#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5434#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5435#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5436#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5437#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5438
5439/**
5440 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5441 * @wiphy: Pointer to wireless phy
5442 * @wdev: Pointer to wireless device
5443 * @data: Pointer to data
5444 * @data_len: Data length
5445 *
5446 * Return: 0 on success, negative errno on failure
5447 */
5448static int
5449__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5450 struct wireless_dev *wdev,
5451 const void *data,
5452 int data_len)
5453{
5454 struct net_device *dev = wdev->netdev;
5455 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5456 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5457 struct nlattr *tb[PARAM_MAX + 1];
5458 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305459 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460 int ret;
5461 uint32_t control;
5462 static const struct nla_policy policy[PARAM_MAX + 1] = {
5463 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5464 [PARAM_CONTROL] = { .type = NLA_U32 },
5465 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5466 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5467 };
5468
Jeff Johnson1f61b612016-02-12 16:28:33 -08005469 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305471 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5472 hdd_err("invalid session id: %d", adapter->sessionId);
5473 return -EINVAL;
5474 }
5475
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305477 if (ret)
5478 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005479
5480 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005481 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005482 return -ENOTSUPP;
5483 }
5484
5485 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005486 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 return -EINVAL;
5488 }
5489
5490 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005491 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492 return -EINVAL;
5493 }
5494
5495 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005496 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497 return -EINVAL;
5498 }
5499
5500 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5501 req.session_id = adapter->sessionId;
5502 control = nla_get_u32(tb[PARAM_CONTROL]);
5503
5504 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5505 req.control = true;
5506 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005507 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005508 return -EINVAL;
5509 }
5510
5511 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005512 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 return -EINVAL;
5514 }
5515
5516 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5517 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5518
5519 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005520 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 req.min_rssi, req.max_rssi);
5522 return -EINVAL;
5523 }
Jeff Johnson77848112016-06-29 14:52:06 -07005524 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 req.min_rssi, req.max_rssi);
5526
5527 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5528 req.control = false;
5529 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005530 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 return -EINVAL;
5532 }
Jeff Johnson77848112016-06-29 14:52:06 -07005533 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005534 req.request_id, req.session_id, req.control);
5535
5536 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305537 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005538 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005539 return -EINVAL;
5540 }
5541
5542 return 0;
5543}
5544
5545/*
5546 * done with short names for the global vendor params
5547 * used by __wlan_hdd_cfg80211_monitor_rssi()
5548 */
5549#undef PARAM_MAX
5550#undef PARAM_CONTROL
5551#undef PARAM_REQUEST_ID
5552#undef PARAM_MAX_RSSI
5553#undef PARAM_MIN_RSSI
5554
5555/**
5556 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5557 * @wiphy: wiphy structure pointer
5558 * @wdev: Wireless device structure pointer
5559 * @data: Pointer to the data received
5560 * @data_len: Length of @data
5561 *
5562 * Return: 0 on success; errno on failure
5563 */
5564static int
5565wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5566 const void *data, int data_len)
5567{
5568 int ret;
5569
5570 cds_ssr_protect(__func__);
5571 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5572 cds_ssr_unprotect(__func__);
5573
5574 return ret;
5575}
5576
5577/**
5578 * hdd_rssi_threshold_breached() - rssi breached NL event
5579 * @hddctx: HDD context
5580 * @data: rssi breached event data
5581 *
5582 * This function reads the rssi breached event %data and fill in the skb with
5583 * NL attributes and send up the NL event.
5584 *
5585 * Return: none
5586 */
5587void hdd_rssi_threshold_breached(void *hddctx,
5588 struct rssi_breach_event *data)
5589{
5590 hdd_context_t *hdd_ctx = hddctx;
5591 struct sk_buff *skb;
5592
5593 ENTER();
5594
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305595 if (wlan_hdd_validate_context(hdd_ctx))
5596 return;
5597 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005598 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005599 return;
5600 }
5601
5602 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5603 NULL,
5604 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5605 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5606 GFP_KERNEL);
5607
5608 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005609 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005610 return;
5611 }
5612
Jeff Johnson77848112016-06-29 14:52:06 -07005613 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005615 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5617
5618 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5619 data->request_id) ||
5620 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5621 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5622 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5623 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005624 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625 goto fail;
5626 }
5627
5628 cfg80211_vendor_event(skb, GFP_KERNEL);
5629 return;
5630
5631fail:
5632 kfree_skb(skb);
5633 return;
5634}
5635
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305636static const struct nla_policy
5637ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5638 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5639};
5640
5641/**
5642 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5643 * @wiphy: Pointer to wireless phy
5644 * @wdev: Pointer to wireless device
5645 * @data: Pointer to data
5646 * @data_len: Length of @data
5647 *
5648 * Return: 0 on success, negative errno on failure
5649 */
5650static int
5651__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5652 struct wireless_dev *wdev,
5653 const void *data, int data_len)
5654{
5655 int status;
5656 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5657 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005658 struct net_device *dev = wdev->netdev;
5659 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305660
5661 ENTER_DEV(wdev->netdev);
5662
5663 status = wlan_hdd_validate_context(pHddCtx);
5664 if (0 != status)
5665 return status;
5666 if (!pHddCtx->config->fhostNSOffload) {
5667 hdd_err("ND Offload not supported");
5668 return -EINVAL;
5669 }
5670
5671 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5672 (struct nlattr *)data,
5673 data_len, ns_offload_set_policy)) {
5674 hdd_err("nla_parse failed");
5675 return -EINVAL;
5676 }
5677
5678 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5679 hdd_err("ND Offload flag attribute not present");
5680 return -EINVAL;
5681 }
5682
5683 pHddCtx->ns_offload_enable =
5684 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5685
Dustin Brownd8279d22016-09-07 14:52:57 -07005686 /* update ns offload in case it is already enabled/disabled */
5687 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5688
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305689 return 0;
5690}
5691
5692/**
5693 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5694 * @wiphy: pointer to wireless wiphy structure.
5695 * @wdev: pointer to wireless_dev structure.
5696 * @data: Pointer to the data to be passed via vendor interface
5697 * @data_len:Length of the data to be passed
5698 *
5699 * Return: Return the Success or Failure code.
5700 */
5701static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5702 struct wireless_dev *wdev,
5703 const void *data, int data_len)
5704{
5705 int ret;
5706
5707 cds_ssr_protect(__func__);
5708 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5709 cds_ssr_unprotect(__func__);
5710
5711 return ret;
5712}
5713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005714/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5715 * @wiphy: Pointer to wireless phy
5716 * @wdev: Pointer to wireless device
5717 * @data: Pointer to data
5718 * @data_len: Data length
5719 *
5720 * This function return the preferred frequency list generated by the policy
5721 * manager.
5722 *
5723 * Return: success or failure code
5724 */
5725static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5726 struct wireless_dev
5727 *wdev, const void *data,
5728 int data_len)
5729{
5730 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5731 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305732 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305733 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005734 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305735 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005736 enum cds_con_mode intf_mode;
5737 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5738 struct sk_buff *reply_skb;
5739
Jeff Johnson1f61b612016-02-12 16:28:33 -08005740 ENTER_DEV(wdev->netdev);
5741
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742 ret = wlan_hdd_validate_context(hdd_ctx);
5743 if (ret)
5744 return -EINVAL;
5745
5746 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5747 data, data_len, NULL)) {
5748 hdd_err("Invalid ATTR");
5749 return -EINVAL;
5750 }
5751
5752 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5753 hdd_err("attr interface type failed");
5754 return -EINVAL;
5755 }
5756
5757 intf_mode = nla_get_u32(tb
5758 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5759
5760 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5761 hdd_err("Invalid interface type");
5762 return -EINVAL;
5763 }
5764
5765 hdd_debug("Userspace requested pref freq list");
5766
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305767 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5768 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305769 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005770 hdd_err("Get pcl failed");
5771 return -EINVAL;
5772 }
5773
5774 /* convert channel number to frequency */
5775 for (i = 0; i < pcl_len; i++) {
5776 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5777 freq_list[i] =
5778 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005779 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005780 else
5781 freq_list[i] =
5782 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005783 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784 }
5785
5786 /* send the freq_list back to supplicant */
5787 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5788 sizeof(u32) *
5789 pcl_len +
5790 NLMSG_HDRLEN);
5791
5792 if (!reply_skb) {
5793 hdd_err("Allocate reply_skb failed");
5794 return -EINVAL;
5795 }
5796
5797 if (nla_put_u32(reply_skb,
5798 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5799 intf_mode) ||
5800 nla_put(reply_skb,
5801 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5802 sizeof(uint32_t) * pcl_len,
5803 freq_list)) {
5804 hdd_err("nla put fail");
5805 kfree_skb(reply_skb);
5806 return -EINVAL;
5807 }
5808
5809 return cfg80211_vendor_cmd_reply(reply_skb);
5810}
5811
5812/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5813 * @wiphy: Pointer to wireless phy
5814 * @wdev: Pointer to wireless device
5815 * @data: Pointer to data
5816 * @data_len: Data length
5817 *
5818 * This function return the preferred frequency list generated by the policy
5819 * manager.
5820 *
5821 * Return: success or failure code
5822 */
5823static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5824 struct wireless_dev
5825 *wdev, const void *data,
5826 int data_len)
5827{
5828 int ret = 0;
5829
5830 cds_ssr_protect(__func__);
5831 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5832 data, data_len);
5833 cds_ssr_unprotect(__func__);
5834
5835 return ret;
5836}
5837
5838/**
5839 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5840 * @wiphy: Pointer to wireless phy
5841 * @wdev: Pointer to wireless device
5842 * @data: Pointer to data
5843 * @data_len: Data length
5844 *
5845 * Return: 0 on success, negative errno on failure
5846 */
5847static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5848 struct wireless_dev *wdev,
5849 const void *data,
5850 int data_len)
5851{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305852 struct net_device *ndev = wdev->netdev;
5853 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005854 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5855 int ret = 0;
5856 enum cds_con_mode intf_mode;
5857 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5858 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005859
Jeff Johnson1f61b612016-02-12 16:28:33 -08005860 ENTER_DEV(ndev);
5861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 ret = wlan_hdd_validate_context(hdd_ctx);
5863 if (ret)
5864 return ret;
5865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005866 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5867 data, data_len, NULL)) {
5868 hdd_err("Invalid ATTR");
5869 return -EINVAL;
5870 }
5871
5872 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5873 hdd_err("attr interface type failed");
5874 return -EINVAL;
5875 }
5876
5877 intf_mode = nla_get_u32(tb
5878 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5879
5880 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5881 hdd_err("Invalid interface type");
5882 return -EINVAL;
5883 }
5884
5885 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5886 hdd_err("attr probable freq failed");
5887 return -EINVAL;
5888 }
5889
5890 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5891 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5892
5893 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005894 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 channel_hint, HW_MODE_20_MHZ)) {
5896 hdd_err("Set channel hint failed due to concurrency check");
5897 return -EINVAL;
5898 }
5899
Krunal Soni09e55032016-06-07 10:06:55 -07005900 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5901 hdd_warn("Remain On Channel Pending");
5902
Krunal Soni3091bcc2016-06-23 12:28:21 -07005903 ret = qdf_reset_connection_update();
5904 if (!QDF_IS_STATUS_SUCCESS(ret))
5905 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005906
Krunal Soni3091bcc2016-06-23 12:28:21 -07005907 ret = cds_current_connections_update(adapter->sessionId,
5908 channel_hint,
5909 SIR_UPDATE_REASON_SET_OPER_CHAN);
5910 if (QDF_STATUS_E_FAILURE == ret) {
5911 /* return in the failure case */
5912 hdd_err("ERROR: connections update failed!!");
5913 return -EINVAL;
5914 }
5915
5916 if (QDF_STATUS_SUCCESS == ret) {
5917 /*
5918 * Success is the only case for which we expect hw mode
5919 * change to take place, hence we need to wait.
5920 * For any other return value it should be a pass
5921 * through
5922 */
5923 ret = qdf_wait_for_connection_update();
5924 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5925 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926 return -EINVAL;
5927 }
5928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 }
5930
5931 return 0;
5932}
5933
5934/**
5935 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5936 * @wiphy: Pointer to wireless phy
5937 * @wdev: Pointer to wireless device
5938 * @data: Pointer to data
5939 * @data_len: Data length
5940 *
5941 * Return: 0 on success, negative errno on failure
5942 */
5943static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5944 struct wireless_dev *wdev,
5945 const void *data,
5946 int data_len)
5947{
5948 int ret = 0;
5949
5950 cds_ssr_protect(__func__);
5951 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5952 data, data_len);
5953 cds_ssr_unprotect(__func__);
5954
5955 return ret;
5956}
5957
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305958static const struct
5959nla_policy
5960qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5961 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5962};
5963
5964/**
5965 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5966 * @wiphy: WIPHY structure pointer
5967 * @wdev: Wireless device structure pointer
5968 * @data: Pointer to the data received
5969 * @data_len: Length of the data received
5970 *
5971 * This function is used to get link properties like nss, rate flags and
5972 * operating frequency for the active connection with the given peer.
5973 *
5974 * Return: 0 on success and errno on failure
5975 */
5976static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5977 struct wireless_dev *wdev,
5978 const void *data,
5979 int data_len)
5980{
5981 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5982 struct net_device *dev = wdev->netdev;
5983 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5984 hdd_station_ctx_t *hdd_sta_ctx;
5985 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305986 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305987 uint32_t sta_id;
5988 struct sk_buff *reply_skb;
5989 uint32_t rate_flags = 0;
5990 uint8_t nss;
5991 uint8_t final_rate_flags = 0;
5992 uint32_t freq;
5993
Jeff Johnson1f61b612016-02-12 16:28:33 -08005994 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305995
Anurag Chouhan6d760662016-02-20 16:05:43 +05305996 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305997 hdd_err("Command not allowed in FTM mode");
5998 return -EPERM;
5999 }
6000
6001 if (0 != wlan_hdd_validate_context(hdd_ctx))
6002 return -EINVAL;
6003
6004 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6005 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006006 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306007 return -EINVAL;
6008 }
6009
6010 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006011 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306012 adapter->device_mode);
6013 return -EINVAL;
6014 }
6015
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306016 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306017 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006018 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306019 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6020
Krunal Sonib4326f22016-03-10 13:05:51 -08006021 if (adapter->device_mode == QDF_STA_MODE ||
6022 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306023 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6024 if ((hdd_sta_ctx->conn_info.connState !=
6025 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306026 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306027 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006028 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306029 MAC_ADDR_ARRAY(peer_mac));
6030 return -EINVAL;
6031 }
6032
6033 nss = hdd_sta_ctx->conn_info.nss;
6034 freq = cds_chan_to_freq(
6035 hdd_sta_ctx->conn_info.operationChannel);
6036 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006037 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6038 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306039
6040 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6041 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306042 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306043 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306044 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306045 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306046 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306047 break;
6048 }
6049
6050 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006051 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306052 MAC_ADDR_ARRAY(peer_mac));
6053 return -EINVAL;
6054 }
6055
6056 nss = adapter->aStaInfo[sta_id].nss;
6057 freq = cds_chan_to_freq(
6058 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6059 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6060 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006061 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306062 MAC_ADDR_ARRAY(peer_mac));
6063 return -EINVAL;
6064 }
6065
6066 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6067 if (rate_flags & eHAL_TX_RATE_VHT80) {
6068 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006069#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306070 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006071#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306072 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6073 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006074#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306075 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006076#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6078 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6079 } else if (rate_flags &
6080 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6081 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006082#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306083 if (rate_flags & eHAL_TX_RATE_HT40)
6084 final_rate_flags |=
6085 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006086#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306087 }
6088
6089 if (rate_flags & eHAL_TX_RATE_SGI) {
6090 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6091 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6092 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6093 }
6094 }
6095
6096 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6097 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6098
6099 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006100 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306101 return -EINVAL;
6102 }
6103
6104 if (nla_put_u8(reply_skb,
6105 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6106 nss) ||
6107 nla_put_u8(reply_skb,
6108 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6109 final_rate_flags) ||
6110 nla_put_u32(reply_skb,
6111 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6112 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006113 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306114 kfree_skb(reply_skb);
6115 return -EINVAL;
6116 }
6117
6118 return cfg80211_vendor_cmd_reply(reply_skb);
6119}
6120
6121/**
6122 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6123 * properties.
6124 * @wiphy: WIPHY structure pointer
6125 * @wdev: Wireless device structure pointer
6126 * @data: Pointer to the data received
6127 * @data_len: Length of the data received
6128 *
6129 * This function is used to get link properties like nss, rate flags and
6130 * operating frequency for the active connection with the given peer.
6131 *
6132 * Return: 0 on success and errno on failure
6133 */
6134static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6135 struct wireless_dev *wdev,
6136 const void *data,
6137 int data_len)
6138{
6139 int ret = 0;
6140
6141 cds_ssr_protect(__func__);
6142 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6143 wdev, data, data_len);
6144 cds_ssr_unprotect(__func__);
6145
6146 return ret;
6147}
6148
Peng Xu278d0122015-09-24 16:34:17 -07006149static const struct
6150nla_policy
6151qca_wlan_vendor_ota_test_policy
6152[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6153 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6154};
6155
6156/**
6157 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6158 * @wiphy: Pointer to wireless phy
6159 * @wdev: Pointer to wireless device
6160 * @data: Pointer to data
6161 * @data_len: Data length
6162 *
6163 * Return: 0 on success, negative errno on failure
6164 */
6165static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6166 struct wireless_dev *wdev,
6167 const void *data,
6168 int data_len)
6169{
6170 struct net_device *dev = wdev->netdev;
6171 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6172 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6173 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6174 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6175 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306176 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006177 uint32_t current_roam_state;
6178
Jeff Johnson1f61b612016-02-12 16:28:33 -08006179 ENTER_DEV(dev);
6180
Anurag Chouhan6d760662016-02-20 16:05:43 +05306181 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006182 hdd_err("Command not allowed in FTM mode");
6183 return -EPERM;
6184 }
6185
6186 if (0 != wlan_hdd_validate_context(hdd_ctx))
6187 return -EINVAL;
6188
6189 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6190 data, data_len,
6191 qca_wlan_vendor_ota_test_policy)) {
6192 hdd_err("invalid attr");
6193 return -EINVAL;
6194 }
6195
6196 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6197 hdd_err("attr ota test failed");
6198 return -EINVAL;
6199 }
6200
6201 ota_enable = nla_get_u8(
6202 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6203
6204 hdd_info(" OTA test enable = %d", ota_enable);
6205 if (ota_enable != 1) {
6206 hdd_err("Invalid value, only enable test mode is supported!");
6207 return -EINVAL;
6208 }
6209
6210 current_roam_state =
6211 sme_get_current_roam_state(hal, adapter->sessionId);
6212 status = sme_stop_roaming(hal, adapter->sessionId,
6213 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306214 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006215 hdd_err("Enable/Disable roaming failed");
6216 return -EINVAL;
6217 }
6218
6219 status = sme_ps_enable_disable(hal, adapter->sessionId,
6220 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306221 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006222 hdd_err("Enable/Disable power save failed");
6223 /* restore previous roaming setting */
6224 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6225 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6226 status = sme_start_roaming(hal, adapter->sessionId,
6227 eCsrHddIssued);
6228 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6229 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6230 status = sme_stop_roaming(hal, adapter->sessionId,
6231 eCsrHddIssued);
6232
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306233 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006234 hdd_err("Restoring roaming state failed");
6235
6236 return -EINVAL;
6237 }
6238
6239
6240 return 0;
6241}
6242
6243/**
6244 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6245 * @wiphy: Pointer to wireless phy
6246 * @wdev: Pointer to wireless device
6247 * @data: Pointer to data
6248 * @data_len: Data length
6249 *
6250 * Return: 0 on success, negative errno on failure
6251 */
6252static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6253 struct wireless_dev *wdev,
6254 const void *data,
6255 int data_len)
6256{
6257 int ret = 0;
6258
6259 cds_ssr_protect(__func__);
6260 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6261 cds_ssr_unprotect(__func__);
6262
6263 return ret;
6264}
6265
Peng Xu4d67c8f2015-10-16 16:02:26 -07006266/**
6267 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6268 * @wiphy: Pointer to wireless phy
6269 * @wdev: Pointer to wireless device
6270 * @data: Pointer to data
6271 * @data_len: Data length
6272 *
6273 * Return: 0 on success, negative errno on failure
6274 */
6275static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6276 struct wireless_dev *wdev,
6277 const void *data,
6278 int data_len)
6279{
6280 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6281 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006282 hdd_adapter_t *adapter;
6283 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006284 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6285 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006286 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006287
Jeff Johnson1f61b612016-02-12 16:28:33 -08006288 ENTER_DEV(dev);
6289
Peng Xu4d67c8f2015-10-16 16:02:26 -07006290 ret = wlan_hdd_validate_context(hdd_ctx);
6291 if (ret)
6292 return ret;
6293
6294 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6295
6296 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6297 data, data_len, NULL)) {
6298 hdd_err("Invalid ATTR");
6299 return -EINVAL;
6300 }
6301
6302 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6303 hdd_err("attr tx power scale failed");
6304 return -EINVAL;
6305 }
6306
6307 scale_value = nla_get_u8(tb
6308 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6309
6310 if (scale_value > MAX_TXPOWER_SCALE) {
6311 hdd_err("Invalid tx power scale level");
6312 return -EINVAL;
6313 }
6314
Peng Xu62c8c432016-05-09 15:23:02 -07006315 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006316
Peng Xu62c8c432016-05-09 15:23:02 -07006317 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006318 hdd_err("Set tx power scale failed");
6319 return -EINVAL;
6320 }
6321
6322 return 0;
6323}
6324
6325/**
6326 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6327 * @wiphy: Pointer to wireless phy
6328 * @wdev: Pointer to wireless device
6329 * @data: Pointer to data
6330 * @data_len: Data length
6331 *
6332 * Return: 0 on success, negative errno on failure
6333 */
6334static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6335 struct wireless_dev *wdev,
6336 const void *data,
6337 int data_len)
6338{
Peng Xu62c8c432016-05-09 15:23:02 -07006339 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006340
6341 cds_ssr_protect(__func__);
6342 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6343 data, data_len);
6344 cds_ssr_unprotect(__func__);
6345
6346 return ret;
6347}
6348
6349/**
6350 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6351 * @wiphy: Pointer to wireless phy
6352 * @wdev: Pointer to wireless device
6353 * @data: Pointer to data
6354 * @data_len: Data length
6355 *
6356 * Return: 0 on success, negative errno on failure
6357 */
6358static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6359 struct wireless_dev *wdev,
6360 const void *data,
6361 int data_len)
6362{
6363 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6364 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006365 hdd_adapter_t *adapter;
6366 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006367 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6368 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006369 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006370
Jeff Johnson1f61b612016-02-12 16:28:33 -08006371 ENTER_DEV(dev);
6372
Peng Xu4d67c8f2015-10-16 16:02:26 -07006373 ret = wlan_hdd_validate_context(hdd_ctx);
6374 if (ret)
6375 return ret;
6376
6377 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6378
6379 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6380 data, data_len, NULL)) {
6381 hdd_err("Invalid ATTR");
6382 return -EINVAL;
6383 }
6384
6385 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6386 hdd_err("attr tx power decrease db value failed");
6387 return -EINVAL;
6388 }
6389
6390 scale_value = nla_get_u8(tb
6391 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6392
Peng Xu62c8c432016-05-09 15:23:02 -07006393 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6394 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006395
Peng Xu62c8c432016-05-09 15:23:02 -07006396 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006397 hdd_err("Set tx power decrease db failed");
6398 return -EINVAL;
6399 }
6400
6401 return 0;
6402}
6403
6404/**
6405 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6406 * @wiphy: Pointer to wireless phy
6407 * @wdev: Pointer to wireless device
6408 * @data: Pointer to data
6409 * @data_len: Data length
6410 *
6411 * Return: 0 on success, negative errno on failure
6412 */
6413static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6414 struct wireless_dev *wdev,
6415 const void *data,
6416 int data_len)
6417{
Peng Xu62c8c432016-05-09 15:23:02 -07006418 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006419
6420 cds_ssr_protect(__func__);
6421 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6422 data, data_len);
6423 cds_ssr_unprotect(__func__);
6424
6425 return ret;
6426}
Peng Xu8fdaa492016-06-22 10:20:47 -07006427
6428/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306429 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6430 * @wiphy: Pointer to wireless phy
6431 * @wdev: Pointer to wireless device
6432 * @data: Pointer to data
6433 * @data_len: Data length
6434 *
6435 * Processes the conditional channel switch request and invokes the helper
6436 * APIs to process the channel switch request.
6437 *
6438 * Return: 0 on success, negative errno on failure
6439 */
6440static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6441 struct wireless_dev *wdev,
6442 const void *data,
6443 int data_len)
6444{
6445 int ret;
6446 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6447 struct net_device *dev = wdev->netdev;
6448 hdd_adapter_t *adapter;
6449 struct nlattr
6450 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6451 uint32_t freq_len, i;
6452 uint32_t *freq;
6453 uint8_t chans[QDF_MAX_NUM_CHAN];
6454
6455 ENTER_DEV(dev);
6456
6457 ret = wlan_hdd_validate_context(hdd_ctx);
6458 if (ret)
6459 return ret;
6460
6461 if (!hdd_ctx->config->enableDFSMasterCap) {
6462 hdd_err("DFS master capability is not present in the driver");
6463 return -EINVAL;
6464 }
6465
6466 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6467 hdd_err("Command not allowed in FTM mode");
6468 return -EPERM;
6469 }
6470
6471 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6472 if (adapter->device_mode != QDF_SAP_MODE) {
6473 hdd_err("Invalid device mode %d", adapter->device_mode);
6474 return -EINVAL;
6475 }
6476
6477 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6478 data, data_len, NULL)) {
6479 hdd_err("Invalid ATTR");
6480 return -EINVAL;
6481 }
6482
6483 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6484 hdd_err("Frequency list is missing");
6485 return -EINVAL;
6486 }
6487
6488 freq_len = nla_len(
6489 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6490 sizeof(uint32_t);
6491
6492 if (freq_len > QDF_MAX_NUM_CHAN) {
6493 hdd_err("insufficient space to hold channels");
6494 return -ENOMEM;
6495 }
6496
6497 hdd_debug("freq_len=%d", freq_len);
6498
6499 freq = nla_data(
6500 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6501
6502
6503 for (i = 0; i < freq_len; i++) {
6504 if (freq[i] == 0)
6505 chans[i] = 0;
6506 else
6507 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6508
6509 hdd_debug("freq[%d]=%d", i, freq[i]);
6510 }
6511
6512 /*
6513 * The input frequency list from user space is designed to be a
6514 * priority based frequency list. This is only to accommodate any
6515 * future request. But, current requirement is only to perform CAC
6516 * on a single channel. So, the first entry from the list is picked.
6517 *
6518 * If channel is zero, any channel in the available outdoor regulatory
6519 * domain will be selected.
6520 */
6521 ret = wlan_hdd_request_pre_cac(chans[0]);
6522 if (ret) {
6523 hdd_err("pre cac request failed with reason:%d", ret);
6524 return ret;
6525 }
6526
6527 return 0;
6528}
6529
6530/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006531 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6532 * @wiphy: Pointer to wireless phy
6533 * @wdev: Pointer to wireless device
6534 * @data: Pointer to data
6535 * @data_len: Data length
6536 *
6537 * This function is to process the p2p listen offload start vendor
6538 * command. It parses the input parameters and invoke WMA API to
6539 * send the command to firmware.
6540 *
6541 * Return: 0 on success, negative errno on failure
6542 */
6543static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6544 struct wireless_dev *wdev,
6545 const void *data,
6546 int data_len)
6547{
6548 int ret;
6549 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6550 struct net_device *dev = wdev->netdev;
6551 hdd_adapter_t *adapter;
6552 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6553 struct sir_p2p_lo_start params;
6554 QDF_STATUS status;
6555
6556 ENTER_DEV(dev);
6557
6558 ret = wlan_hdd_validate_context(hdd_ctx);
6559 if (ret)
6560 return ret;
6561
6562 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6563 hdd_err("Command not allowed in FTM mode");
6564 return -EPERM;
6565 }
6566
6567 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6568 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6569 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6570 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6571 hdd_err("Invalid device mode %d", adapter->device_mode);
6572 return -EINVAL;
6573 }
6574
6575 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6576 data, data_len, NULL)) {
6577 hdd_err("Invalid ATTR");
6578 return -EINVAL;
6579 }
6580
6581 memset(&params, 0, sizeof(params));
6582
6583 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6584 params.ctl_flags = 1; /* set to default value */
6585 else
6586 params.ctl_flags = nla_get_u32(tb
6587 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6588
6589 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6590 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6591 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6592 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6593 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6594 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6595 hdd_err("Attribute parsing failed");
6596 return -EINVAL;
6597 }
6598
6599 params.vdev_id = adapter->sessionId;
6600 params.freq = nla_get_u32(tb
6601 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6602 if ((params.freq != 2412) && (params.freq != 2437) &&
6603 (params.freq != 2462)) {
6604 hdd_err("Invalid listening channel: %d", params.freq);
6605 return -EINVAL;
6606 }
6607
6608 params.period = nla_get_u32(tb
6609 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6610 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6611 hdd_err("Invalid period: %d", params.period);
6612 return -EINVAL;
6613 }
6614
6615 params.interval = nla_get_u32(tb
6616 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6617 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6618 hdd_err("Invalid interval: %d", params.interval);
6619 return -EINVAL;
6620 }
6621
6622 params.count = nla_get_u32(tb
6623 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006624 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006625 hdd_err("Invalid count: %d", params.count);
6626 return -EINVAL;
6627 }
6628
6629 params.device_types = nla_data(tb
6630 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6631 if (params.device_types == NULL) {
6632 hdd_err("Invalid device types");
6633 return -EINVAL;
6634 }
6635
6636 params.dev_types_len = nla_len(tb
6637 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6638 if (params.dev_types_len < 8) {
6639 hdd_err("Invalid device type length: %d", params.dev_types_len);
6640 return -EINVAL;
6641 }
6642
6643 params.probe_resp_tmplt = nla_data(tb
6644 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6645 if (params.probe_resp_tmplt == NULL) {
6646 hdd_err("Invalid probe response template");
6647 return -EINVAL;
6648 }
6649
6650 params.probe_resp_len = nla_len(tb
6651 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6652 if (params.probe_resp_len == 0) {
6653 hdd_err("Invalid probe resp template length: %d",
6654 params.probe_resp_len);
6655 return -EINVAL;
6656 }
6657
6658 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6659 params.freq, params.period, params.interval, params.count);
6660
6661 status = wma_p2p_lo_start(&params);
6662
6663 if (!QDF_IS_STATUS_SUCCESS(status)) {
6664 hdd_err("P2P LO start failed");
6665 return -EINVAL;
6666 }
6667
6668 return 0;
6669}
6670
6671
6672/**
6673 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6674 * @wiphy: Pointer to wireless phy
6675 * @wdev: Pointer to wireless device
6676 * @data: Pointer to data
6677 * @data_len: Data length
6678 *
6679 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6680 * to process p2p listen offload start vendor command.
6681 *
6682 * Return: 0 on success, negative errno on failure
6683 */
6684static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6685 struct wireless_dev *wdev,
6686 const void *data,
6687 int data_len)
6688{
6689 int ret = 0;
6690
6691 cds_ssr_protect(__func__);
6692 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6693 data, data_len);
6694 cds_ssr_unprotect(__func__);
6695
6696 return ret;
6697}
6698
6699/**
6700 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6701 * @wiphy: Pointer to wireless phy
6702 * @wdev: Pointer to wireless device
6703 * @data: Pointer to data
6704 * @data_len: Data length
6705 *
6706 * This function is to process the p2p listen offload stop vendor
6707 * command. It invokes WMA API to send command to firmware.
6708 *
6709 * Return: 0 on success, negative errno on failure
6710 */
6711static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6712 struct wireless_dev *wdev,
6713 const void *data,
6714 int data_len)
6715{
6716 QDF_STATUS status;
6717 hdd_adapter_t *adapter;
6718 struct net_device *dev = wdev->netdev;
6719
6720 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6721 hdd_err("Command not allowed in FTM mode");
6722 return -EPERM;
6723 }
6724
6725 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6726 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6727 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6728 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6729 hdd_err("Invalid device mode");
6730 return -EINVAL;
6731 }
6732
6733 status = wma_p2p_lo_stop(adapter->sessionId);
6734
6735 if (!QDF_IS_STATUS_SUCCESS(status)) {
6736 hdd_err("P2P LO stop failed");
6737 return -EINVAL;
6738 }
6739
6740 return 0;
6741}
6742
6743/**
6744 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6745 * @wiphy: Pointer to wireless phy
6746 * @wdev: Pointer to wireless device
6747 * @data: Pointer to data
6748 * @data_len: Data length
6749 *
6750 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6751 * to process p2p listen offload stop vendor command.
6752 *
6753 * Return: 0 on success, negative errno on failure
6754 */
6755static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6756 struct wireless_dev *wdev,
6757 const void *data,
6758 int data_len)
6759{
6760 int ret = 0;
6761
6762 cds_ssr_protect(__func__);
6763 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6764 data, data_len);
6765 cds_ssr_unprotect(__func__);
6766
6767 return ret;
6768}
6769
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306770/**
6771 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6772 * @wiphy: Pointer to wireless phy
6773 * @wdev: Pointer to wireless device
6774 * @data: Pointer to data
6775 * @data_len: Data length
6776 *
6777 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6778 * to process the conditional channel switch request.
6779 *
6780 * Return: 0 on success, negative errno on failure
6781 */
6782static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6783 struct wireless_dev *wdev,
6784 const void *data,
6785 int data_len)
6786{
6787 int ret;
6788
6789 cds_ssr_protect(__func__);
6790 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6791 data, data_len);
6792 cds_ssr_unprotect(__func__);
6793
6794 return ret;
6795}
6796
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306797/*
6798 * define short names for the global vendor params
6799 * used by __wlan_hdd_cfg80211_bpf_offload()
6800 */
6801#define BPF_INVALID \
6802 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6803#define BPF_SET_RESET \
6804 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6805#define BPF_VERSION \
6806 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6807#define BPF_FILTER_ID \
6808 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6809#define BPF_PACKET_SIZE \
6810 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6811#define BPF_CURRENT_OFFSET \
6812 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6813#define BPF_PROGRAM \
6814 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6815#define BPF_MAX \
6816 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006817
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306818static const struct nla_policy
6819wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6820 [BPF_SET_RESET] = {.type = NLA_U32},
6821 [BPF_VERSION] = {.type = NLA_U32},
6822 [BPF_FILTER_ID] = {.type = NLA_U32},
6823 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6824 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6825 [BPF_PROGRAM] = {.type = NLA_U8},
6826};
6827
6828/**
6829 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6830 * @hdd_context: hdd_context
6831 * @bpf_get_offload: struct for get offload
6832 *
6833 * This function receives the response/data from the lower layer and
6834 * checks to see if the thread is still waiting then post the results to
6835 * upper layer, if the request has timed out then ignore.
6836 *
6837 * Return: None
6838 */
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006839static void hdd_get_bpf_offload_cb(void *hdd_context,
6840 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306841{
6842 hdd_context_t *hdd_ctx = hdd_context;
6843 struct hdd_bpf_context *context;
6844
6845 ENTER();
6846
6847 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006848 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306849 data);
6850 return;
6851 }
6852
6853 spin_lock(&hdd_context_lock);
6854
6855 context = &bpf_context;
6856 /* The caller presumably timed out so there is nothing we can do */
6857 if (context->magic != BPF_CONTEXT_MAGIC) {
6858 spin_unlock(&hdd_context_lock);
6859 return;
6860 }
6861
6862 /* context is valid so caller is still waiting */
6863 /* paranoia: invalidate the magic */
6864 context->magic = 0;
6865
6866 context->capability_response = *data;
6867 complete(&context->completion);
6868
6869 spin_unlock(&hdd_context_lock);
6870
6871 return;
6872}
6873
6874/**
6875 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6876 * @hdd_context: hdd_context
6877 * @bpf_get_offload: struct for get offload
6878 *
6879 * Return: 0 on success, error number otherwise.
6880 */
6881static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6882 struct sir_bpf_get_offload *bpf_get_offload)
6883{
6884 struct sk_buff *skb;
6885 uint32_t nl_buf_len;
6886
6887 ENTER();
6888
6889 nl_buf_len = NLMSG_HDRLEN;
6890 nl_buf_len +=
6891 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6892 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6893
6894 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6895 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006896 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306897 return -ENOMEM;
6898 }
6899
Jeff Johnson77848112016-06-29 14:52:06 -07006900 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306901 bpf_get_offload->bpf_version,
6902 bpf_get_offload->max_bytes_for_bpf_inst);
6903
6904 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6905 bpf_get_offload->max_bytes_for_bpf_inst) ||
6906 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006907 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306908 goto nla_put_failure;
6909 }
6910
6911 cfg80211_vendor_cmd_reply(skb);
6912 EXIT();
6913 return 0;
6914
6915nla_put_failure:
6916 kfree_skb(skb);
6917 return -EINVAL;
6918}
6919
6920/**
6921 * hdd_get_bpf_offload - Get BPF offload Capabilities
6922 * @hdd_ctx: Hdd context
6923 *
6924 * Return: 0 on success, errno on failure
6925 */
6926static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6927{
6928 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006929 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306930 QDF_STATUS status;
6931 int ret;
6932
6933 ENTER();
6934
6935 spin_lock(&hdd_context_lock);
6936 context = &bpf_context;
6937 context->magic = BPF_CONTEXT_MAGIC;
6938 INIT_COMPLETION(context->completion);
6939 spin_unlock(&hdd_context_lock);
6940
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006941 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6942 hdd_get_bpf_offload_cb,
6943 hdd_ctx);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306944 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006945 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306946 return -EINVAL;
6947 }
6948 /* request was sent -- wait for the response */
6949 rc = wait_for_completion_timeout(&context->completion,
6950 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6951 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006952 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306953 spin_lock(&hdd_context_lock);
6954 context->magic = 0;
6955 spin_unlock(&hdd_context_lock);
6956
6957 return -ETIMEDOUT;
6958 }
6959 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6960 &bpf_context.capability_response);
6961 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006962 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306963
6964 EXIT();
6965 return ret;
6966}
6967
6968/**
6969 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6970 * @hdd_ctx: Hdd context
6971 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306972 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306973 *
6974 * Return: 0 on success; errno on failure
6975 */
6976static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6977 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306978 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306979{
6980 struct sir_bpf_set_offload *bpf_set_offload;
6981 QDF_STATUS status;
6982 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306983 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306984
6985 ENTER();
6986
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306987 if (adapter->device_mode == QDF_STA_MODE ||
6988 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6989 if (!hdd_conn_is_connected(
6990 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6991 hdd_err("Not in Connected state!");
6992 return -ENOTSUPP;
6993 }
6994 }
6995
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306996 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6997 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006998 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306999 return -ENOMEM;
7000 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307001
7002 /* Parse and fetch bpf packet size */
7003 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007004 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307005 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307006 goto fail;
7007 }
7008 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7009
7010 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007011 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307012 goto post_sme;
7013 }
7014
7015 /* Parse and fetch bpf program */
7016 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007017 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307018 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307019 goto fail;
7020 }
7021
7022 prog_len = nla_len(tb[BPF_PROGRAM]);
7023 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307024
7025 if (bpf_set_offload->program == NULL) {
7026 hdd_err("qdf_mem_malloc failed for bpf offload program");
7027 ret = -ENOMEM;
7028 goto fail;
7029 }
7030
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307031 bpf_set_offload->current_length = prog_len;
7032 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307033 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307034
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307035 hdd_info("BPF set instructions");
7036 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7037 bpf_set_offload->program, prog_len);
7038
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307039 /* Parse and fetch filter Id */
7040 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007041 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307042 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307043 goto fail;
7044 }
7045 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7046
7047 /* Parse and fetch current offset */
7048 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007049 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307050 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307051 goto fail;
7052 }
7053 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7054
7055post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007056 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 +05307057 bpf_set_offload->session_id,
7058 bpf_set_offload->version,
7059 bpf_set_offload->filter_id,
7060 bpf_set_offload->total_length,
7061 bpf_set_offload->current_length,
7062 bpf_set_offload->current_offset);
7063
7064 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7065 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007066 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307067 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307068 goto fail;
7069 }
7070 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307071
7072fail:
7073 if (bpf_set_offload->current_length)
7074 qdf_mem_free(bpf_set_offload->program);
7075 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307076 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307077}
7078
7079/**
7080 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7081 * @wiphy: wiphy structure pointer
7082 * @wdev: Wireless device structure pointer
7083 * @data: Pointer to the data received
7084 * @data_len: Length of @data
7085 *
7086 * Return: 0 on success; errno on failure
7087 */
7088static int
7089__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7090 struct wireless_dev *wdev,
7091 const void *data, int data_len)
7092{
7093 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7094 struct net_device *dev = wdev->netdev;
7095 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7096 struct nlattr *tb[BPF_MAX + 1];
7097 int ret_val, packet_filter_subcmd;
7098
7099 ENTER();
7100
7101 ret_val = wlan_hdd_validate_context(hdd_ctx);
7102 if (ret_val)
7103 return ret_val;
7104
7105 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007106 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307107 return -EINVAL;
7108 }
7109
7110 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007111 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307112 return -ENOTSUPP;
7113 }
7114
7115 if (nla_parse(tb, BPF_MAX, data, data_len,
7116 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007117 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307118 return -EINVAL;
7119 }
7120
7121 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007122 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307123 return -EINVAL;
7124 }
7125
7126 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7127
7128 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7129 return hdd_get_bpf_offload(hdd_ctx);
7130 else
7131 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307132 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307133}
7134
7135/**
7136 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7137 * @wiphy: wiphy structure pointer
7138 * @wdev: Wireless device structure pointer
7139 * @data: Pointer to the data received
7140 * @data_len: Length of @data
7141 *
7142 * Return: 0 on success; errno on failure
7143 */
7144
7145static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7146 struct wireless_dev *wdev,
7147 const void *data, int data_len)
7148{
7149 int ret;
7150
7151 cds_ssr_protect(__func__);
7152 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7153 cds_ssr_unprotect(__func__);
7154
7155 return ret;
7156}
7157
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307158/**
7159 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7160 * @pre_cac_adapter: AP adapter used for pre cac
7161 * @status: Status (true or false)
7162 * @handle: Global handle
7163 *
7164 * Sets the status of pre cac i.e., whether the pre cac is active or not
7165 *
7166 * Return: Zero on success, non-zero on failure
7167 */
7168static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7169 bool status, tHalHandle handle)
7170{
7171 QDF_STATUS ret;
7172
7173 ret = wlan_sap_set_pre_cac_status(
7174 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7175 if (QDF_IS_STATUS_ERROR(ret))
7176 return -EINVAL;
7177
7178 return 0;
7179}
7180
7181/**
7182 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7183 * @ap_adapter: AP adapter
7184 * @chan_before_pre_cac: Channel
7185 *
7186 * Saves the channel which the AP was beaconing on before moving to the pre
7187 * cac channel. If radar is detected on the pre cac channel, this saved
7188 * channel will be used for AP operations.
7189 *
7190 * Return: Zero on success, non-zero on failure
7191 */
7192static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7193 uint8_t chan_before_pre_cac)
7194{
7195 QDF_STATUS ret;
7196
7197 ret = wlan_sap_set_chan_before_pre_cac(
7198 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7199 if (QDF_IS_STATUS_ERROR(ret))
7200 return -EINVAL;
7201
7202 return 0;
7203}
7204
7205/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307206 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7207 * are in nol list from provided channel list
7208 * @adapter: AP adapter
7209 * @channel_count: channel count
7210 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307211 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307212 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307213 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307214static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7215 uint32_t *channel_count,
7216 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307217{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307218 uint8_t i, j;
7219 uint32_t nol_len = 0;
7220 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7221 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7222 uint32_t chan_count;
7223 bool found;
7224 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307225
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307226 if (!hdd_ctx) {
7227 hdd_err("hdd ctx not found");
7228 *channel_count = 0;
7229 return;
7230 }
7231
7232 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7233 hdd_err("invalid channel count %d", *channel_count);
7234 return;
7235 }
7236
7237 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7238 if (nol_len == 0)
7239 return;
7240
7241 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7242 chan_count = *channel_count;
7243 qdf_mem_zero(channel_list, chan_count);
7244 *channel_count = 0;
7245
7246 for (i = 0 ; i < chan_count; i++) {
7247 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7248 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7249 continue;
7250 found = false;
7251 for (j = 0; j < nol_len; j++) {
7252 if (tmp_chan_list[i] == nol[j]) {
7253 found = true;
7254 hdd_notice("skipped channel %d due to nol",
7255 nol[j]);
7256 break;
7257 }
7258 }
7259 if (!found) {
7260 channel_list[*channel_count] = tmp_chan_list[i];
7261 *channel_count = *channel_count + 1;
7262 }
7263 }
7264}
7265
7266int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7267 uint32_t *channel_count,
7268 uint8_t *channel_list)
7269{
7270 tsap_Config_t *sap_config;
7271
7272 sap_config = &adapter->sessionCtx.ap.sapConfig;
7273
7274 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7275 sap_config->acs_cfg.ch_list_count);
7276 *channel_count = sap_config->acs_cfg.ch_list_count;
7277 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7278
7279 if (*channel_count == 0) {
7280 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307281 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307282 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307283
7284 return 0;
7285}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307286
7287/**
7288 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7289 * @hdd_ctx: HDD context
7290 * @ap_adapter: AP adapter
7291 * @channel: Channel requested by userspace
7292 * @pre_cac_chan: Pointer to the pre CAC channel
7293 *
7294 * Validates the channel provided by userspace. If user provided channel 0,
7295 * a valid outdoor channel must be selected from the regulatory channel.
7296 *
7297 * Return: Zero on success and non zero value on error
7298 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007299static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7300 hdd_adapter_t *ap_adapter,
7301 uint8_t channel,
7302 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307303{
7304 uint32_t i, j;
7305 QDF_STATUS status;
7306 int ret;
7307 uint8_t nol[QDF_MAX_NUM_CHAN];
7308 uint32_t nol_len = 0, weight_len = 0;
7309 bool found;
7310 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7311 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7312 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7313
7314 if (0 == channel) {
7315 /* Channel is not obtained from PCL because PCL may not have
7316 * the entire channel list. For example: if SAP is up on
7317 * channel 6 and PCL is queried for the next SAP interface,
7318 * if SCC is preferred, the PCL will contain only the channel
7319 * 6. But, we are in need of a DFS channel. So, going with the
7320 * first channel from the valid channel list.
7321 */
7322 status = cds_get_valid_chans(channel_list, &len);
7323 if (QDF_IS_STATUS_ERROR(status)) {
7324 hdd_err("Failed to get channel list");
7325 return -EINVAL;
7326 }
7327 cds_update_with_safe_channel_list(channel_list, &len,
7328 pcl_weights, weight_len);
7329 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7330 for (i = 0; i < len; i++) {
7331 found = false;
7332 for (j = 0; j < nol_len; j++) {
7333 if (channel_list[i] == nol[j]) {
7334 found = true;
7335 break;
7336 }
7337 }
7338 if (found)
7339 continue;
7340 if (CDS_IS_DFS_CH(channel_list[i])) {
7341 *pre_cac_chan = channel_list[i];
7342 break;
7343 }
7344 }
7345 if (*pre_cac_chan == 0) {
7346 hdd_err("unable to find outdoor channel");
7347 return -EINVAL;
7348 }
7349 } else {
7350 /* Only when driver selects a channel, check is done for
7351 * unnsafe and NOL channels. When user provides a fixed channel
7352 * the user is expected to take care of this.
7353 */
7354 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7355 !CDS_IS_DFS_CH(channel)) {
7356 hdd_err("Invalid channel for pre cac:%d", channel);
7357 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307358 }
Jeff Johnson68755312017-02-10 11:46:55 -08007359
7360 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307361 }
7362 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7363 return 0;
7364}
7365
7366/**
7367 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7368 * @channel: Channel option provided by userspace
7369 *
7370 * Sets the driver to the required hardware mode and start an adapater for
7371 * pre CAC which will mimic an AP.
7372 *
7373 * Return: Zero on success, non-zero value on error
7374 */
7375int wlan_hdd_request_pre_cac(uint8_t channel)
7376{
Krunal Sonib37bb352016-12-20 14:12:21 -08007377 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307378 hdd_context_t *hdd_ctx;
7379 int ret;
7380 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7381 hdd_ap_ctx_t *hdd_ap_ctx;
7382 QDF_STATUS status;
7383 struct wiphy *wiphy;
7384 struct net_device *dev;
7385 struct cfg80211_chan_def chandef;
7386 enum nl80211_channel_type channel_type;
7387 uint32_t freq;
7388 struct ieee80211_channel *chan;
7389 tHalHandle handle;
7390 bool val;
7391
7392 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7393 if (0 != wlan_hdd_validate_context(hdd_ctx))
7394 return -EINVAL;
7395
7396 if (cds_get_connection_count() > 1) {
7397 hdd_err("pre cac not allowed in concurrency");
7398 return -EINVAL;
7399 }
7400
7401 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7402 if (!ap_adapter) {
7403 hdd_err("unable to get SAP adapter");
7404 return -EINVAL;
7405 }
7406
7407 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7408 if (!handle) {
7409 hdd_err("Invalid handle");
7410 return -EINVAL;
7411 }
7412
7413 val = wlan_sap_is_pre_cac_active(handle);
7414 if (val) {
7415 hdd_err("pre cac is already in progress");
7416 return -EINVAL;
7417 }
7418
7419 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7420 if (!hdd_ap_ctx) {
7421 hdd_err("SAP context is NULL");
7422 return -EINVAL;
7423 }
7424
7425 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7426 hdd_err("SAP is already on DFS channel:%d",
7427 hdd_ap_ctx->operatingChannel);
7428 return -EINVAL;
7429 }
7430
7431 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7432 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7433 hdd_ap_ctx->operatingChannel);
7434 return -EINVAL;
7435 }
7436
Krunal Sonib37bb352016-12-20 14:12:21 -08007437 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7438 if (!mac_addr) {
7439 hdd_err("can't add virtual intf: Not getting valid mac addr");
7440 return -EINVAL;
7441 }
7442
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307443 hdd_info("channel:%d", channel);
7444
7445 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7446 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007447 if (ret != 0) {
7448 hdd_err("can't validate pre-cac channel");
7449 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307450 }
7451
7452 hdd_debug("starting pre cac SAP adapter");
7453
7454 /* Starting a SAP adapter:
7455 * Instead of opening an adapter, we could just do a SME open session
7456 * for AP type. But, start BSS would still need an adapter.
7457 * So, this option is not taken.
7458 *
7459 * hdd open adapter is going to register this precac interface with
7460 * user space. This interface though exposed to user space will be in
7461 * DOWN state. Consideration was done to avoid this registration to the
7462 * user space. But, as part of SAP operations multiple events are sent
7463 * to user space. Some of these events received from unregistered
7464 * interface was causing crashes. So, retaining the registration.
7465 *
7466 * So, this interface would remain registered and will remain in DOWN
7467 * state for the CAC duration. We will add notes in the feature
7468 * announcement to not use this temporary interface for any activity
7469 * from user space.
7470 */
7471 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007472 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307473 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307474 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007475 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307476 }
7477
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307478 /*
7479 * This interface is internally created by the driver. So, no interface
7480 * up comes for this interface from user space and hence starting
7481 * the adapter internally.
7482 */
7483 if (hdd_start_adapter(pre_cac_adapter)) {
7484 hdd_err("error starting the pre cac adapter");
7485 goto close_pre_cac_adapter;
7486 }
7487
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307488 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7489
7490 wiphy = hdd_ctx->wiphy;
7491 dev = pre_cac_adapter->dev;
7492
7493 /* Since this is only a dummy interface lets us use the IEs from the
7494 * other active SAP interface. In regular scenarios, these IEs would
7495 * come from the user space entity
7496 */
7497 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7498 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7499 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7500 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307501 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307502 }
7503 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7504 ap_adapter->sessionCtx.ap.beacon,
7505 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7506 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7507 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7508 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7509 ap_adapter->sessionCtx.ap.sapConfig.authType;
7510
7511 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7512 * to operate on the same bandwidth as that of the 2.4GHz operations.
7513 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7514 */
7515 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7516 case CH_WIDTH_20MHZ:
7517 channel_type = NL80211_CHAN_HT20;
7518 break;
7519 case CH_WIDTH_40MHZ:
7520 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7521 ap_adapter->sessionCtx.ap.sapConfig.channel)
7522 channel_type = NL80211_CHAN_HT40PLUS;
7523 else
7524 channel_type = NL80211_CHAN_HT40MINUS;
7525 break;
7526 default:
7527 channel_type = NL80211_CHAN_NO_HT;
7528 break;
7529 }
7530
7531 freq = cds_chan_to_freq(pre_cac_chan);
7532 chan = __ieee80211_get_channel(wiphy, freq);
7533 if (!chan) {
7534 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307535 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307536 }
7537
7538 cfg80211_chandef_create(&chandef, chan, channel_type);
7539
7540 hdd_debug("orig width:%d channel_type:%d freq:%d",
7541 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7542 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007543 /*
7544 * Doing update after opening and starting pre-cac adapter will make
7545 * sure that driver won't do hardware mode change if there are any
7546 * initial hick-ups or issues in pre-cac adapter's configuration.
7547 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7548 * connection update should result in DBS mode
7549 */
7550 status = cds_update_and_wait_for_connection_update(
7551 ap_adapter->sessionId,
7552 pre_cac_chan,
7553 SIR_UPDATE_REASON_PRE_CAC);
7554 if (QDF_IS_STATUS_ERROR(status)) {
7555 hdd_err("error in moving to DBS mode");
7556 goto stop_close_pre_cac_adapter;
7557 }
7558
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307559
7560 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7561 if (0 != ret) {
7562 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307563 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307564 }
7565
7566 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7567 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007568 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307569 if (QDF_IS_STATUS_ERROR(status)) {
7570 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307571 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307572 }
7573
7574 /*
7575 * The pre cac status is set here. But, it would not be reset explicitly
7576 * anywhere, since after the pre cac success/failure, the pre cac
7577 * adapter itself would be removed.
7578 */
7579 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7580 if (0 != ret) {
7581 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307582 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307583 }
7584
7585 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7586 hdd_ap_ctx->operatingChannel);
7587 if (0 != ret) {
7588 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307589 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307590 }
7591
7592 ap_adapter->pre_cac_chan = pre_cac_chan;
7593
7594 return 0;
7595
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307596stop_close_pre_cac_adapter:
7597 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307598 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7599 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307600close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307601 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007602release_intf_addr_and_return_failure:
7603 /*
7604 * Release the interface address as the adapter
7605 * failed to start, if you don't release then next
7606 * adapter which is trying to come wouldn't get valid
7607 * mac address. Remember we have limited pool of mac addresses
7608 */
7609 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307610 return -EINVAL;
7611}
7612
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307613/**
7614 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7615 *
7616 * Return: None
7617 */
7618void hdd_init_bpf_completion(void)
7619{
7620 init_completion(&bpf_context.completion);
7621}
7622
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307623static const struct nla_policy
7624wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7625 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7626};
7627
Agrawal Ashish65634612016-08-18 13:24:32 +05307628static const struct nla_policy
7629wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7630 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7631 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7632};
7633
7634/**
7635 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7636 * @wiphy: Pointer to wireless phy
7637 * @wdev: Pointer to wireless device
7638 * @data: Pointer to data
7639 * @data_len: Length of @data
7640 *
7641 * This function parses the incoming NL vendor command data attributes and
7642 * updates the SAP context about channel_hint and DFS mode.
7643 * If channel_hint is set, SAP will choose that channel
7644 * as operating channel.
7645 *
7646 * If DFS mode is enabled, driver will include DFS channels
7647 * in ACS else driver will skip DFS channels.
7648 *
7649 * Return: 0 on success, negative errno on failure
7650 */
7651static int
7652__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7653 struct wireless_dev *wdev,
7654 const void *data, int data_len)
7655{
7656 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7657 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7658 int ret;
7659 struct acs_dfs_policy *acs_policy;
7660 int mode = DFS_MODE_NONE;
7661 int channel_hint = 0;
7662
7663 ENTER_DEV(wdev->netdev);
7664
7665 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7666 hdd_err("Command not allowed in FTM mode");
7667 return -EINVAL;
7668 }
7669
7670 ret = wlan_hdd_validate_context(hdd_ctx);
7671 if (0 != ret)
7672 return ret;
7673
7674 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7675 data, data_len,
7676 wlan_hdd_set_acs_dfs_config_policy)) {
7677 hdd_err("invalid attr");
7678 return -EINVAL;
7679 }
7680
7681 acs_policy = &hdd_ctx->acs_policy;
7682 /*
7683 * SCM sends this attribute to restrict SAP from choosing
7684 * DFS channels from ACS.
7685 */
7686 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7687 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7688
7689 if (!IS_DFS_MODE_VALID(mode)) {
7690 hdd_err("attr acs dfs mode is not valid");
7691 return -EINVAL;
7692 }
7693 acs_policy->acs_dfs_mode = mode;
7694
7695 /*
7696 * SCM sends this attribute to provide an active channel,
7697 * to skip redundant ACS between drivers, and save driver start up time
7698 */
7699 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7700 channel_hint = nla_get_u8(
7701 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7702
7703 if (!IS_CHANNEL_VALID(channel_hint)) {
7704 hdd_err("acs channel is not valid");
7705 return -EINVAL;
7706 }
7707 acs_policy->acs_channel = channel_hint;
7708
7709 return 0;
7710}
7711
7712/**
7713 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7714 * @wiphy: wiphy structure pointer
7715 * @wdev: Wireless device structure pointer
7716 * @data: Pointer to the data received
7717 * @data_len: Length of @data
7718 *
7719 * This function parses the incoming NL vendor command data attributes and
7720 * updates the SAP context about channel_hint and DFS mode.
7721 *
7722 * Return: 0 on success; errno on failure
7723 */
7724static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7725 struct wireless_dev *wdev,
7726 const void *data, int data_len)
7727{
7728 int ret;
7729
7730 cds_ssr_protect(__func__);
7731 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7732 cds_ssr_unprotect(__func__);
7733
7734 return ret;
7735}
7736
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307737/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307738 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7739 * @mode : cfg80211 dfs mode
7740 *
7741 * Return: return csr sta roam dfs mode else return NONE
7742 */
7743static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7744 enum dfs_mode mode)
7745{
7746 switch (mode) {
7747 case DFS_MODE_ENABLE:
7748 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7749 break;
7750 case DFS_MODE_DISABLE:
7751 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7752 break;
7753 case DFS_MODE_DEPRIORITIZE:
7754 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7755 break;
7756 default:
7757 hdd_err("STA Roam policy dfs mode is NONE");
7758 return CSR_STA_ROAM_POLICY_NONE;
7759 }
7760}
7761
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307762/*
7763 * hdd_get_sap_operating_band: Get current operating channel
7764 * for sap.
7765 * @hdd_ctx: hdd context
7766 *
7767 * Return : Corresponding band for SAP operating channel
7768 */
7769uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7770{
7771 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7772 QDF_STATUS status;
7773 hdd_adapter_t *adapter;
7774 uint8_t operating_channel = 0;
7775 uint8_t sap_operating_band = 0;
7776 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7777 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7778 adapter = adapter_node->pAdapter;
7779
7780 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7781 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7782 &next);
7783 adapter_node = next;
7784 continue;
7785 }
7786 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7787 if (IS_24G_CH(operating_channel))
7788 sap_operating_band = eCSR_BAND_24;
7789 else if (IS_5G_CH(operating_channel))
7790 sap_operating_band = eCSR_BAND_5G;
7791 else
7792 sap_operating_band = eCSR_BAND_ALL;
7793 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7794 &next);
bings373b99b2017-01-23 10:35:08 +08007795 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307796 }
7797 return sap_operating_band;
7798}
7799
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307800static const struct nla_policy
7801wlan_hdd_set_sta_roam_config_policy[
7802QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7803 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7804 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7805};
7806
7807/**
7808 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7809 * for station connection or roaming.
7810 * @wiphy: Pointer to wireless phy
7811 * @wdev: Pointer to wireless device
7812 * @data: Pointer to data
7813 * @data_len: Length of @data
7814 *
7815 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7816 * channels needs to be skipped in scanning or not.
7817 * If dfs_mode is disabled, driver will not scan DFS channels.
7818 * If skip_unsafe_channels is set, driver will skip unsafe channels
7819 * in Scanning.
7820 *
7821 * Return: 0 on success, negative errno on failure
7822 */
7823static int
7824__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7825 struct wireless_dev *wdev,
7826 const void *data, int data_len)
7827{
7828 struct net_device *dev = wdev->netdev;
7829 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7830 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7831 struct nlattr *tb[
7832 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7833 int ret;
7834 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7835 enum dfs_mode mode = DFS_MODE_NONE;
7836 bool skip_unsafe_channels = false;
7837 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307838 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307839
7840 ENTER_DEV(dev);
7841
7842 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7843 hdd_err("Command not allowed in FTM mode");
7844 return -EINVAL;
7845 }
7846
7847 ret = wlan_hdd_validate_context(hdd_ctx);
7848 if (0 != ret)
7849 return ret;
7850 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7851 data, data_len,
7852 wlan_hdd_set_sta_roam_config_policy)) {
7853 hdd_err("invalid attr");
7854 return -EINVAL;
7855 }
7856 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7857 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7858 if (!IS_DFS_MODE_VALID(mode)) {
7859 hdd_err("attr sta roam dfs mode policy is not valid");
7860 return -EINVAL;
7861 }
7862
7863 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7864
7865 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7866 skip_unsafe_channels = nla_get_u8(
7867 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307868 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307869 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307870 skip_unsafe_channels, adapter->sessionId,
7871 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307872
7873 if (!QDF_IS_STATUS_SUCCESS(status)) {
7874 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7875 return -EINVAL;
7876 }
7877 return 0;
7878}
7879
7880/**
7881 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7882 * connection and roaming for station.
7883 * @wiphy: wiphy structure pointer
7884 * @wdev: Wireless device structure pointer
7885 * @data: Pointer to the data received
7886 * @data_len: Length of @data
7887 *
7888 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7889 * channels needs to be skipped in scanning or not.
7890 * If dfs_mode is disabled, driver will not scan DFS channels.
7891 * If skip_unsafe_channels is set, driver will skip unsafe channels
7892 * in Scanning.
7893 * Return: 0 on success; errno on failure
7894 */
7895static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7896 struct wireless_dev *wdev,
7897 const void *data, int data_len)
7898{
7899 int ret;
7900
7901 cds_ssr_protect(__func__);
7902 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7903 cds_ssr_unprotect(__func__);
7904
7905 return ret;
7906}
7907
Agrawal Ashish467dde42016-09-08 18:44:22 +05307908#ifdef FEATURE_WLAN_CH_AVOID
7909/**
7910 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7911 * is on unsafe channel.
7912 * @wiphy: wiphy structure pointer
7913 * @wdev: Wireless device structure pointer
7914 * @data: Pointer to the data received
7915 * @data_len: Length of @data
7916 *
7917 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7918 * on any of unsafe channels.
7919 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7920 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7921 *
7922 * Return: 0 on success; errno on failure
7923 */
7924static int
7925__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7926 struct wireless_dev *wdev,
7927 const void *data, int data_len)
7928{
7929 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7930 int ret;
7931 uint16_t unsafe_channel_count;
7932 int unsafe_channel_index;
7933 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7934
7935 ENTER_DEV(wdev->netdev);
7936
7937 if (!qdf_ctx) {
7938 cds_err("qdf_ctx is NULL");
7939 return -EINVAL;
7940 }
7941
7942 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7943 hdd_err("Command not allowed in FTM mode");
7944 return -EINVAL;
7945 }
7946
7947 ret = wlan_hdd_validate_context(hdd_ctx);
7948 if (0 != ret)
7949 return ret;
7950 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7951 &(hdd_ctx->unsafe_channel_count),
7952 sizeof(hdd_ctx->unsafe_channel_list));
7953
7954 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7955 (uint16_t)NUM_CHANNELS);
7956 for (unsafe_channel_index = 0;
7957 unsafe_channel_index < unsafe_channel_count;
7958 unsafe_channel_index++) {
7959 hdd_info("Channel %d is not safe",
7960 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7961 }
7962 hdd_unsafe_channel_restart_sap(hdd_ctx);
7963 return 0;
7964}
7965
7966/**
7967 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7968 * is on unsafe channel.
7969 * @wiphy: wiphy structure pointer
7970 * @wdev: Wireless device structure pointer
7971 * @data: Pointer to the data received
7972 * @data_len: Length of @data
7973 *
7974 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7975 * on any of unsafe channels.
7976 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7977 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7978 *
7979 * Return: 0 on success; errno on failure
7980 */
7981static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7982 struct wireless_dev *wdev,
7983 const void *data, int data_len)
7984{
7985 int ret;
7986
7987 cds_ssr_protect(__func__);
7988 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7989 cds_ssr_unprotect(__func__);
7990
7991 return ret;
7992}
7993
7994#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307995/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307996 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7997 * SAP is on unsafe channel.
7998 * @wiphy: wiphy structure pointer
7999 * @wdev: Wireless device structure pointer
8000 * @data: Pointer to the data received
8001 * @data_len: Length of @data
8002 *
8003 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8004 * driver.
8005 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8006 * will initiate restart of sap.
8007 *
8008 * Return: 0 on success; errno on failure
8009 */
8010static int
8011__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8012 struct wireless_dev *wdev,
8013 const void *data, int data_len)
8014{
8015 struct net_device *ndev = wdev->netdev;
8016 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8017 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8018 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8019 uint8_t config_channel = 0;
8020 hdd_ap_ctx_t *ap_ctx;
8021 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308022 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308023
8024 ENTER();
8025
8026 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008027 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308028 return -EINVAL;
8029 }
8030
8031 ret = wlan_hdd_validate_context(hdd_ctx);
8032 if (0 != ret)
8033 return -EINVAL;
8034
8035 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8036 data, data_len,
8037 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008038 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308039 return -EINVAL;
8040 }
8041
8042 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8043 if (!test_bit(SOFTAP_BSS_STARTED,
8044 &hostapd_adapter->event_flags)) {
8045 hdd_err("SAP is not started yet. Restart sap will be invalid");
8046 return -EINVAL;
8047 }
8048
8049 config_channel =
8050 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8051
8052 if (!((IS_24G_CH(config_channel)) ||
8053 (IS_5G_CH(config_channel)))) {
8054 hdd_err("Channel %d is not valid to restart SAP",
8055 config_channel);
8056 return -ENOTSUPP;
8057 }
8058
8059 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8060 ap_ctx->sapConfig.channel = config_channel;
8061 ap_ctx->sapConfig.ch_params.ch_width =
8062 ap_ctx->sapConfig.ch_width_orig;
8063
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008064 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308065 ap_ctx->sapConfig.sec_ch,
8066 &ap_ctx->sapConfig.ch_params);
8067
8068 cds_restart_sap(hostapd_adapter);
8069 }
8070
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308071 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8072 uint32_t freq_len, i;
8073 uint32_t *freq;
8074 uint8_t chans[QDF_MAX_NUM_CHAN];
8075
8076 hdd_debug("setting mandatory freq/chan list");
8077
8078 freq_len = nla_len(
8079 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8080 sizeof(uint32_t);
8081
8082 if (freq_len > QDF_MAX_NUM_CHAN) {
8083 hdd_err("insufficient space to hold channels");
8084 return -ENOMEM;
8085 }
8086
8087 freq = nla_data(
8088 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8089
8090 hdd_debug("freq_len=%d", freq_len);
8091
8092 for (i = 0; i < freq_len; i++) {
8093 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8094 hdd_debug("freq[%d]=%d", i, freq[i]);
8095 }
8096
8097 status = cds_set_sap_mandatory_channels(chans, freq_len);
8098 if (QDF_IS_STATUS_ERROR(status))
8099 return -EINVAL;
8100 }
8101
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308102 return 0;
8103}
8104
8105/**
8106 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8107 * @wiphy: wiphy structure pointer
8108 * @wdev: Wireless device structure pointer
8109 * @data: Pointer to the data received
8110 * @data_len: Length of @data
8111 *
8112 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8113 * driver.
8114 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8115 * will initiate restart of sap.
8116 *
8117 * Return: 0 on success; errno on failure
8118 */
8119static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8120 struct wireless_dev *wdev,
8121 const void *data, int data_len)
8122{
8123 int ret;
8124
8125 cds_ssr_protect(__func__);
8126 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8127 wdev, data, data_len);
8128 cds_ssr_unprotect(__func__);
8129
8130 return ret;
8131}
8132
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308133#undef BPF_INVALID
8134#undef BPF_SET_RESET
8135#undef BPF_VERSION
8136#undef BPF_ID
8137#undef BPF_PACKET_SIZE
8138#undef BPF_CURRENT_OFFSET
8139#undef BPF_PROGRAM
8140#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308141
8142/**
8143 * define short names for the global vendor params
8144 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8145 */
8146#define PARAM_TOTAL_CMD_EVENT_WAKE \
8147 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8148#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8149 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8150#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8151 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8152#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8153 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8154#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8155 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8156#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8157 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8158#define PARAM_TOTAL_RX_DATA_WAKE \
8159 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8160#define PARAM_RX_UNICAST_CNT \
8161 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8162#define PARAM_RX_MULTICAST_CNT \
8163 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8164#define PARAM_RX_BROADCAST_CNT \
8165 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8166#define PARAM_ICMP_PKT \
8167 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8168#define PARAM_ICMP6_PKT \
8169 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8170#define PARAM_ICMP6_RA \
8171 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8172#define PARAM_ICMP6_NA \
8173 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8174#define PARAM_ICMP6_NS \
8175 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8176#define PARAM_ICMP4_RX_MULTICAST_CNT \
8177 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8178#define PARAM_ICMP6_RX_MULTICAST_CNT \
8179 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8180#define PARAM_OTHER_RX_MULTICAST_CNT \
8181 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308182#define PARAM_RSSI_BREACH_CNT \
8183 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8184#define PARAM_LOW_RSSI_CNT \
8185 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8186#define PARAM_GSCAN_CNT \
8187 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8188#define PARAM_PNO_COMPLETE_CNT \
8189 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8190#define PARAM_PNO_MATCH_CNT \
8191 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8192
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308193
8194
8195/**
8196 * hdd_send_wakelock_stats() - API to send wakelock stats
8197 * @ctx: context to be passed to callback
8198 * @data: data passed to callback
8199 *
8200 * This function is used to send wake lock stats to HAL layer
8201 *
8202 * Return: 0 on success, error number otherwise.
8203 */
8204static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8205 const struct sir_wake_lock_stats *data)
8206{
8207 struct sk_buff *skb;
8208 uint32_t nl_buf_len;
8209 uint32_t total_rx_data_wake, rx_multicast_cnt;
8210 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308211 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308212
8213 ENTER();
8214
8215 nl_buf_len = NLMSG_HDRLEN;
8216 nl_buf_len +=
8217 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8218 (NLMSG_HDRLEN + sizeof(uint32_t));
8219
8220 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8221
8222 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008223 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308224 return -ENOMEM;
8225 }
8226
Jeff Johnson64943bd2016-08-23 13:14:06 -07008227 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308228 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008229 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308230 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008231 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308232 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008233 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308234 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008235 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308236 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008237 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308238 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008239 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308240 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008241 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8242 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308243 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308244 hdd_info("wow_rssi_breach_wake_up_count %d",
8245 data->wow_rssi_breach_wake_up_count);
8246 hdd_info("wow_low_rssi_wake_up_count %d",
8247 data->wow_low_rssi_wake_up_count);
8248 hdd_info("wow_gscan_wake_up_count %d",
8249 data->wow_gscan_wake_up_count);
8250 hdd_info("wow_pno_complete_wake_up_count %d",
8251 data->wow_pno_complete_wake_up_count);
8252 hdd_info("wow_pno_match_wake_up_count %d",
8253 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308254
8255 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308256 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308257
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308258 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308259 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308260
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308261 rx_multicast_cnt =
8262 data->wow_ipv4_mcast_wake_up_count +
8263 ipv6_rx_multicast_addr_cnt;
8264
8265 total_rx_data_wake =
8266 data->wow_ucast_wake_up_count +
8267 data->wow_bcast_wake_up_count +
8268 rx_multicast_cnt;
8269
8270 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8271 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8272 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8273 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8274 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8275 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8276 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8277 total_rx_data_wake) ||
8278 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8279 data->wow_ucast_wake_up_count) ||
8280 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8281 rx_multicast_cnt) ||
8282 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8283 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308284 nla_put_u32(skb, PARAM_ICMP_PKT,
8285 data->wow_icmpv4_count) ||
8286 nla_put_u32(skb, PARAM_ICMP6_PKT,
8287 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308288 nla_put_u32(skb, PARAM_ICMP6_RA,
8289 data->wow_ipv6_mcast_ra_stats) ||
8290 nla_put_u32(skb, PARAM_ICMP6_NA,
8291 data->wow_ipv6_mcast_na_stats) ||
8292 nla_put_u32(skb, PARAM_ICMP6_NS,
8293 data->wow_ipv6_mcast_ns_stats) ||
8294 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8295 data->wow_ipv4_mcast_wake_up_count) ||
8296 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8297 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308298 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8299 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8300 data->wow_rssi_breach_wake_up_count) ||
8301 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8302 data->wow_low_rssi_wake_up_count) ||
8303 nla_put_u32(skb, PARAM_GSCAN_CNT,
8304 data->wow_gscan_wake_up_count) ||
8305 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8306 data->wow_pno_complete_wake_up_count) ||
8307 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8308 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008309 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308310 goto nla_put_failure;
8311 }
8312
8313 cfg80211_vendor_cmd_reply(skb);
8314
8315 EXIT();
8316 return 0;
8317
8318nla_put_failure:
8319 kfree_skb(skb);
8320 return -EINVAL;
8321}
8322
8323/**
8324 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8325 * @wiphy: wiphy pointer
8326 * @wdev: pointer to struct wireless_dev
8327 * @data: pointer to incoming NL vendor data
8328 * @data_len: length of @data
8329 *
8330 * This function parses the incoming NL vendor command data attributes and
8331 * invokes the SME Api and blocks on a completion variable.
8332 * WMA copies required data and invokes callback
8333 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8334 *
8335 * Return: 0 on success; error number otherwise.
8336 */
8337static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8338 struct wireless_dev *wdev,
8339 const void *data,
8340 int data_len)
8341{
8342 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8343 int status, ret;
8344 struct sir_wake_lock_stats wake_lock_stats;
8345 QDF_STATUS qdf_status;
8346
8347 ENTER();
8348
8349 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008350 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308351 return -EINVAL;
8352 }
8353
8354 status = wlan_hdd_validate_context(hdd_ctx);
8355 if (0 != status)
8356 return -EINVAL;
8357
8358 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8359 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008360 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308361 return -EINVAL;
8362 }
8363
8364 ret = hdd_send_wakelock_stats(hdd_ctx,
8365 &wake_lock_stats);
8366 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008367 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308368
8369 EXIT();
8370 return ret;
8371}
8372
8373/**
8374 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8375 * @wiphy: wiphy pointer
8376 * @wdev: pointer to struct wireless_dev
8377 * @data: pointer to incoming NL vendor data
8378 * @data_len: length of @data
8379 *
8380 * This function parses the incoming NL vendor command data attributes and
8381 * invokes the SME Api and blocks on a completion variable.
8382 * WMA copies required data and invokes callback
8383 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8384 *
8385 * Return: 0 on success; error number otherwise.
8386 */
8387static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8388 struct wireless_dev *wdev,
8389 const void *data, int data_len)
8390{
8391 int ret;
8392
8393 cds_ssr_protect(__func__);
8394 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8395 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008396 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308397
8398 return ret;
8399}
8400
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308401/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308402 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8403 * @wiphy: wiphy structure pointer
8404 * @wdev: Wireless device structure pointer
8405 * @data: Pointer to the data received
8406 * @data_len: Length of @data
8407 *
8408 * This function reads wmi max bus size and fill in the skb with
8409 * NL attributes and send up the NL event.
8410 * Return: 0 on success; errno on failure
8411 */
8412static int
8413__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8414 struct wireless_dev *wdev,
8415 const void *data, int data_len)
8416{
8417 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8418 int ret_val;
8419 struct sk_buff *skb;
8420 uint32_t nl_buf_len;
8421
8422 ENTER();
8423
8424 ret_val = wlan_hdd_validate_context(hdd_ctx);
8425 if (ret_val)
8426 return ret_val;
8427
8428 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8429 hdd_err("Command not allowed in FTM mode");
8430 return -EINVAL;
8431 }
8432
8433 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8434
8435 nl_buf_len = NLMSG_HDRLEN;
8436 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8437
8438 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8439 if (!skb) {
8440 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8441 return -ENOMEM;
8442 }
8443
8444 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8445 hdd_ctx->wmi_max_len)) {
8446 hdd_err("nla put failure");
8447 goto nla_put_failure;
8448 }
8449
8450 cfg80211_vendor_cmd_reply(skb);
8451
8452 EXIT();
8453
8454 return 0;
8455
8456nla_put_failure:
8457 kfree_skb(skb);
8458 return -EINVAL;
8459}
8460
8461/**
8462 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8463 * @wiphy: wiphy structure pointer
8464 * @wdev: Wireless device structure pointer
8465 * @data: Pointer to the data received
8466 * @data_len: Length of @data
8467 *
8468 * Return: 0 on success; errno on failure
8469 */
8470static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8471 struct wireless_dev *wdev,
8472 const void *data, int data_len)
8473{
8474 int ret;
8475
8476 cds_ssr_protect(__func__);
8477 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8478 cds_ssr_unprotect(__func__);
8479
8480 return ret;
8481}
8482
8483/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308484 *__wlan_hdd_cfg80211_setband() - set band
8485 * @wiphy: Pointer to wireless phy
8486 * @wdev: Pointer to wireless device
8487 * @data: Pointer to data
8488 * @data_len: Length of @data
8489 *
8490 * Return: 0 on success, negative errno on failure
8491 */
8492static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8493 struct wireless_dev *wdev,
8494 const void *data, int data_len)
8495{
8496 struct net_device *dev = wdev->netdev;
8497 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8498 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8499 int ret;
8500 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8501 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8502
8503 ENTER();
8504
8505 ret = wlan_hdd_validate_context(hdd_ctx);
8506 if (ret)
8507 return ret;
8508
8509 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8510 hdd_err(FL("Invalid ATTR"));
8511 return -EINVAL;
8512 }
8513
8514 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8515 hdd_err(FL("attr SETBAND_VALUE failed"));
8516 return -EINVAL;
8517 }
8518
8519 ret = hdd_set_band(dev,
8520 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8521
8522 EXIT();
8523 return ret;
8524}
8525
8526/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308527 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8528 * @adapter: hdd adapter
8529 * @channel: channel number
8530 *
8531 * return: QDF status based on success or failure
8532 */
8533static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8534 int channel, int chan_bw)
8535{
8536 if (QDF_STATUS_SUCCESS !=
8537 wlan_hdd_validate_operation_channel(adapter, channel))
8538 return QDF_STATUS_E_FAILURE;
8539 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8540 channel,
8541 PHY_SINGLE_CHANNEL_CENTERED))) {
8542 hdd_notice("channel %d is in nol", channel);
8543 return -EINVAL;
8544 }
8545
8546 if ((wlansap_is_channel_leaking_in_nol(
8547 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8548 channel, chan_bw))) {
8549 hdd_notice("channel %d is leaking in nol", channel);
8550 return -EINVAL;
8551 }
8552
8553 return 0;
8554
8555}
8556
Kapil Gupta8878ad92017-02-13 11:56:04 +05308557static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8558 tsap_Config_t *sap_config,
8559 struct hdd_vendor_chan_info *channel_list)
8560{
8561 sap_config->channel = channel_list->pri_ch;
8562
8563 sap_config->ch_params.center_freq_seg0 =
8564 channel_list->vht_seg0_center_ch;
8565 sap_config->ch_params.center_freq_seg1 =
8566 channel_list->vht_seg1_center_ch;
8567
8568 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8569 sap_config->ch_params.ch_width = channel_list->chan_width;
8570 if (sap_config->channel >= 36)
8571 sap_config->ch_width_orig =
8572 hdd_ctx->config->vhtChannelWidth;
8573 else
8574 sap_config->ch_width_orig =
8575 hdd_ctx->config->nChannelBondingMode24GHz ?
8576 eHT_CHANNEL_WIDTH_40MHZ :
8577 eHT_CHANNEL_WIDTH_20MHZ;
8578
8579 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8580 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8581 sap_config->acs_cfg.vht_seg0_center_ch =
8582 channel_list->vht_seg0_center_ch;
8583 sap_config->acs_cfg.vht_seg1_center_ch =
8584 channel_list->vht_seg1_center_ch;
8585 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8586}
8587
8588static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8589 uint8_t channel_cnt,
8590 struct hdd_vendor_chan_info *channel_list)
8591{
8592 tsap_Config_t *sap_config;
8593 hdd_ap_ctx_t *hdd_ap_ctx;
8594 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8595 QDF_STATUS status = QDF_STATUS_SUCCESS;
8596
8597 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8598 sap_config = &adapter->sessionCtx.ap.sapConfig;
8599
8600 if (QDF_TIMER_STATE_RUNNING ==
8601 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8602 ap.vendor_acs_timer)) {
8603 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8604 }
8605
8606 if (channel_list && channel_list->pri_ch == 0) {
8607 /* Check mode, set default channel */
8608 channel_list->pri_ch = 6;
8609 /*
8610 * sap_select_default_oper_chan(hdd_ctx->hHal,
8611 * sap_config->acs_cfg.hw_mode);
8612 */
8613 }
8614
8615 switch (reason) {
8616 /* SAP init case */
8617 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8618 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8619 /* Update Hostapd */
8620 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8621 break;
8622
8623 /* DFS detected on current channel */
8624 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8625 wlan_sap_update_next_channel(
8626 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8627 channel_list->pri_ch,
8628 channel_list->chan_width);
8629 status = sme_update_new_channel_event(
8630 WLAN_HDD_GET_HAL_CTX(adapter),
8631 adapter->sessionId);
8632 break;
8633
8634 /* LTE coex event on current channel */
8635 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8636 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8637 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8638 hdd_ap_ctx->sapConfig.ch_width_orig =
8639 channel_list->chan_width;
8640 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8641 break;
8642
8643 default:
8644 hdd_info("invalid reason for timer invoke");
8645 }
8646 qdf_mem_free(channel_list);
8647 EXIT();
8648 return status;
8649}
8650
8651/**
8652 * Define short name for vendor channel set config
8653 */
8654#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8655#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8656#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8657#define SET_CHAN_PRIMARY_CHANNEL \
8658 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8659#define SET_CHAN_SECONDARY_CHANNEL \
8660 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8661#define SET_CHAN_SEG0_CENTER_CHANNEL \
8662 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8663#define SET_CHAN_SEG1_CENTER_CHANNEL \
8664 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8665#define SET_CHAN_CHANNEL_WIDTH \
8666 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8667#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8668
8669/**
8670 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8671 * @channel_list: pointer to hdd_vendor_chan_info
8672 * @reason: channel change reason
8673 * @channel_cnt: channel count
8674 * @data: data
8675 * @data_len: data len
8676 *
8677 * Return: 0 on success, negative errno on failure
8678 */
8679static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8680 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8681 const void *data, int data_len)
8682{
8683 int rem, i = 0;
8684 struct nlattr *tb[SET_CHAN_MAX + 1];
8685 struct nlattr *tb2[SET_CHAN_MAX + 1];
8686 struct nlattr *curr_attr;
8687 struct hdd_vendor_chan_info *channel_list;
8688
8689 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8690 hdd_err("Invalid ATTR");
8691 return -EINVAL;
8692 }
8693
8694 if (tb[SET_CHAN_REASON])
8695 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8696
8697 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8698 *channel_cnt = nla_get_u8(tb[
8699 SET_CHAN_CHANNEL_COUNT]);
8700 hdd_info("channel count %d", *channel_cnt);
8701 }
8702
8703 if (!(*channel_cnt)) {
8704 hdd_err("channel count is %d", *channel_cnt);
8705 return -EINVAL;
8706 }
8707
8708 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8709 (*channel_cnt));
8710
8711 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8712 if (nla_parse(tb2,
8713 SET_CHAN_MAX,
8714 nla_data(curr_attr), nla_len(curr_attr),
8715 NULL)) {
8716 hdd_err("nla_parse failed");
8717 return -EINVAL;
8718 }
8719 /* Parse and Fetch allowed SSID list*/
8720 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8721 channel_list[i].pri_ch =
8722 nla_get_u8(
8723 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8724 }
8725 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8726 channel_list[i].ht_sec_ch =
8727 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8728 }
8729 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8730 channel_list[i].vht_seg0_center_ch =
8731 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8732 }
8733 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8734 channel_list[i].vht_seg1_center_ch =
8735 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8736 }
8737 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8738 channel_list[i].chan_width =
8739 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8740 }
8741 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8742 i, channel_list[i].pri_ch,
8743 channel_list[i].ht_sec_ch,
8744 channel_list[i].vht_seg0_center_ch,
8745 channel_list[i].vht_seg1_center_ch,
8746 channel_list[i].chan_width);
8747 i++;
8748 if (i > *channel_cnt)
8749 break;
8750 }
8751 *chan_list_ptr = channel_list;
8752
8753 return 0;
8754}
8755
8756/**
8757 * Undef short names for vendor set channel configuration
8758 */
8759#undef SET_CHAN_REASON
8760#undef SET_CHAN_CHANNEL_COUNT
8761#undef SET_CHAN_CHAN_LIST
8762#undef SET_CHAN_PRIMARY_CHANNEL
8763#undef SET_CHAN_SECONDARY_CHANNEL
8764#undef SET_CHAN_SEG0_CENTER_CHANNEL
8765#undef SET_CHAN_SEG1_CENTER_CHANNEL
8766#undef SET_CHAN_CHANNEL_WIDTH
8767#undef SET_CHAN_MAX
8768
8769/**
8770 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8771 * @wiphy: Pointer to wireless phy
8772 * @wdev: Pointer to wireless device
8773 * @data: Pointer to data
8774 * @data_len: Length of @data
8775 *
8776 * Return: 0 on success, negative errno on failure
8777 */
8778static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8779 struct wireless_dev *wdev,
8780 const void *data, int data_len)
8781{
8782 int ret_val;
8783 QDF_STATUS qdf_status;
8784 uint8_t channel_cnt = 0, reason = -1;
8785 struct hdd_vendor_chan_info *channel_list = NULL;
8786 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8787 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8788
8789 ENTER();
8790
8791 ret_val = wlan_hdd_validate_context(hdd_ctx);
8792 if (ret_val)
8793 return ret_val;
8794
8795 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8796 hdd_err("Command not allowed in FTM mode");
8797 return -EINVAL;
8798 }
8799
8800 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8801 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8802 else {
8803 hdd_err("already timeout happened for acs");
8804 return -EINVAL;
8805 }
8806
8807 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8808 &channel_cnt, data, data_len);
8809 if (ret_val)
8810 return ret_val;
8811
8812 /* Validate channel to be set */
8813 while (channel_cnt && channel_list) {
8814 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8815 channel_list->pri_ch,
8816 channel_list->chan_width);
8817 if (qdf_status == QDF_STATUS_SUCCESS)
8818 break;
8819 channel_cnt--;
8820 channel_list++;
8821 }
8822 if ((channel_cnt <= 0) || !channel_list) {
8823 hdd_err("no available channel/chanlist %p", channel_list);
8824 return -EINVAL;
8825 }
8826
8827 qdf_status = hdd_update_acs_channel(adapter, reason,
8828 channel_cnt, channel_list);
8829 return qdf_status_to_os_return(qdf_status);
8830}
8831
8832/**
8833 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8834 * @wiphy: Pointer to wireless phy
8835 * @wdev: Pointer to wireless device
8836 * @data: Pointer to data
8837 * @data_len: Length of @data
8838 *
8839 * Return: 0 on success, negative errno on failure
8840 */
8841static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8842 struct wireless_dev *wdev,
8843 const void *data, int data_len)
8844{
8845 int ret;
8846
8847 cds_ssr_protect(__func__);
8848 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8849 data_len);
8850 cds_ssr_protect(__func__);
8851
8852 return ret;
8853}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308854
8855/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308856 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8857 * @wiphy: wiphy structure pointer
8858 * @wdev: Wireless device structure pointer
8859 * @data: Pointer to the data received
8860 * @data_len: Length of @data
8861 *
8862 * Return: 0 on success; errno on failure
8863 */
8864static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8865 struct wireless_dev *wdev,
8866 const void *data, int data_len)
8867{
8868 int ret;
8869
8870 cds_ssr_protect(__func__);
8871 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8872 cds_ssr_unprotect(__func__);
8873
8874 return ret;
8875}
8876
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008877/**
8878 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8879 * @nl80211_value: Vendor command attribute value
8880 * @wmi_value: Pointer to return converted WMI return value
8881 *
8882 * Convert NL80211 vendor command value for SAR limit set to WMI value
8883 * Return: 0 on success, -1 on invalid value
8884 */
8885static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8886 u32 *wmi_value)
8887{
8888 int ret = 0;
8889
8890 switch (nl80211_value) {
8891 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8892 *wmi_value = WMI_SAR_FEATURE_OFF;
8893 break;
8894 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8895 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8896 break;
8897 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8898 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8899 break;
8900 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8901 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8902 break;
8903 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8904 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8905 break;
8906 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8907 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8908 break;
8909 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8910 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8911 break;
8912 default:
8913 ret = -1;
8914 }
8915 return ret;
8916}
8917
8918/**
8919 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8920 * @nl80211_value: Vendor command attribute value
8921 * @wmi_value: Pointer to return converted WMI return value
8922 *
8923 * Convert NL80211 vendor command value for SAR BAND to WMI value
8924 * Return: 0 on success, -1 on invalid value
8925 */
8926static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8927{
8928 int ret = 0;
8929
8930 switch (nl80211_value) {
8931 case NL80211_BAND_2GHZ:
8932 *wmi_value = WMI_SAR_2G_ID;
8933 break;
8934 case NL80211_BAND_5GHZ:
8935 *wmi_value = WMI_SAR_5G_ID;
8936 break;
8937 default:
8938 ret = -1;
8939 }
8940 return ret;
8941}
8942
8943/**
8944 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8945 * @nl80211_value: Vendor command attribute value
8946 * @wmi_value: Pointer to return converted WMI return value
8947 *
8948 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8949 * Return: 0 on success, -1 on invalid value
8950 */
8951static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8952 u32 *wmi_value)
8953{
8954 int ret = 0;
8955
8956 switch (nl80211_value) {
8957 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8958 *wmi_value = WMI_SAR_MOD_CCK;
8959 break;
8960 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8961 *wmi_value = WMI_SAR_MOD_OFDM;
8962 break;
8963 default:
8964 ret = -1;
8965 }
8966 return ret;
8967}
8968
8969
8970/**
8971 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8972 * @wiphy: Pointer to wireless phy
8973 * @wdev: Pointer to wireless device
8974 * @data: Pointer to data
8975 * @data_len: Length of @data
8976 *
8977 * This function is used to setup Specific Absorption Rate limit specs.
8978 *
8979 * Return: 0 on success, negative errno on failure
8980 */
8981static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8982 struct wireless_dev *wdev,
8983 const void *data, int data_len)
8984{
8985 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8986 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8987 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8988 *sar_spec_list;
8989 struct sar_limit_cmd_params sar_limit_cmd = {0};
8990 int ret = -EINVAL, i = 0, rem = 0;
8991
8992 ENTER();
8993
8994 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8995 hdd_err("Command not allowed in FTM mode");
8996 return -EPERM;
8997 }
8998
8999 if (wlan_hdd_validate_context(hdd_ctx))
9000 return -EINVAL;
9001
9002 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9003 data, data_len, NULL)) {
9004 hdd_err("Invalid SAR attributes");
9005 return -EINVAL;
9006 }
9007
9008 /* Vendor command manadates all SAR Specs in single call */
9009 sar_limit_cmd.commit_limits = 1;
9010 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9011 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9012 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9013 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9014 &sar_limit_cmd.sar_enable) < 0) {
9015 hdd_err("Invalid SAR Enable attr");
9016 goto fail;
9017 }
9018 }
9019 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9020
9021 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9022 sar_limit_cmd.num_limit_rows = nla_get_u32(
9023 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9024 hdd_info("attr sar num_limit_rows %d",
9025 sar_limit_cmd.num_limit_rows);
9026 }
9027 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9028 hdd_err("SAR Spec list exceed supported size");
9029 goto fail;
9030 }
9031 if (sar_limit_cmd.num_limit_rows == 0)
9032 goto send_sar_limits;
9033 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9034 struct sar_limit_cmd_row) *
9035 sar_limit_cmd.num_limit_rows);
9036 if (!sar_limit_cmd.sar_limit_row_list) {
9037 ret = -ENOMEM;
9038 goto fail;
9039 }
9040 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9041 hdd_err("Invalid SAR SPECs list");
9042 goto fail;
9043 }
9044
9045 nla_for_each_nested(sar_spec_list,
9046 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9047 if (i == sar_limit_cmd.num_limit_rows) {
9048 hdd_warn("SAR Cmd has excess SPECs in list");
9049 break;
9050 }
9051
9052 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9053 nla_data(sar_spec_list), nla_len(sar_spec_list),
9054 NULL)) {
9055 hdd_err("nla_parse failed for SAR Spec list");
9056 goto fail;
9057 }
9058 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9059 if (sar_spec[
9060 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9061 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9062 nla_get_u32(sar_spec[
9063 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9064 } else {
9065 hdd_err("SAR Spec does not have power limit value");
9066 goto fail;
9067 }
9068
9069 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9070 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9071 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9072 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9073 < 0) {
9074 hdd_err("Invalid SAR Band attr");
9075 goto fail;
9076 }
9077 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9078 WMI_SAR_BAND_ID_VALID_MASK;
9079 }
9080 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9081 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9082 nla_get_u32(sar_spec[
9083 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9084 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9085 WMI_SAR_CHAIN_ID_VALID_MASK;
9086 }
9087 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9088 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9089 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9090 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9091 < 0) {
9092 hdd_err("Invalid SAR Modulation attr");
9093 goto fail;
9094 }
9095 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9096 WMI_SAR_MOD_ID_VALID_MASK;
9097 }
9098 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9099 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9100 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9101 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9102 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9103 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9104 i++;
9105 }
9106
9107 if (i < sar_limit_cmd.num_limit_rows) {
9108 hdd_warn("SAR Cmd has less SPECs in list");
9109 sar_limit_cmd.num_limit_rows = i;
9110 }
9111
9112send_sar_limits:
9113 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9114 QDF_STATUS_SUCCESS)
9115 ret = 0;
9116fail:
9117 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9118 return ret;
9119}
9120
9121/**
9122 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9123 * @wiphy: Pointer to wireless phy
9124 * @wdev: Pointer to wireless device
9125 * @data: Pointer to data
9126 * @data_len: Length of @data
9127 *
9128 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9129 *
9130 * Return: 0 on success, negative errno on failure
9131 */
9132static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9133 struct wireless_dev *wdev,
9134 const void *data,
9135 int data_len)
9136{
9137 int ret;
9138
9139 cds_ssr_protect(__func__);
9140 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9141 data_len);
9142 cds_ssr_unprotect(__func__);
9143
9144 return ret;
9145}
9146
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309147static const struct
9148nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9149 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9150 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9151 .len = QDF_MAC_ADDR_SIZE},
9152};
9153
9154/**
9155 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9156 * @wiphy: Pointer to wireless phy
9157 * @wdev: Pointer to wireless device
9158 * @data: Pointer to data
9159 * @data_len: Length of @data
9160 *
9161 * This function is used to enable/disable roaming using vendor commands
9162 *
9163 * Return: 0 on success, negative errno on failure
9164 */
9165static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9166 struct wireless_dev *wdev,
9167 const void *data, int data_len)
9168{
9169 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9170 struct net_device *dev = wdev->netdev;
9171 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9172 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9173 uint32_t is_fast_roam_enabled;
9174 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309175 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309176
9177 ENTER_DEV(dev);
9178
9179 ret = wlan_hdd_validate_context(hdd_ctx);
9180 if (0 != ret)
9181 return ret;
9182
9183 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9184 hdd_err("Command not allowed in FTM mode");
9185 return -EINVAL;
9186 }
9187
9188 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9189 qca_wlan_vendor_attr);
9190 if (ret) {
9191 hdd_err("Invalid ATTR");
9192 return -EINVAL;
9193 }
9194
9195 /* Parse and fetch Enable flag */
9196 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9197 hdd_err("attr enable failed");
9198 return -EINVAL;
9199 }
9200
9201 is_fast_roam_enabled = nla_get_u32(
9202 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009203 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9204 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309205
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009206 if (!adapter->fast_roaming_allowed) {
9207 hdd_err("fast roaming not allowed on %s interface",
9208 adapter->dev->name);
9209 return -EINVAL;
9210 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309211 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309212 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009213 (is_fast_roam_enabled &&
9214 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309215 if (qdf_status != QDF_STATUS_SUCCESS)
9216 hdd_err("sme_config_fast_roaming failed with status=%d",
9217 qdf_status);
9218 ret = qdf_status_to_os_return(qdf_status);
9219
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309220 EXIT();
9221 return ret;
9222}
9223
9224/**
9225 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9226 * @wiphy: Pointer to wireless phy
9227 * @wdev: Pointer to wireless device
9228 * @data: Pointer to data
9229 * @data_len: Length of @data
9230 *
9231 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9232 *
9233 * Return: 0 on success, negative errno on failure
9234 */
9235static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9236 struct wireless_dev *wdev,
9237 const void *data, int data_len)
9238{
9239 int ret;
9240
9241 cds_ssr_protect(__func__);
9242 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9243 cds_ssr_unprotect(__func__);
9244
9245 return ret;
9246}
9247
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309248static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9249 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9250 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9251 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9252 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9253};
9254
9255/**
9256 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9257 * @wiphy: Pointer to wireless phy
9258 * @wdev: Pointer to wireless device
9259 * @data: Pointer to data
9260 * @data_len: Length of @data
9261 *
9262 * Return: 0 on success, negative errno on failure
9263 */
9264static int
9265__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9266 struct wireless_dev *wdev,
9267 const void *data,
9268 int data_len)
9269{
9270 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9271 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9272 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9273 struct nlattr *apth;
9274 int rem;
9275 int ret = 1;
9276 int print_idx = -1;
9277 int module_id = -1;
9278 int bit_mask = -1;
9279 int status;
9280
9281 ENTER();
9282
9283 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9284 hdd_err("Command not allowed in FTM mode");
9285 return -EINVAL;
9286 }
9287
9288 ret = wlan_hdd_validate_context(hdd_ctx);
9289 if (ret != 0)
9290 return -EINVAL;
9291
9292 print_idx = qdf_get_pidx();
9293 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9294 hdd_err("Invalid print controle object index");
9295 return -EINVAL;
9296 }
9297
9298 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9299 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9300 hdd_err("Invalid attr");
9301 return -EINVAL;
9302 }
9303
9304 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9305 hdd_err("attr trace level param failed");
9306 return -EINVAL;
9307 }
9308
9309 nla_for_each_nested(apth,
9310 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9311 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9312 nla_data(apth), nla_len(apth), NULL)) {
9313 hdd_err("Invalid attr");
9314 return -EINVAL;
9315 }
9316
9317 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9318 hdd_err("attr Module ID failed");
9319 return -EINVAL;
9320 }
9321 module_id = nla_get_u32
9322 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9323
9324 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9325 hdd_err("attr Verbose mask failed");
9326 return -EINVAL;
9327 }
9328 bit_mask = nla_get_u32
9329 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9330
9331 status = hdd_qdf_trace_enable(module_id, bit_mask);
9332
9333 if (status != 0)
9334 hdd_err("can not set verbose mask %d for the category %d",
9335 bit_mask, module_id);
9336 }
9337
9338 EXIT();
9339 return ret;
9340}
9341
9342/**
9343 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9344 * @wiphy: Pointer to wireless phy
9345 * @wdev: Pointer to wireless device
9346 * @data: Pointer to data
9347 * @data_len: Length of @data
9348 *
9349 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9350 *
9351 * Return: 0 on success, negative errno on failure
9352 */
9353
9354static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9355 struct wireless_dev *wdev,
9356 const void *data,
9357 int data_len)
9358{
9359 int ret;
9360
9361 cds_ssr_protect(__func__);
9362 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9363 cds_ssr_unprotect(__func__);
9364
9365 return ret;
9366}
9367
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009368const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9369 {
9370 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9371 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9372 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309373 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009374 .doit = is_driver_dfs_capable
9375 },
9376
9377#ifdef WLAN_FEATURE_NAN
9378 {
9379 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9380 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9381 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9382 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9383 .doit = wlan_hdd_cfg80211_nan_request
9384 },
9385#endif
9386
9387#ifdef WLAN_FEATURE_STATS_EXT
9388 {
9389 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9390 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9391 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9392 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9393 .doit = wlan_hdd_cfg80211_stats_ext_request
9394 },
9395#endif
9396#ifdef FEATURE_WLAN_EXTSCAN
9397 {
9398 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9399 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9400 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9401 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9402 .doit = wlan_hdd_cfg80211_extscan_start
9403 },
9404 {
9405 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9406 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9407 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9408 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9409 .doit = wlan_hdd_cfg80211_extscan_stop
9410 },
9411 {
9412 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9413 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9414 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9415 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9416 },
9417 {
9418 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9419 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9420 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9421 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9422 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9423 },
9424 {
9425 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9426 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9427 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9428 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9429 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9430 },
9431 {
9432 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9433 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9434 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9435 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9436 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9437 },
9438 {
9439 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9440 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9441 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9442 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9443 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9444 },
9445 {
9446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9447 .info.subcmd =
9448 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9449 .flags =
9450 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9451 WIPHY_VENDOR_CMD_NEED_RUNNING,
9452 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9453 },
9454 {
9455 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9456 .info.subcmd =
9457 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9458 .flags =
9459 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9460 WIPHY_VENDOR_CMD_NEED_RUNNING,
9461 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9462 },
9463 {
9464 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9465 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9466 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9467 WIPHY_VENDOR_CMD_NEED_NETDEV |
9468 WIPHY_VENDOR_CMD_NEED_RUNNING,
9469 .doit = wlan_hdd_cfg80211_set_epno_list
9470 },
9471#endif /* FEATURE_WLAN_EXTSCAN */
9472
9473#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9474 {
9475 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9476 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9477 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9478 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9479 .doit = wlan_hdd_cfg80211_ll_stats_clear
9480 },
9481
9482 {
9483 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9484 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9485 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9486 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9487 .doit = wlan_hdd_cfg80211_ll_stats_set
9488 },
9489
9490 {
9491 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9492 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9493 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9494 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9495 .doit = wlan_hdd_cfg80211_ll_stats_get
9496 },
9497#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9498#ifdef FEATURE_WLAN_TDLS
9499 {
9500 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9501 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9502 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9503 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9504 .doit = wlan_hdd_cfg80211_exttdls_enable
9505 },
9506 {
9507 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9508 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9509 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9510 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9511 .doit = wlan_hdd_cfg80211_exttdls_disable
9512 },
9513 {
9514 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9515 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9516 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9517 .doit = wlan_hdd_cfg80211_exttdls_get_status
9518 },
9519#endif
9520 {
9521 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9522 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9523 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9524 .doit = wlan_hdd_cfg80211_get_supported_features
9525 },
9526 {
9527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9528 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9529 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9530 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9531 },
9532 {
9533 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9534 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309536 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009537 },
9538 {
9539 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9540 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9541 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9542 WIPHY_VENDOR_CMD_NEED_NETDEV,
9543 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9544 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009545 {
9546 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9547 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9548 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9549 WIPHY_VENDOR_CMD_NEED_NETDEV,
9550 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9551 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009552 {
9553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9556 WIPHY_VENDOR_CMD_NEED_NETDEV |
9557 WIPHY_VENDOR_CMD_NEED_RUNNING,
9558 .doit = hdd_cfg80211_get_station_cmd
9559 },
9560 {
9561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9564 WIPHY_VENDOR_CMD_NEED_NETDEV |
9565 WIPHY_VENDOR_CMD_NEED_RUNNING,
9566 .doit = wlan_hdd_cfg80211_do_acs
9567 },
9568
9569 {
9570 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9571 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9572 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9573 WIPHY_VENDOR_CMD_NEED_NETDEV,
9574 .doit = wlan_hdd_cfg80211_get_features
9575 },
9576#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9577 {
9578 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9579 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9580 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9581 WIPHY_VENDOR_CMD_NEED_NETDEV |
9582 WIPHY_VENDOR_CMD_NEED_RUNNING,
9583 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9584 },
9585#endif
9586#ifdef FEATURE_WLAN_EXTSCAN
9587 {
9588 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9589 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9590 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9591 WIPHY_VENDOR_CMD_NEED_NETDEV |
9592 WIPHY_VENDOR_CMD_NEED_RUNNING,
9593 .doit = wlan_hdd_cfg80211_set_passpoint_list
9594 },
9595 {
9596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9599 WIPHY_VENDOR_CMD_NEED_NETDEV |
9600 WIPHY_VENDOR_CMD_NEED_RUNNING,
9601 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9602 },
9603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9607 WIPHY_VENDOR_CMD_NEED_NETDEV |
9608 WIPHY_VENDOR_CMD_NEED_RUNNING,
9609 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9610 },
9611 {
9612 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9613 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9614 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9615 WIPHY_VENDOR_CMD_NEED_NETDEV |
9616 WIPHY_VENDOR_CMD_NEED_RUNNING,
9617 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9618 },
9619#endif /* FEATURE_WLAN_EXTSCAN */
9620 {
9621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9624 WIPHY_VENDOR_CMD_NEED_NETDEV,
9625 .doit = wlan_hdd_cfg80211_get_wifi_info
9626 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009627#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009628 {
9629 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9630 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9632 WIPHY_VENDOR_CMD_NEED_NETDEV |
9633 WIPHY_VENDOR_CMD_NEED_RUNNING,
9634 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9635 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009636#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009637 {
9638 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9639 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9640 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9641 WIPHY_VENDOR_CMD_NEED_NETDEV,
9642 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9643 },
9644 {
9645 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9646 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9647 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9648 WIPHY_VENDOR_CMD_NEED_NETDEV,
9649 .doit = wlan_hdd_cfg80211_wifi_logger_start
9650 },
9651 {
9652 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9653 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9654 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9655 WIPHY_VENDOR_CMD_NEED_NETDEV,
9656 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9657 },
9658 {
9659 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9660 .info.subcmd =
9661 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9662 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9663 WIPHY_VENDOR_CMD_NEED_NETDEV |
9664 WIPHY_VENDOR_CMD_NEED_RUNNING,
9665 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9666 },
9667 {
9668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9669 .info.subcmd =
9670 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9671 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9672 WIPHY_VENDOR_CMD_NEED_NETDEV |
9673 WIPHY_VENDOR_CMD_NEED_RUNNING,
9674 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9675 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009676#ifdef WLAN_FEATURE_TSF
9677 {
9678 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9679 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9680 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9681 WIPHY_VENDOR_CMD_NEED_NETDEV |
9682 WIPHY_VENDOR_CMD_NEED_RUNNING,
9683 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9684 },
9685#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686#ifdef FEATURE_WLAN_TDLS
9687 {
9688 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9689 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9690 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9691 WIPHY_VENDOR_CMD_NEED_NETDEV |
9692 WIPHY_VENDOR_CMD_NEED_RUNNING,
9693 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9694 },
9695#endif
9696#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9697 {
9698 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9699 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9700 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9701 WIPHY_VENDOR_CMD_NEED_NETDEV |
9702 WIPHY_VENDOR_CMD_NEED_RUNNING,
9703 .doit = wlan_hdd_cfg80211_offloaded_packets
9704 },
9705#endif
9706 {
9707 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9708 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9709 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9710 WIPHY_VENDOR_CMD_NEED_NETDEV |
9711 WIPHY_VENDOR_CMD_NEED_RUNNING,
9712 .doit = wlan_hdd_cfg80211_monitor_rssi
9713 },
9714 {
9715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309716 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9717 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9718 WIPHY_VENDOR_CMD_NEED_NETDEV |
9719 WIPHY_VENDOR_CMD_NEED_RUNNING,
9720 .doit = wlan_hdd_cfg80211_set_ns_offload
9721 },
9722 {
9723 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9725 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9726 WIPHY_VENDOR_CMD_NEED_NETDEV |
9727 WIPHY_VENDOR_CMD_NEED_RUNNING,
9728 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9729 },
9730#ifdef WLAN_FEATURE_MEMDUMP
9731 {
9732 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9733 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9734 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9735 WIPHY_VENDOR_CMD_NEED_NETDEV |
9736 WIPHY_VENDOR_CMD_NEED_RUNNING,
9737 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9738 },
9739#endif /* WLAN_FEATURE_MEMDUMP */
9740 {
9741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9742 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9743 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9744 WIPHY_VENDOR_CMD_NEED_NETDEV |
9745 WIPHY_VENDOR_CMD_NEED_RUNNING,
9746 .doit = wlan_hdd_cfg80211_vendor_scan
9747 },
9748
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309749 /* Vendor abort scan */
9750 {
9751 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9752 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9753 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9754 WIPHY_VENDOR_CMD_NEED_NETDEV |
9755 WIPHY_VENDOR_CMD_NEED_RUNNING,
9756 .doit = wlan_hdd_vendor_abort_scan
9757 },
9758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009759 /* OCB commands */
9760 {
9761 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9762 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9763 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9764 WIPHY_VENDOR_CMD_NEED_NETDEV |
9765 WIPHY_VENDOR_CMD_NEED_RUNNING,
9766 .doit = wlan_hdd_cfg80211_ocb_set_config
9767 },
9768 {
9769 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9770 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9771 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9772 WIPHY_VENDOR_CMD_NEED_NETDEV |
9773 WIPHY_VENDOR_CMD_NEED_RUNNING,
9774 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9775 },
9776 {
9777 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9778 .info.subcmd =
9779 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9780 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9781 WIPHY_VENDOR_CMD_NEED_NETDEV |
9782 WIPHY_VENDOR_CMD_NEED_RUNNING,
9783 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9784 },
9785 {
9786 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9787 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9788 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9789 WIPHY_VENDOR_CMD_NEED_NETDEV |
9790 WIPHY_VENDOR_CMD_NEED_RUNNING,
9791 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9792 },
9793 {
9794 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9795 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9796 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9797 WIPHY_VENDOR_CMD_NEED_NETDEV |
9798 WIPHY_VENDOR_CMD_NEED_RUNNING,
9799 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9800 },
9801 {
9802 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9803 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9804 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9805 WIPHY_VENDOR_CMD_NEED_NETDEV |
9806 WIPHY_VENDOR_CMD_NEED_RUNNING,
9807 .doit = wlan_hdd_cfg80211_dcc_get_stats
9808 },
9809 {
9810 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9811 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9812 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9813 WIPHY_VENDOR_CMD_NEED_NETDEV |
9814 WIPHY_VENDOR_CMD_NEED_RUNNING,
9815 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9816 },
9817 {
9818 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9819 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9821 WIPHY_VENDOR_CMD_NEED_NETDEV |
9822 WIPHY_VENDOR_CMD_NEED_RUNNING,
9823 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9824 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309825 {
9826 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9827 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9828 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9829 WIPHY_VENDOR_CMD_NEED_NETDEV |
9830 WIPHY_VENDOR_CMD_NEED_RUNNING,
9831 .doit = wlan_hdd_cfg80211_get_link_properties
9832 },
Peng Xu278d0122015-09-24 16:34:17 -07009833 {
Peng Xud2220962016-07-11 17:59:17 -07009834 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009835 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9837 WIPHY_VENDOR_CMD_NEED_NETDEV |
9838 WIPHY_VENDOR_CMD_NEED_RUNNING,
9839 .doit = wlan_hdd_cfg80211_set_ota_test
9840 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009841#ifdef FEATURE_LFR_SUBNET_DETECTION
9842 {
9843 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9844 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9845 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9846 WIPHY_VENDOR_CMD_NEED_NETDEV |
9847 WIPHY_VENDOR_CMD_NEED_RUNNING,
9848 .doit = wlan_hdd_cfg80211_set_gateway_params
9849 },
9850#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009851 {
Peng Xud2220962016-07-11 17:59:17 -07009852 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009853 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9854 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9855 WIPHY_VENDOR_CMD_NEED_NETDEV |
9856 WIPHY_VENDOR_CMD_NEED_RUNNING,
9857 .doit = wlan_hdd_cfg80211_txpower_scale
9858 },
9859 {
9860 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9861 .info.subcmd =
9862 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9864 WIPHY_VENDOR_CMD_NEED_NETDEV |
9865 WIPHY_VENDOR_CMD_NEED_RUNNING,
9866 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9867 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309868 {
9869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9872 WIPHY_VENDOR_CMD_NEED_NETDEV |
9873 WIPHY_VENDOR_CMD_NEED_RUNNING,
9874 .doit = wlan_hdd_cfg80211_bpf_offload
9875 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309876 {
9877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9880 WIPHY_VENDOR_CMD_NEED_NETDEV |
9881 WIPHY_VENDOR_CMD_NEED_RUNNING,
9882 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9883 },
9884 {
9885 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309886 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9887 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9888 WIPHY_VENDOR_CMD_NEED_NETDEV |
9889 WIPHY_VENDOR_CMD_NEED_RUNNING,
9890 .doit = wlan_hdd_cfg80211_sta_roam_policy
9891 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309892#ifdef FEATURE_WLAN_CH_AVOID
9893 {
9894 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9895 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9896 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9897 WIPHY_VENDOR_CMD_NEED_NETDEV |
9898 WIPHY_VENDOR_CMD_NEED_RUNNING,
9899 .doit = wlan_hdd_cfg80211_avoid_freq
9900 },
9901#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309902 {
9903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309904 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9905 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9906 WIPHY_VENDOR_CMD_NEED_NETDEV |
9907 WIPHY_VENDOR_CMD_NEED_RUNNING,
9908 .doit = wlan_hdd_cfg80211_sap_configuration_set
9909 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009910 {
Peng Xu4225c152016-07-14 21:18:14 -07009911 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009912 .info.subcmd =
9913 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_p2p_lo_start
9918 },
9919 {
9920 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9921 .info.subcmd =
9922 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9923 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9924 WIPHY_VENDOR_CMD_NEED_NETDEV |
9925 WIPHY_VENDOR_CMD_NEED_RUNNING,
9926 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9927 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309928 {
9929 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9930 .info.subcmd =
9931 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9933 WIPHY_VENDOR_CMD_NEED_NETDEV |
9934 WIPHY_VENDOR_CMD_NEED_RUNNING,
9935 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9936 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009937#ifdef WLAN_FEATURE_NAN_DATAPATH
9938 {
9939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9942 WIPHY_VENDOR_CMD_NEED_NETDEV |
9943 WIPHY_VENDOR_CMD_NEED_RUNNING,
9944 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9945 },
9946#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309947 {
9948 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9949 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9951 WIPHY_VENDOR_CMD_NEED_NETDEV |
9952 WIPHY_VENDOR_CMD_NEED_RUNNING,
9953 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9954 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309955 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9957 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9958 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9959 WIPHY_VENDOR_CMD_NEED_NETDEV |
9960 WIPHY_VENDOR_CMD_NEED_RUNNING,
9961 .doit = wlan_hdd_cfg80211_get_bus_size
9962 },
9963 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309964 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9965 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
9966 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9967 WIPHY_VENDOR_CMD_NEED_NETDEV |
9968 WIPHY_VENDOR_CMD_NEED_RUNNING,
9969 .doit = wlan_hdd_cfg80211_update_vendor_channel
9970 },
9971 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309972 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9973 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9974 WIPHY_VENDOR_CMD_NEED_NETDEV |
9975 WIPHY_VENDOR_CMD_NEED_RUNNING,
9976 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309977 },
9978 {
9979 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9980 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9981 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9982 WIPHY_VENDOR_CMD_NEED_NETDEV |
9983 WIPHY_VENDOR_CMD_NEED_RUNNING,
9984 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309985 },
9986#ifdef WLAN_FEATURE_DISA
9987 {
9988 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9989 .info.subcmd =
9990 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
9991 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9992 WIPHY_VENDOR_CMD_NEED_NETDEV |
9993 WIPHY_VENDOR_CMD_NEED_RUNNING,
9994 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
9995 },
9996#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009997#ifdef FEATURE_WLAN_TDLS
9998 {
9999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10000 .info.subcmd =
10001 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10003 WIPHY_VENDOR_CMD_NEED_NETDEV |
10004 WIPHY_VENDOR_CMD_NEED_RUNNING,
10005 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010006 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010007#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010008 {
10009 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10010 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10011 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10012 WIPHY_VENDOR_CMD_NEED_RUNNING,
10013 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10014 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010015 {
10016 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10017 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10019 WIPHY_VENDOR_CMD_NEED_NETDEV |
10020 WIPHY_VENDOR_CMD_NEED_RUNNING,
10021 .doit = wlan_hdd_cfg80211_set_trace_level
10022 },
10023
Paul Zhang3a210c52016-12-08 10:18:12 +080010024#ifdef WLAN_UMAC_CONVERGENCE
10025 COMMON_VENDOR_COMMANDS
10026#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027};
10028
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010029#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10030 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10031 defined(FEATURE_WLAN_SCAN_PNO)
10032/**
10033 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10034 * @wiphy: pointer to wiphy
10035 * @config: pointer to config
10036 *
10037 * Return: None
10038 */
10039static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10040 struct hdd_config *config)
10041{
10042 if (config->configPNOScanSupport) {
10043 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10044 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10045 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10046 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10047 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10048 if (config->max_sched_scan_plan_interval)
10049 wiphy->max_sched_scan_plan_interval =
10050 config->max_sched_scan_plan_interval;
10051 if (config->max_sched_scan_plan_iterations)
10052 wiphy->max_sched_scan_plan_iterations =
10053 config->max_sched_scan_plan_iterations;
10054 }
10055}
10056#else
10057static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10058 struct hdd_config *config)
10059{
10060}
10061#endif
10062
10063
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010064/**
10065 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10066 * @priv_size: Size of the hdd context.
10067 *
10068 * Allocate wiphy context and hdd context.
10069 *
10070 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010071 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010072hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010073{
10074 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010075 hdd_context_t *hdd_ctx;
10076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010077 ENTER();
10078
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010079 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10080
10081 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010082 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010083 return NULL;
10084 }
10085
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010086 hdd_ctx = wiphy_priv(wiphy);
10087
10088 hdd_ctx->wiphy = wiphy;
10089
10090 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010091}
10092
10093/*
10094 * FUNCTION: wlan_hdd_cfg80211_update_band
10095 * This function is called from the supplicant through a
10096 * private ioctl to change the band value
10097 */
10098int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10099{
10100 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010101 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102
10103 ENTER();
10104
Dustin Browna30892e2016-10-12 17:28:36 -070010105 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010106
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010107 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010108 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109
10110 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10111 struct ieee80211_supported_band *band = wiphy->bands[i];
10112
10113 channelEnabledState =
10114 cds_get_channel_state(band->channels[j].
10115 hw_value);
10116
Dustin Browna30892e2016-10-12 17:28:36 -070010117 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118 /* 5G only */
10119#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10120 /* Enable Social channels for P2P */
10121 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10122 (band->channels[j].center_freq)
10123 && CHANNEL_STATE_ENABLE ==
10124 channelEnabledState)
10125 band->channels[j].flags &=
10126 ~IEEE80211_CHAN_DISABLED;
10127 else
10128#endif
10129 band->channels[j].flags |=
10130 IEEE80211_CHAN_DISABLED;
10131 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010132 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010133 eCSR_BAND_24 == eBand) {
10134 /* 2G only */
10135 band->channels[j].flags |=
10136 IEEE80211_CHAN_DISABLED;
10137 continue;
10138 }
10139
Amar Singhal6842e8f2016-02-23 16:30:32 -080010140 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010141 band->channels[j].flags &=
10142 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010143 }
10144 }
10145 return 0;
10146}
10147
Peng Xuacfdda12017-02-06 16:15:38 -080010148#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149/*
10150 * FUNCTION: wlan_hdd_cfg80211_init
10151 * This function is called by hdd_wlan_startup()
10152 * during initialization.
10153 * This function is used to initialize and register wiphy structure.
10154 */
10155int wlan_hdd_cfg80211_init(struct device *dev,
10156 struct wiphy *wiphy, struct hdd_config *pCfg)
10157{
10158 int i, j;
10159 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10160
10161 ENTER();
10162
10163 /* Now bind the underlying wlan device with wiphy */
10164 set_wiphy_dev(wiphy, dev);
10165
10166 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010168#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10169 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010170 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171#else
10172 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010173 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010174#endif
10175
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10177 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10178 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10179#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10180 | WIPHY_FLAG_4ADDR_STATION
10181#endif
10182 | WIPHY_FLAG_OFFCHAN_TX;
10183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010184#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10185 wiphy->wowlan = &wowlan_support_cfg80211_init;
10186#else
10187 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10188 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10189 wiphy->wowlan.pattern_min_len = 1;
10190 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10191#endif
10192
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010193 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010194#ifdef FEATURE_WLAN_ESE
10195 || pCfg->isEseIniFeatureEnabled
10196#endif
10197 ) {
10198 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10199 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010200#ifdef FEATURE_WLAN_TDLS
10201 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10202 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10203#endif
10204
10205 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10206
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010207#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10208 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10209#endif
10210
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010211 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010212
10213#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010214 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215#endif
10216
10217 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010218 * driver can still register regulatory callback and
10219 * it will get regulatory settings in wiphy->band[], but
10220 * driver need to determine what to do with both
10221 * regulatory settings
10222 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223
10224 wiphy->reg_notifier = hdd_reg_notifier;
10225
10226#if defined QCA_WIFI_FTM
10227}
10228#endif
10229
10230 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10231
10232 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10233
10234 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10235
Arun Khandavallifae92942016-08-01 13:31:08 +053010236 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10237 | BIT(NL80211_IFTYPE_ADHOC)
10238 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10239 | BIT(NL80211_IFTYPE_P2P_GO)
10240 | BIT(NL80211_IFTYPE_AP)
10241 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010242
Arun Khandavallifae92942016-08-01 13:31:08 +053010243 if (pCfg->advertiseConcurrentOperation) {
10244 if (pCfg->enableMCC) {
10245 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010246
Arun Khandavallifae92942016-08-01 13:31:08 +053010247 for (i = 0;
10248 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10249 i++) {
10250 if (!pCfg->allowMCCGODiffBI)
10251 wlan_hdd_iface_combination[i].
10252 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253 }
10254 }
10255 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010256 ARRAY_SIZE(wlan_hdd_iface_combination);
10257 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010258 }
10259
10260 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010261 * on ini values
10262 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010263 if (!pCfg->ShortGI20MhzEnable) {
10264 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10265 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010266 }
10267
10268 if (!pCfg->ShortGI40MhzEnable) {
10269 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10270 }
10271
10272 if (!pCfg->nChannelBondingMode5GHz) {
10273 wlan_hdd_band_5_ghz.ht_cap.cap &=
10274 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10275 }
10276
Abhishek Singhf512bf32016-05-04 16:47:46 +053010277 /*
10278 * In case of static linked driver at the time of driver unload,
10279 * module exit doesn't happens. Module cleanup helps in cleaning
10280 * of static memory.
10281 * If driver load happens statically, at the time of driver unload,
10282 * wiphy flags don't get reset because of static memory.
10283 * It's better not to store channel in static memory.
10284 */
Dustin Browna30892e2016-10-12 17:28:36 -070010285 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10286 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010287 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010288 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010289 hdd_err("Not enough memory to allocate channels");
10290 return -ENOMEM;
10291 }
Dustin Browna30892e2016-10-12 17:28:36 -070010292 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010293 &hdd_channels_2_4_ghz[0],
10294 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010295 if ((hdd_is_5g_supported(pHddCtx)) &&
10296 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10297 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10298 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10299 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010300 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10301 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010302 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010303 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010304 hdd_err("Not enough memory to allocate channels");
10305 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010306 bands[NL80211_BAND_2GHZ]->channels);
10307 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010308 return -ENOMEM;
10309 }
Dustin Browna30892e2016-10-12 17:28:36 -070010310 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010311 &hdd_channels_5_ghz[0],
10312 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010313 }
10314
Dustin Browna30892e2016-10-12 17:28:36 -070010315 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010316
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010317 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010319
10320 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10321 struct ieee80211_supported_band *band = wiphy->bands[i];
10322
Dustin Browna30892e2016-10-12 17:28:36 -070010323 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 eCSR_BAND_5G == pCfg->nBandCapability) {
10325 /* 5G only */
10326#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10327 /* Enable social channels for P2P */
10328 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10329 (band->channels[j].center_freq))
10330 band->channels[j].flags &=
10331 ~IEEE80211_CHAN_DISABLED;
10332 else
10333#endif
10334 band->channels[j].flags |=
10335 IEEE80211_CHAN_DISABLED;
10336 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010337 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010338 eCSR_BAND_24 == pCfg->nBandCapability) {
10339 /* 2G only */
10340 band->channels[j].flags |=
10341 IEEE80211_CHAN_DISABLED;
10342 continue;
10343 }
10344 }
10345 }
10346 /*Initialise the supported cipher suite details */
10347 wiphy->cipher_suites = hdd_cipher_suites;
10348 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10349
10350 /*signal strength in mBm (100*dBm) */
10351 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10352 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10353
Anurag Chouhan6d760662016-02-20 16:05:43 +053010354 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010355 wiphy->n_vendor_commands =
10356 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10357 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10358
10359 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10360 wiphy->n_vendor_events =
10361 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10362 }
10363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364 if (pCfg->enableDFSMasterCap) {
10365 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10366 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367
10368 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10369
10370#ifdef QCA_HT_2040_COEX
10371 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10372#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010373 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010374
10375#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10376 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10377 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10378 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10379 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10380#endif
10381
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010382 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010383 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010385 EXIT();
10386 return 0;
10387}
10388
Abhishek Singhf512bf32016-05-04 16:47:46 +053010389/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010390 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10391 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010392 *
10393 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010394 * memory allocated in wlan_hdd_cfg80211_init also
10395 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010396 *
10397 * Return: void
10398 */
10399void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10400{
10401 int i;
10402
Dustin Browna30892e2016-10-12 17:28:36 -070010403 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010404 if (NULL != wiphy->bands[i] &&
10405 (NULL != wiphy->bands[i]->channels)) {
10406 qdf_mem_free(wiphy->bands[i]->channels);
10407 wiphy->bands[i]->channels = NULL;
10408 }
10409 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010410 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010411}
10412
Yingying Tang80e15f32016-09-27 18:23:01 +080010413/**
10414 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10415 * @hdd_ctx: HDD context
10416 *
10417 * this function will update capabilities for supported bands
10418 *
10419 * Return: void
10420 */
10421static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10422{
10423 uint32_t val32;
10424 uint16_t val16;
10425 tSirMacHTCapabilityInfo *ht_cap_info;
10426 QDF_STATUS status;
10427
10428 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10429 if (QDF_STATUS_SUCCESS != status) {
10430 hdd_err("could not get HT capability info");
10431 val32 = 0;
10432 }
10433 val16 = (uint16_t)val32;
10434 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10435
10436 if (ht_cap_info->txSTBC == true) {
10437 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10438 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10439 IEEE80211_HT_CAP_TX_STBC;
10440 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10441 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10442 IEEE80211_HT_CAP_TX_STBC;
10443 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010444
10445 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10446 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10447 vht_cap.vht_supported = 0;
10448 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10449 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10450 vht_cap.vht_supported = 0;
10451 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10452 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010453}
10454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010455/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010456 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010457 * initialization. In wlan_hdd_cfg80211_init, only the
10458 * default values will be initialized. The final initialization
10459 * of all required members can be done here.
10460 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010461void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010462{
Yingying Tang80e15f32016-09-27 18:23:01 +080010463 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10464
10465 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010466}
10467
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010468/**
10469 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10470 * @cfg: hdd cfg
10471 *
10472 * this function update 11n mode in hdd cfg
10473 *
10474 * Return: void
10475 */
10476void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10477{
10478 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10479 hdd_notice("support 11ac");
10480 } else {
10481 hdd_notice("not support 11ac");
10482 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10483 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10484 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10485 cfg->sap_p2p_11ac_override = 0;
10486 }
10487 }
10488}
10489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010490/* In this function we are registering wiphy. */
10491int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10492{
10493 ENTER();
10494 /* Register our wiphy dev with cfg80211 */
10495 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010496 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010497 return -EIO;
10498 }
10499
10500 EXIT();
10501 return 0;
10502}
10503
10504/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010505 * HDD function to update wiphy capability based on target offload status.
10506 *
10507 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10508 * capability even before downloading firmware to the target. In discrete
10509 * case, host will get know certain offload capability (say sched_scan
10510 * caps) only after downloading firmware to the target and target boots up.
10511 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10512 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010513 */
10514void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10515{
10516#ifdef FEATURE_WLAN_SCAN_PNO
10517 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10518 struct hdd_config *pCfg = pHddCtx->config;
10519
10520 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10521 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010522 * have PNO support.
10523 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010524 if (!pCfg->PnoOffload) {
10525 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10526 wiphy->max_sched_scan_ssids = 0;
10527 wiphy->max_match_sets = 0;
10528 wiphy->max_sched_scan_ie_len = 0;
10529 }
10530#endif
10531}
10532
10533/* This function registers for all frame which supplicant is interested in */
10534void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10535{
10536 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10537 /* Register for all P2P action, public action etc frames */
10538 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10539
10540 ENTER();
10541
Abhishek Singh7996eb72015-12-30 17:24:02 +053010542 /* Register frame indication call back */
10543 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10544
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010545 /* Register for p2p ack indication */
10546 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10547
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010548 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010549 * initialized. Once we will move to 2.6.37 kernel, in which we have
10550 * frame register ops, we will move this code as a part of that
10551 */
10552
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010553 /* GAS Initial Request */
10554 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10555 (uint8_t *) GAS_INITIAL_REQ,
10556 GAS_INITIAL_REQ_SIZE);
10557
10558 /* GAS Initial Response */
10559 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10560 (uint8_t *) GAS_INITIAL_RSP,
10561 GAS_INITIAL_RSP_SIZE);
10562
10563 /* GAS Comeback Request */
10564 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10565 (uint8_t *) GAS_COMEBACK_REQ,
10566 GAS_COMEBACK_REQ_SIZE);
10567
10568 /* GAS Comeback Response */
10569 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10570 (uint8_t *) GAS_COMEBACK_RSP,
10571 GAS_COMEBACK_RSP_SIZE);
10572
10573 /* P2P Public Action */
10574 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10575 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10576 P2P_PUBLIC_ACTION_FRAME_SIZE);
10577
10578 /* P2P Action */
10579 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10580 (uint8_t *) P2P_ACTION_FRAME,
10581 P2P_ACTION_FRAME_SIZE);
10582
10583 /* WNM BSS Transition Request frame */
10584 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10585 (uint8_t *) WNM_BSS_ACTION_FRAME,
10586 WNM_BSS_ACTION_FRAME_SIZE);
10587
10588 /* WNM-Notification */
10589 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10590 (uint8_t *) WNM_NOTIFICATION_FRAME,
10591 WNM_NOTIFICATION_FRAME_SIZE);
10592}
10593
10594void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10595{
10596 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10597 /* Register for all P2P action, public action etc frames */
10598 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10599
10600 ENTER();
10601
10602 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010603 * initialized. Once we will move to 2.6.37 kernel, in which we have
10604 * frame register ops, we will move this code as a part of that
10605 */
10606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010607 /* GAS Initial Request */
10608
10609 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10610 (uint8_t *) GAS_INITIAL_REQ,
10611 GAS_INITIAL_REQ_SIZE);
10612
10613 /* GAS Initial Response */
10614 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10615 (uint8_t *) GAS_INITIAL_RSP,
10616 GAS_INITIAL_RSP_SIZE);
10617
10618 /* GAS Comeback Request */
10619 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10620 (uint8_t *) GAS_COMEBACK_REQ,
10621 GAS_COMEBACK_REQ_SIZE);
10622
10623 /* GAS Comeback Response */
10624 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10625 (uint8_t *) GAS_COMEBACK_RSP,
10626 GAS_COMEBACK_RSP_SIZE);
10627
10628 /* P2P Public Action */
10629 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10630 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10631 P2P_PUBLIC_ACTION_FRAME_SIZE);
10632
10633 /* P2P Action */
10634 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10635 (uint8_t *) P2P_ACTION_FRAME,
10636 P2P_ACTION_FRAME_SIZE);
10637
10638 /* WNM-Notification */
10639 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10640 (uint8_t *) WNM_NOTIFICATION_FRAME,
10641 WNM_NOTIFICATION_FRAME_SIZE);
10642}
10643
10644#ifdef FEATURE_WLAN_WAPI
10645void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10646 const uint8_t *mac_addr, const uint8_t *key,
10647 int key_Len)
10648{
10649 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10650 tCsrRoamSetKey setKey;
10651 bool isConnected = true;
10652 int status = 0;
10653 uint32_t roamId = 0xFF;
10654 uint8_t *pKeyPtr = NULL;
10655 int n = 0;
10656
Jeff Johnson46b40792016-06-29 14:03:14 -070010657 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010658 hdd_device_mode_to_string(pAdapter->device_mode),
10659 pAdapter->device_mode);
10660
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010661 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010662 setKey.keyId = key_index; /* Store Key ID */
10663 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10664 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10665 setKey.paeRole = 0; /* the PAE role */
10666 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010667 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010668 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010669 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010670 }
10671 setKey.keyLength = key_Len;
10672 pKeyPtr = setKey.Key;
10673 memcpy(pKeyPtr, key, key_Len);
10674
Jeff Johnson46b40792016-06-29 14:03:14 -070010675 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010676 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010677 hdd_notice("WAPI KEY Data[%d]:%02x ",
10678 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010679
10680 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10681 if (isConnected) {
10682 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10683 pAdapter->sessionId, &setKey, &roamId);
10684 }
10685 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010686 hdd_err("sme_roam_set_key returned ERROR status= %d",
10687 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010688 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10689 }
10690}
10691#endif /* FEATURE_WLAN_WAPI */
10692
10693uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10694 uint8_t eid)
10695{
10696 int left = length;
10697 uint8_t *ptr = (uint8_t *)ies_ptr;
10698 uint8_t elem_id, elem_len;
10699
10700 while (left >= 2) {
10701 elem_id = ptr[0];
10702 elem_len = ptr[1];
10703 left -= 2;
10704 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010705 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706 eid, elem_len, left);
10707 return NULL;
10708 }
10709 if (elem_id == eid) {
10710 return ptr;
10711 }
10712
10713 left -= elem_len;
10714 ptr += (elem_len + 2);
10715 }
10716 return NULL;
10717}
10718
10719/*
10720 * FUNCTION: wlan_hdd_validate_operation_channel
10721 * called by wlan_hdd_cfg80211_start_bss() and
10722 * wlan_hdd_set_channel()
10723 * This function validates whether given channel is part of valid
10724 * channel list.
10725 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010726QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010727 int channel)
10728{
10729
10730 uint32_t num_ch = 0;
10731 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10732 u32 indx = 0;
10733 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10734 uint8_t fValidChannel = false, count = 0;
10735 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10736
10737 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10738
10739 if (hdd_pConfig_ini->sapAllowAllChannel) {
10740 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010741 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010742 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010743 fValidChannel = true;
10744 break;
10745 }
10746 }
10747 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010748 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010749 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010750 }
10751 } else {
10752 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10753 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010754 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010755 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010756 }
10757 for (indx = 0; indx < num_ch; indx++) {
10758 if (channel == valid_ch[indx]) {
10759 break;
10760 }
10761 }
10762
10763 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010764 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010765 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010766 }
10767 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010768 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010769
10770}
10771
10772#ifdef DHCP_SERVER_OFFLOAD
10773static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10774{
10775 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10776 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10777 uint8_t numEntries = 0;
10778 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10779 uint8_t num;
10780 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010781 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010782 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010783 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010784 return;
10785 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010786 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10787 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10788 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10789 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10790 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10791 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010792 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 goto end;
10794 }
10795 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010796 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010797 goto end;
10798 }
10799 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010800 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 goto end;
10802 }
10803 for (num = 0; num < numEntries; num++) {
10804 temp = srv_ip[num];
10805 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10806 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010807 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010809 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810 goto end;
10811 }
Jeff Johnson77848112016-06-29 14:52:06 -070010812 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010814 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010815 return;
10816}
10817#endif /* DHCP_SERVER_OFFLOAD */
10818
10819static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10820 struct net_device *dev,
10821 struct bss_parameters *params)
10822{
10823 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10824 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10825 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010826 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827
10828 ENTER();
10829
Anurag Chouhan6d760662016-02-20 16:05:43 +053010830 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010831 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832 return -EINVAL;
10833 }
10834
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010835 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10836 hdd_err("invalid session id: %d", pAdapter->sessionId);
10837 return -EINVAL;
10838 }
10839
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010840 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010841 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10842 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010843 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010844 hdd_device_mode_to_string(pAdapter->device_mode),
10845 pAdapter->device_mode, params->ap_isolate);
10846
10847 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10848 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010849 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851
Krunal Sonib4326f22016-03-10 13:05:51 -080010852 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10853 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010854 return -EOPNOTSUPP;
10855 }
10856
10857 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010858 * want to update this parameter
10859 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010860 if (-1 != params->ap_isolate) {
10861 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10862 !!params->ap_isolate;
10863
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010864 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865 pAdapter->sessionId,
10866 pAdapter->sessionCtx.
10867 ap.
10868 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010869 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010870 ret = -EINVAL;
10871 }
10872 }
10873
10874 EXIT();
10875 return ret;
10876}
10877
Krunal Soni8c37e322016-02-03 16:08:37 -080010878/**
10879 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10880 * @ndev: pointer to net device provided by supplicant
10881 * @type: type of the interface, upper layer wanted to change
10882 *
10883 * Upper layer provides the new interface mode that needs to be changed
10884 * for given net device
10885 *
10886 * Return: success or failure in terms of integer value
10887 */
10888static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010889 enum nl80211_iftype type)
10890{
Krunal Soni8c37e322016-02-03 16:08:37 -080010891 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10892 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10893 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 hdd_wext_state_t *wext;
10895 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010896 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897
10898 ENTER();
10899
Krunal Soni8c37e322016-02-03 16:08:37 -080010900 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010901 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010902 return 0;
10903 }
10904
10905 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010906 hdd_stop_adapter(hdd_ctx, adapter, true);
10907 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010908 wdev->iftype = type;
10909 /*Check for sub-string p2p to confirm its a p2p interface */
10910 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010911 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010912 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010913 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010914 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010915 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010917 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010918 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010919 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010921 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10922 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010923 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10924 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010925 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010926 adapter->scan_info.scanAddIE.length;
10927 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010928 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010929 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10930 wext->roamProfile.phyMode =
10931 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10932 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010933 EXIT();
10934 return status;
10935}
10936
10937static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10938 struct net_device *dev,
10939 struct bss_parameters *params)
10940{
10941 int ret;
10942
10943 cds_ssr_protect(__func__);
10944 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10945 cds_ssr_unprotect(__func__);
10946
10947 return ret;
10948}
10949
10950/* FUNCTION: wlan_hdd_change_country_code_cd
10951 * to wait for contry code completion
10952 */
10953void *wlan_hdd_change_country_code_cb(void *pAdapter)
10954{
10955 hdd_adapter_t *call_back_pAdapter = pAdapter;
10956 complete(&call_back_pAdapter->change_country_code);
10957 return NULL;
10958}
10959
Rajeev Kumar98edb772016-01-19 12:42:19 -080010960/**
10961 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10962 * @wiphy: Pointer to the wiphy structure
10963 * @ndev: Pointer to the net device
10964 * @type: Interface type
10965 * @flags: Flags for change interface
10966 * @params: Pointer to change interface parameters
10967 *
10968 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969 */
10970static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10971 struct net_device *ndev,
10972 enum nl80211_iftype type,
10973 u32 *flags,
10974 struct vif_params *params)
10975{
10976 struct wireless_dev *wdev;
10977 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10978 hdd_context_t *pHddCtx;
10979 tCsrRoamProfile *pRoamProfile = NULL;
10980 eCsrRoamBssType LastBSSType;
10981 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010982 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010983 int status;
10984
10985 ENTER();
10986
Anurag Chouhan6d760662016-02-20 16:05:43 +053010987 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010988 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 return -EINVAL;
10990 }
10991
10992 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10993 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010994 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010995 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010997 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010998 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
10999 pAdapter->sessionId, type));
11000
Jeff Johnson77848112016-06-29 14:52:06 -070011001 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 pAdapter->device_mode, type);
11003
Arun Khandavallifae92942016-08-01 13:31:08 +053011004 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11005 if (status) {
11006 hdd_err("Failed to start modules");
11007 return -EINVAL;
11008 }
11009
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011010 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011011 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11012 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011013 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014 return -EINVAL;
11015 }
11016
11017 pConfig = pHddCtx->config;
11018 wdev = ndev->ieee80211_ptr;
11019
11020 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011021 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011022
11023 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
11024
Krunal Sonib4326f22016-03-10 13:05:51 -080011025 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11026 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11027 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11028 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011029 hdd_wext_state_t *pWextState =
11030 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11031
11032 pRoamProfile = &pWextState->roamProfile;
11033 LastBSSType = pRoamProfile->BSSType;
11034
11035 switch (type) {
11036 case NL80211_IFTYPE_STATION:
11037 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011038 case NL80211_IFTYPE_ADHOC:
11039 if (type == NL80211_IFTYPE_ADHOC) {
11040 wlan_hdd_tdls_exit(pAdapter);
11041 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011042 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011043 }
11044 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11045 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011046 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011047 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011048 if (hdd_start_adapter(pAdapter)) {
11049 hdd_err("Failed to start adapter :%d",
11050 pAdapter->device_mode);
11051 return -EINVAL;
11052 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011053 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011054 case NL80211_IFTYPE_AP:
11055 case NL80211_IFTYPE_P2P_GO:
11056 {
Jeff Johnson77848112016-06-29 14:52:06 -070011057 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011058 (type ==
11059 NL80211_IFTYPE_AP) ? "SoftAP" :
11060 "P2pGo");
11061
11062 /* Cancel any remain on channel for GO mode */
11063 if (NL80211_IFTYPE_P2P_GO == type) {
11064 wlan_hdd_cancel_existing_remain_on_channel
11065 (pAdapter);
11066 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011067
Arun Khandavallifae92942016-08-01 13:31:08 +053011068 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069 /* De-init the adapter */
11070 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11071 memset(&pAdapter->sessionCtx, 0,
11072 sizeof(pAdapter->sessionCtx));
11073 pAdapter->device_mode =
11074 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011075 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11076 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011077
11078 /*
11079 * Fw will take care incase of concurrency
11080 */
11081
Krunal Sonib4326f22016-03-10 13:05:51 -080011082 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011084 /* To meet Android requirements create
11085 * a randomized MAC address of the
11086 * form 02:1A:11:Fx:xx:xx
11087 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011088 get_random_bytes(&ndev->dev_addr[3], 3);
11089 ndev->dev_addr[0] = 0x02;
11090 ndev->dev_addr[1] = 0x1A;
11091 ndev->dev_addr[2] = 0x11;
11092 ndev->dev_addr[3] |= 0xF0;
11093 memcpy(pAdapter->macAddressCurrent.
11094 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011095 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 pr_info("wlan: Generated HotSpot BSSID "
11097 MAC_ADDRESS_STR "\n",
11098 MAC_ADDR_ARRAY(ndev->dev_addr));
11099 }
11100
11101 hdd_set_ap_ops(pAdapter->dev);
11102
Arun Khandavallifae92942016-08-01 13:31:08 +053011103 if (hdd_start_adapter(pAdapter)) {
11104 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011105 return -EINVAL;
11106 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107 /* Interface type changed update in wiphy structure */
11108 if (wdev) {
11109 wdev->iftype = type;
11110 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011111 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011112 return -EINVAL;
11113 }
11114 goto done;
11115 }
11116
11117 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011118 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011119 type);
11120 return -EOPNOTSUPP;
11121 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011122 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11123 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011124 switch (type) {
11125 case NL80211_IFTYPE_STATION:
11126 case NL80211_IFTYPE_P2P_CLIENT:
11127 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011128 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11129 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011130 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011131 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011132 if (hdd_start_adapter(pAdapter)) {
11133 hdd_err("Failed to start adapter :%d",
11134 pAdapter->device_mode);
11135 return -EINVAL;
11136 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011137 goto done;
11138
11139 case NL80211_IFTYPE_AP:
11140 case NL80211_IFTYPE_P2P_GO:
11141 wdev->iftype = type;
11142 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011143 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 goto done;
11145
11146 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011147 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011148 type);
11149 return -EOPNOTSUPP;
11150 }
11151 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011152 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 pAdapter->device_mode);
11154 return -EOPNOTSUPP;
11155 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156done:
11157 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011158 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011160 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161
11162 EXIT();
11163 return 0;
11164}
11165
Rajeev Kumar98edb772016-01-19 12:42:19 -080011166/**
11167 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11168 * @wiphy: Pointer to the wiphy structure
11169 * @ndev: Pointer to the net device
11170 * @type: Interface type
11171 * @flags: Flags for change interface
11172 * @params: Pointer to change interface parameters
11173 *
11174 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011175 */
11176static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11177 struct net_device *ndev,
11178 enum nl80211_iftype type,
11179 u32 *flags,
11180 struct vif_params *params)
11181{
11182 int ret;
11183
11184 cds_ssr_protect(__func__);
11185 ret =
11186 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11187 cds_ssr_unprotect(__func__);
11188
11189 return ret;
11190}
11191
11192#ifdef FEATURE_WLAN_TDLS
11193static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11194 int index, uint8_t match)
11195{
11196 int i;
11197 for (i = 0; i < index; i++) {
11198 if (arr[i] == match)
11199 return true;
11200 }
11201 return false;
11202}
11203#endif
11204
11205/**
11206 * __wlan_hdd_change_station() - change station
11207 * @wiphy: Pointer to the wiphy structure
11208 * @dev: Pointer to the net device.
11209 * @mac: bssid
11210 * @params: Pointer to station parameters
11211 *
11212 * Return: 0 for success, error number on failure.
11213 */
11214#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11215static int __wlan_hdd_change_station(struct wiphy *wiphy,
11216 struct net_device *dev,
11217 const uint8_t *mac,
11218 struct station_parameters *params)
11219#else
11220static int __wlan_hdd_change_station(struct wiphy *wiphy,
11221 struct net_device *dev,
11222 uint8_t *mac,
11223 struct station_parameters *params)
11224#endif
11225{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011226 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11228 hdd_context_t *pHddCtx;
11229 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011230 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011231#ifdef FEATURE_WLAN_TDLS
11232 tCsrStaParams StaParams = { 0 };
11233 uint8_t isBufSta = 0;
11234 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011235 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011236#endif
11237 int ret;
11238
11239 ENTER();
11240
Anurag Chouhan6d760662016-02-20 16:05:43 +053011241 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011242 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 return -EINVAL;
11244 }
11245
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011246 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 TRACE_CODE_HDD_CHANGE_STATION,
11248 pAdapter->sessionId, params->listen_interval));
11249
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011250 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11251 hdd_err("invalid session id: %d", pAdapter->sessionId);
11252 return -EINVAL;
11253 }
11254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011255 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11256 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011257 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259
11260 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11261
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011262 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263
Krunal Sonib4326f22016-03-10 13:05:51 -080011264 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11265 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011266 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11267 status =
11268 hdd_softap_change_sta_state(pAdapter,
11269 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011270 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011271
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011272 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011273 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 return -EINVAL;
11275 }
11276 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011277 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11278 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011279#ifdef FEATURE_WLAN_TDLS
11280 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011281
11282 if (cds_is_sub_20_mhz_enabled()) {
11283 hdd_err("TDLS not allowed with sub 20 MHz");
11284 return -EINVAL;
11285 }
11286
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 StaParams.capability = params->capability;
11288 StaParams.uapsd_queues = params->uapsd_queues;
11289 StaParams.max_sp = params->max_sp;
11290
11291 /* Convert (first channel , number of channels) tuple to
11292 * the total list of channels. This goes with the assumption
11293 * that if the first channel is < 14, then the next channels
11294 * are an incremental of 1 else an incremental of 4 till the number
11295 * of channels.
11296 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011297 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298 if (0 != params->supported_channels_len) {
11299 int i = 0, j = 0, k = 0, no_of_channels = 0;
11300 int num_unique_channels;
11301 int next;
11302 for (i = 0;
11303 i < params->supported_channels_len
11304 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11305 int wifi_chan_index;
11306 if (!wlan_hdd_is_duplicate_channel
11307 (StaParams.supported_channels, j,
11308 params->supported_channels[i])) {
11309 StaParams.
11310 supported_channels[j] =
11311 params->
11312 supported_channels[i];
11313 } else {
11314 continue;
11315 }
11316 wifi_chan_index =
11317 ((StaParams.supported_channels[j] <=
11318 HDD_CHANNEL_14) ? 1 : 4);
11319 no_of_channels =
11320 params->supported_channels[i + 1];
11321
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011322 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 -080011323 StaParams.
11324 supported_channels[j],
11325 wifi_chan_index,
11326 no_of_channels);
11327 for (k = 1; k <= no_of_channels &&
11328 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11329 k++) {
11330 next =
11331 StaParams.
11332 supported_channels[j] +
11333 wifi_chan_index;
11334 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11335 StaParams.
11336 supported_channels[j
11337 +
11338 1]
11339 = next;
11340 } else {
11341 continue;
11342 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011343 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 j + 1,
11345 StaParams.
11346 supported_channels[j +
11347 1]);
11348 j += 1;
11349 }
11350 }
11351 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011352 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011354 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011355 StaParams.
11356 supported_channels[i]);
11357 }
11358 if (MAX_CHANNEL < num_unique_channels)
11359 num_unique_channels = MAX_CHANNEL;
11360 StaParams.supported_channels_len =
11361 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011362 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011363 StaParams.supported_channels_len);
11364 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011365 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011366 params->supported_oper_classes,
11367 params->supported_oper_classes_len);
11368 StaParams.supported_oper_classes_len =
11369 params->supported_oper_classes_len;
11370
11371 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011372 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011373 params->ext_capab,
11374 sizeof(StaParams.extn_capability));
11375
11376 if (NULL != params->ht_capa) {
11377 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011378 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011379 sizeof(tSirHTCap));
11380 }
11381
11382 StaParams.supported_rates_len =
11383 params->supported_rates_len;
11384
11385 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11386 * The supported_rates array , for all the structures propogating till Add Sta
11387 * to the firmware has to be modified , if the supplicant (ieee80211) is
11388 * modified to send more rates.
11389 */
11390
11391 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11392 */
11393 if (StaParams.supported_rates_len >
11394 SIR_MAC_MAX_SUPP_RATES)
11395 StaParams.supported_rates_len =
11396 SIR_MAC_MAX_SUPP_RATES;
11397
11398 if (0 != StaParams.supported_rates_len) {
11399 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011400 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011401 params->supported_rates,
11402 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011403 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011404 StaParams.supported_rates_len);
11405 for (i = 0; i < StaParams.supported_rates_len;
11406 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011407 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011408 StaParams.supported_rates[i]);
11409 }
11410
11411 if (NULL != params->vht_capa) {
11412 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011413 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011414 params->vht_capa,
11415 sizeof(tSirVHTCap));
11416 }
11417
11418 if (0 != params->ext_capab_len) {
11419 /*Define A Macro : TODO Sunil */
11420 if ((1 << 4) & StaParams.extn_capability[3]) {
11421 isBufSta = 1;
11422 }
11423 /* TDLS Channel Switching Support */
11424 if ((1 << 6) & StaParams.extn_capability[3]) {
11425 isOffChannelSupported = 1;
11426 }
11427 }
11428
Nitesh Shah99934ac2016-09-05 15:54:08 +053011429 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011430 (params->ht_capa || params->vht_capa ||
11431 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011432 is_qos_wmm_sta = true;
11433
11434 hdd_notice("%s: TDLS Peer is QOS capable"
11435 " is_qos_wmm_sta= %d HTcapPresent = %d",
11436 __func__, is_qos_wmm_sta,
11437 StaParams.htcap_present);
11438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011439 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011440 &StaParams,
11441 isBufSta,
11442 isOffChannelSupported,
11443 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011444 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011445 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 return -EINVAL;
11447 }
11448
11449 status =
11450 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11451 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011452 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011453 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011454 return -EINVAL;
11455 }
11456 }
11457#endif
11458 }
11459 EXIT();
11460 return ret;
11461}
11462
11463/**
11464 * wlan_hdd_change_station() - cfg80211 change station handler function
11465 * @wiphy: Pointer to the wiphy structure
11466 * @dev: Pointer to the net device.
11467 * @mac: bssid
11468 * @params: Pointer to station parameters
11469 *
11470 * This is the cfg80211 change station handler function which invokes
11471 * the internal function @__wlan_hdd_change_station with
11472 * SSR protection.
11473 *
11474 * Return: 0 for success, error number on failure.
11475 */
11476#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11477static int wlan_hdd_change_station(struct wiphy *wiphy,
11478 struct net_device *dev,
11479 const u8 *mac,
11480 struct station_parameters *params)
11481#else
11482static int wlan_hdd_change_station(struct wiphy *wiphy,
11483 struct net_device *dev,
11484 u8 *mac,
11485 struct station_parameters *params)
11486#endif
11487{
11488 int ret;
11489
11490 cds_ssr_protect(__func__);
11491 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11492 cds_ssr_unprotect(__func__);
11493
11494 return ret;
11495}
11496
11497/*
11498 * FUNCTION: __wlan_hdd_cfg80211_add_key
11499 * This function is used to initialize the key information
11500 */
11501static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11502 struct net_device *ndev,
11503 u8 key_index, bool pairwise,
11504 const u8 *mac_addr,
11505 struct key_params *params)
11506{
11507 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11508 tCsrRoamSetKey setKey;
11509 int status;
11510 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011512 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 hdd_context_t *pHddCtx;
11514 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11515
11516 ENTER();
11517
Anurag Chouhan6d760662016-02-20 16:05:43 +053011518 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011519 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 return -EINVAL;
11521 }
11522
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011523 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11524 hdd_err("invalid session id: %d", pAdapter->sessionId);
11525 return -EINVAL;
11526 }
11527
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011528 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11530 pAdapter->sessionId, params->key_len));
11531 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11532 status = wlan_hdd_validate_context(pHddCtx);
11533
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011534 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011536
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011537 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 hdd_device_mode_to_string(pAdapter->device_mode),
11539 pAdapter->device_mode);
11540
11541 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011542 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543
11544 return -EINVAL;
11545 }
11546
11547 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011548 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011549
11550 return -EINVAL;
11551 }
11552
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011553 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554
11555 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011556 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 setKey.keyId = key_index;
11558 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011559 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011560
11561 switch (params->cipher) {
11562 case WLAN_CIPHER_SUITE_WEP40:
11563 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11564 break;
11565
11566 case WLAN_CIPHER_SUITE_WEP104:
11567 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11568 break;
11569
11570 case WLAN_CIPHER_SUITE_TKIP:
11571 {
11572 u8 *pKey = &setKey.Key[0];
11573 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11574
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011575 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011576
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011577 /* Supplicant sends the 32bytes key in this order
11578 *
11579 * |--------------|----------|----------|
11580 * | Tk1 |TX-MIC | RX Mic |
11581 * |--------------|----------|----------|
11582 * <---16bytes---><--8bytes--><--8bytes-->
11583 *
11584 * Sme expects the 32 bytes key to be in the below order
11585 *
11586 * |--------------|----------|----------|
11587 * | Tk1 |RX-MIC | TX Mic |
11588 * |--------------|----------|----------|
11589 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590 */
11591 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011592 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011593
11594 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011595 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011596
11597 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011598 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011599
11600 break;
11601 }
11602
11603 case WLAN_CIPHER_SUITE_CCMP:
11604 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11605 break;
11606
11607#ifdef FEATURE_WLAN_WAPI
11608 case WLAN_CIPHER_SUITE_SMS4:
11609 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011610 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11612 mac_addr, params->key,
11613 params->key_len);
11614 return 0;
11615 }
11616#endif
11617
11618#ifdef FEATURE_WLAN_ESE
11619 case WLAN_CIPHER_SUITE_KRK:
11620 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11621 break;
11622#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11623 case WLAN_CIPHER_SUITE_BTK:
11624 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11625 break;
11626#endif
11627#endif
11628
11629#ifdef WLAN_FEATURE_11W
11630 case WLAN_CIPHER_SUITE_AES_CMAC:
11631 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11632 break;
11633#endif
11634
11635 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011636 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 return -EOPNOTSUPP;
11638 }
11639
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641
11642 if (!pairwise) {
11643 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011644 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011646 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011647 } else {
11648 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011649 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011651 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011653 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011654 /* if a key is already installed, block all subsequent ones */
11655 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011656 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657 return 0;
11658 }
11659
11660 setKey.keyDirection = eSIR_TX_RX;
11661 /*Set the group key */
11662 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11663 pAdapter->sessionId, &setKey, &roamId);
11664
11665 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011666 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011667 return -EINVAL;
11668 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011669 /* Save the keys here and call sme_roam_set_key for setting
11670 * the PTK after peer joins the IBSS network
11671 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011672 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 &setKey, sizeof(tCsrRoamSetKey));
11674
11675 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11676 return status;
11677 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011678 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11679 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11681 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011682 status = wlansap_set_key_sta(
11683 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011684 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011685 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 __LINE__, status);
11687 }
11688 }
11689
11690 /* Save the key in ap ctx for use on START_BASS and restart */
11691 if (pairwise ||
11692 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11693 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011694 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011695 sizeof(tCsrRoamSetKey));
11696 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011697 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698 sizeof(tCsrRoamSetKey));
11699
Krunal Sonib4326f22016-03-10 13:05:51 -080011700 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11701 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702 hdd_wext_state_t *pWextState =
11703 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11704 hdd_station_ctx_t *pHddStaCtx =
11705 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11706
11707 if (!pairwise) {
11708 /* set group key */
11709 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011710 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011711 __func__, __LINE__);
11712 hdd_perform_roam_set_key_complete(pAdapter);
11713 }
11714 }
11715
11716 pWextState->roamProfile.Keys.KeyLength[key_index] =
11717 (u8) params->key_len;
11718
11719 pWextState->roamProfile.Keys.defaultIndex = key_index;
11720
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011721 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011722 KeyMaterial[key_index][0], params->key,
11723 params->key_len);
11724
11725 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11726
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011727 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011728 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11729 setKey.keyDirection);
11730
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011731 /* The supplicant may attempt to set the PTK once
11732 * pre-authentication is done. Save the key in the
11733 * UMAC and include it in the ADD BSS request
11734 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011735 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011737 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011738 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011740 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011741 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742 return -EINVAL;
11743 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744
11745 /* issue set key request to SME */
11746 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11747 pAdapter->sessionId, &setKey, &roamId);
11748
11749 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011750 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011751 pHddStaCtx->roam_info.roamingState =
11752 HDD_ROAM_STATE_NONE;
11753 return -EINVAL;
11754 }
11755
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011756 /* in case of IBSS as there was no information
11757 * available about WEP keys during IBSS join, group
11758 * key intialized with NULL key, so re-initialize
11759 * group key with correct value
11760 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 if ((eCSR_BSS_TYPE_START_IBSS ==
11762 pWextState->roamProfile.BSSType)
11763 &&
11764 !((IW_AUTH_KEY_MGMT_802_1X ==
11765 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11766 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11767 pHddStaCtx->conn_info.authType)
11768 )
11769 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11770 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11771 )
11772 ) {
11773 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011774 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011776 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011777 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11778 setKey.keyDirection);
11779
11780 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11781 pAdapter->sessionId, &setKey,
11782 &roamId);
11783
11784 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011785 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011786 pHddStaCtx->roam_info.roamingState =
11787 HDD_ROAM_STATE_NONE;
11788 return -EINVAL;
11789 }
11790 }
11791 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011792 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011793 return 0;
11794}
11795
11796static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11797 struct net_device *ndev,
11798 u8 key_index, bool pairwise,
11799 const u8 *mac_addr,
11800 struct key_params *params)
11801{
11802 int ret;
11803 cds_ssr_protect(__func__);
11804 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11805 mac_addr, params);
11806 cds_ssr_unprotect(__func__);
11807
11808 return ret;
11809}
11810
11811/*
11812 * FUNCTION: __wlan_hdd_cfg80211_get_key
11813 * This function is used to get the key information
11814 */
11815static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11816 struct net_device *ndev,
11817 u8 key_index, bool pairwise,
11818 const u8 *mac_addr, void *cookie,
11819 void (*callback)(void *cookie,
11820 struct key_params *)
11821 )
11822{
11823 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11824 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11825 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11826 struct key_params params;
11827
11828 ENTER();
11829
Anurag Chouhan6d760662016-02-20 16:05:43 +053011830 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011831 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832 return -EINVAL;
11833 }
11834
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011835 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011836 hdd_device_mode_to_string(pAdapter->device_mode),
11837 pAdapter->device_mode);
11838
11839 memset(&params, 0, sizeof(params));
11840
11841 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011842 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843 key_index);
11844 return -EINVAL;
11845 }
11846
11847 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11848 case eCSR_ENCRYPT_TYPE_NONE:
11849 params.cipher = IW_AUTH_CIPHER_NONE;
11850 break;
11851
11852 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11853 case eCSR_ENCRYPT_TYPE_WEP40:
11854 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11855 break;
11856
11857 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11858 case eCSR_ENCRYPT_TYPE_WEP104:
11859 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11860 break;
11861
11862 case eCSR_ENCRYPT_TYPE_TKIP:
11863 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11864 break;
11865
11866 case eCSR_ENCRYPT_TYPE_AES:
11867 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11868 break;
11869
11870 default:
11871 params.cipher = IW_AUTH_CIPHER_NONE;
11872 break;
11873 }
11874
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011875 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 TRACE_CODE_HDD_CFG80211_GET_KEY,
11877 pAdapter->sessionId, params.cipher));
11878
11879 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11880 params.seq_len = 0;
11881 params.seq = NULL;
11882 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11883 callback(cookie, &params);
11884
11885 EXIT();
11886 return 0;
11887}
11888
11889static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11890 struct net_device *ndev,
11891 u8 key_index, bool pairwise,
11892 const u8 *mac_addr, void *cookie,
11893 void (*callback)(void *cookie,
11894 struct key_params *)
11895 )
11896{
11897 int ret;
11898
11899 cds_ssr_protect(__func__);
11900 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11901 mac_addr, cookie, callback);
11902 cds_ssr_unprotect(__func__);
11903
11904 return ret;
11905}
11906
11907/**
11908 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11909 * @wiphy: wiphy interface context
11910 * @ndev: pointer to net device
11911 * @key_index: Key index used in 802.11 frames
11912 * @unicast: true if it is unicast key
11913 * @multicast: true if it is multicast key
11914 *
11915 * This function is required for cfg80211_ops API.
11916 * It is used to delete the key information
11917 * Underlying hardware implementation does not have API to delete the
11918 * encryption key. It is automatically deleted when the peer is
11919 * removed. Hence this function currently does nothing.
11920 * Future implementation may interprete delete key operation to
11921 * replacing the key with a random junk value, effectively making it
11922 * useless.
11923 *
11924 * Return: status code, always 0.
11925 */
11926
11927static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11928 struct net_device *ndev,
11929 u8 key_index,
11930 bool pairwise, const u8 *mac_addr)
11931{
11932 EXIT();
11933 return 0;
11934}
11935
11936/**
11937 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11938 * @wiphy: Pointer to wiphy structure.
11939 * @dev: Pointer to net_device structure.
11940 * @key_index: key index
11941 * @pairwise: pairwise
11942 * @mac_addr: mac address
11943 *
11944 * This is the cfg80211 delete key handler function which invokes
11945 * the internal function @__wlan_hdd_cfg80211_del_key with
11946 * SSR protection.
11947 *
11948 * Return: 0 for success, error number on failure.
11949 */
11950static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11951 struct net_device *dev,
11952 u8 key_index,
11953 bool pairwise, const u8 *mac_addr)
11954{
11955 int ret;
11956
11957 cds_ssr_protect(__func__);
11958 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11959 pairwise, mac_addr);
11960 cds_ssr_unprotect(__func__);
11961
11962 return ret;
11963}
11964
11965/*
11966 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11967 * This function is used to set the default tx key index
11968 */
11969static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11970 struct net_device *ndev,
11971 u8 key_index,
11972 bool unicast, bool multicast)
11973{
11974 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11975 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11976 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11977 hdd_context_t *pHddCtx;
11978 int status;
11979
11980 ENTER();
11981
Anurag Chouhan6d760662016-02-20 16:05:43 +053011982 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011983 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 return -EINVAL;
11985 }
11986
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011987 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11988 hdd_err("invalid session id: %d", pAdapter->sessionId);
11989 return -EINVAL;
11990 }
11991
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011992 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
11994 pAdapter->sessionId, key_index));
11995
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011996 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997 hdd_device_mode_to_string(pAdapter->device_mode),
11998 pAdapter->device_mode, key_index);
11999
12000 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012001 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012002 return -EINVAL;
12003 }
12004
12005 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12006 status = wlan_hdd_validate_context(pHddCtx);
12007
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012008 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012009 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012010
Krunal Sonib4326f22016-03-10 13:05:51 -080012011 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12012 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012013 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12014 pHddStaCtx->conn_info.ucEncryptionType) &&
12015 (eCSR_ENCRYPT_TYPE_AES !=
12016 pHddStaCtx->conn_info.ucEncryptionType)) {
12017 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012018 * then update the default key index
12019 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012020
12021 tCsrRoamSetKey setKey;
12022 uint32_t roamId = 0xFF;
12023 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12024
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012025 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012026
12027 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012028 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012029 setKey.keyId = key_index;
12030 setKey.keyLength = Keys->KeyLength[key_index];
12031
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012032 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012033 &Keys->KeyMaterial[key_index][0],
12034 Keys->KeyLength[key_index]);
12035
12036 setKey.keyDirection = eSIR_TX_RX;
12037
Anurag Chouhanc5548422016-02-24 18:33:27 +053012038 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039 &pHddStaCtx->conn_info.bssId);
12040
12041 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12042 pWextState->roamProfile.EncryptionType.
12043 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012044 /* In the case of dynamic wep
12045 * supplicant hardcodes DWEP type to
12046 * eCSR_ENCRYPT_TYPE_WEP104 even
12047 * though ap is configured for WEP-40
12048 * encryption. In this canse the key
12049 * length is 5 but the encryption type
12050 * is 104 hence checking the key
12051 * lenght(5) and encryption type(104)
12052 * and switching encryption type to 40
12053 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012054 pWextState->roamProfile.EncryptionType.
12055 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12056 pWextState->roamProfile.mcEncryptionType.
12057 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12058 }
12059
12060 setKey.encType =
12061 pWextState->roamProfile.EncryptionType.
12062 encryptionType[0];
12063
12064 /* Issue set key request */
12065 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12066 pAdapter->sessionId, &setKey,
12067 &roamId);
12068
12069 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012070 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012071 status);
12072 return -EINVAL;
12073 }
12074 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012075 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012076 /* In SoftAp mode setting key direction for default mode */
12077 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12078 pWextState->roamProfile.EncryptionType.encryptionType[0])
12079 && (eCSR_ENCRYPT_TYPE_AES !=
12080 pWextState->roamProfile.EncryptionType.
12081 encryptionType[0])) {
12082 /* Saving key direction for default key index to TX default */
12083 hdd_ap_ctx_t *pAPCtx =
12084 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12085 pAPCtx->wepKey[key_index].keyDirection =
12086 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012087 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012088 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012089 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012090 }
12091 }
12092
12093 EXIT();
12094 return status;
12095}
12096
12097static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12098 struct net_device *ndev,
12099 u8 key_index,
12100 bool unicast, bool multicast)
12101{
12102 int ret;
12103 cds_ssr_protect(__func__);
12104 ret =
12105 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12106 multicast);
12107 cds_ssr_unprotect(__func__);
12108
12109 return ret;
12110}
12111
Abhishek Singhc9941602016-08-09 16:06:22 +053012112/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012113 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12114 * interface that BSS might have been lost.
12115 * @pAdapter: adaptor
12116 * @bssid: bssid which might have been lost
12117 *
12118 * Return: bss which is unlinked from kernel cache
12119 */
12120struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12121 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122{
12123 struct net_device *dev = pAdapter->dev;
12124 struct wireless_dev *wdev = dev->ieee80211_ptr;
12125 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 struct cfg80211_bss *bss = NULL;
12127
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012128 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012129 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012130 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012131 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012133 hdd_info("cfg80211_unlink_bss called for BSSID "
12134 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012135 cfg80211_unlink_bss(wiphy, bss);
12136 }
12137 return bss;
12138}
12139
Abhishek Singhc9941602016-08-09 16:06:22 +053012140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012141/**
12142 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12143 * @pAdapter: Pointer to adapter
12144 * @bss_desc: Pointer to bss descriptor
12145 *
12146 * This function is used to inform the BSS details to nl80211 interface.
12147 *
12148 * Return: struct cfg80211_bss pointer
12149 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012150struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12151 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152{
12153 /*
12154 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12155 * already exists in bss data base of cfg80211 for that particular BSS
12156 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12157 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12158 * As of now there is no possibility to get the mgmt(probe response)
12159 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12160 * and passing to cfg80211_inform_bss_frame.
12161 */
12162 struct net_device *dev = pAdapter->dev;
12163 struct wireless_dev *wdev = dev->ieee80211_ptr;
12164 struct wiphy *wiphy = wdev->wiphy;
12165 int chan_no = bss_desc->channelId;
12166#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12167 qcom_ie_age *qie_age = NULL;
12168 int ie_length =
12169 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12170#else
12171 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12172#endif
12173 const char *ie =
12174 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12175 unsigned int freq;
12176 struct ieee80211_channel *chan;
12177 struct ieee80211_mgmt *mgmt = NULL;
12178 struct cfg80211_bss *bss_status = NULL;
12179 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12180 int rssi = 0;
12181 hdd_context_t *pHddCtx;
12182 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012183 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012184 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185
12186 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12187 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012188 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012189 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012190
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012191 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012192 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012193 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012194 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012195 return NULL;
12196 }
12197
12198 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12199
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012200 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012201 * Instead it wants a monotonic increasing value
12202 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012203 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012204 mgmt->u.probe_resp.timestamp =
12205 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012206
12207 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12208 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12209
12210#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12211 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12212 /* Assuming this is the last IE, copy at the end */
12213 ie_length -= sizeof(qcom_ie_age);
12214 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12215 qie_age->element_id = QCOM_VENDOR_IE_ID;
12216 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12217 qie_age->oui_1 = QCOM_OUI1;
12218 qie_age->oui_2 = QCOM_OUI2;
12219 qie_age->oui_3 = QCOM_OUI3;
12220 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012221 /*
12222 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12223 * all bss related timestamp is in units of ms. Due to this when scan
12224 * results are sent to lowi the scan age is high.To address this,
12225 * send age in units of 1/10 ms.
12226 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012227 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012228 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012230 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12231 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012232 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12233 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012234#endif
12235
12236 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12237 if (bss_desc->fProbeRsp) {
12238 mgmt->frame_control |=
12239 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12240 } else {
12241 mgmt->frame_control |=
12242 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12243 }
12244
12245 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012246 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012247 freq =
12248 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012249 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012250 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012251 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012252 freq =
12253 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012254 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012255 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012256 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012257 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012258 return NULL;
12259 }
12260
12261 chan = __ieee80211_get_channel(wiphy, freq);
12262 /* When the band is changed on the fly using the GUI, three things are done
12263 * 1. scan abort
12264 * 2. flush scan results from cache
12265 * 3. update the band with the new band user specified (refer to the
12266 * hdd_set_band_helper function) as part of the scan abort, message will be
12267 * queued to PE and we proceed with flushing and changinh the band.
12268 * PE will stop the scanning further and report back the results what ever
12269 * it had till now by calling the call back function.
12270 * if the time between update band and scandone call back is sufficient
12271 * enough the band change reflects in SME, SME validates the channels
12272 * and discards the channels correponding to previous band and calls back
12273 * with zero bss results. but if the time between band update and scan done
12274 * callback is very small then band change will not reflect in SME and SME
12275 * reports to HDD all the channels correponding to previous band.this is due
12276 * to race condition.but those channels are invalid to the new band and so
12277 * this function __ieee80211_get_channel will return NULL.Each time we
12278 * report scan result with this pointer null warning kernel trace is printed.
12279 * if the scan results contain large number of APs continuosly kernel
12280 * warning trace is printed and it will lead to apps watch dog bark.
12281 * So drop the bss and continue to next bss.
12282 */
12283 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012284 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12285 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012286 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287 return NULL;
12288 }
12289
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012290 /* Based on .ini configuration, raw rssi can be reported for bss.
12291 * Raw rssi is typically used for estimating power.
12292 */
12293
12294 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12295 bss_desc->rssi;
12296
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012298 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012300 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012302 (int)(rssi / 100),
12303 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012304
12305 bss_status =
12306 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
12307 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012308 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012309 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310 return bss_status;
12311}
12312
12313/**
12314 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12315 * @pAdapter: Pointer to adapter
12316 * @pRoamInfo: Pointer to roam info
12317 *
12318 * This function is used to update the BSS data base of CFG8011
12319 *
12320 * Return: struct cfg80211_bss pointer
12321 */
12322struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12323 tCsrRoamInfo *pRoamInfo)
12324{
12325 tCsrRoamConnectedProfile roamProfile;
12326 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12327 struct cfg80211_bss *bss = NULL;
12328
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12330 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12331
12332 if (NULL != roamProfile.pBssDesc) {
12333 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12334 roamProfile.pBssDesc);
12335
12336 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012337 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012338
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012339 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012341 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012342 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 return bss;
12344}
12345/**
12346 * wlan_hdd_cfg80211_update_bss() - update bss
12347 * @wiphy: Pointer to wiphy
12348 * @pAdapter: Pointer to adapter
12349 * @scan_time: scan request timestamp
12350 *
12351 * Return: zero if success, non-zero otherwise
12352 */
12353int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12354 hdd_adapter_t *pAdapter,
12355 uint32_t scan_time)
12356{
12357 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12358 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012359 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012360 tScanResultHandle pResult;
12361 struct cfg80211_bss *bss_status = NULL;
12362 hdd_context_t *pHddCtx;
12363 int ret;
12364
12365 ENTER();
12366
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012367 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12368 hdd_err("invalid session id: %d", pAdapter->sessionId);
12369 return -EINVAL;
12370 }
12371
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012372 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12374 NO_SESSION, pAdapter->sessionId));
12375
12376 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12377 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012378 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012380
12381 /* start getting scan results and populate cgf80211 BSS database */
12382 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12383
12384 /* no scan results */
12385 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012386 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012387 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 }
12389
12390 pScanResult = sme_scan_result_get_first(hHal, pResult);
12391
12392 while (pScanResult) {
12393 /*
12394 * - cfg80211_inform_bss() is not updating ie field of bss
12395 * entry if entry already exists in bss data base of cfg80211
12396 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12397 * to update thebss entry instead of cfg80211_inform_bss,
12398 * But this call expects mgmt packet as input. As of now
12399 * there is no possibility to get the mgmt(probe response)
12400 * frame from PE, converting bss_desc to
12401 * ieee80211_mgmt(probe response) and passing to c
12402 * fg80211_inform_bss_frame.
12403 * - Update BSS only if beacon timestamp is later than
12404 * scan request timestamp.
12405 */
12406 if ((scan_time == 0) ||
12407 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012408 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012409 bss_status =
12410 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12411 &pScanResult->BssDescriptor);
12412
12413 if (NULL == bss_status) {
12414 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12415 } else {
12416 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 bss_status);
12419 }
12420 } else {
12421 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12422 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12423 }
12424 pScanResult = sme_scan_result_get_next(hHal, pResult);
12425 }
12426
12427 sme_scan_result_purge(hHal, pResult);
12428 /*
12429 * For SAP mode, scan is invoked by hostapd during SAP start
12430 * if hostapd is restarted, we need to flush previous scan
12431 * result so that it will reflect environment change
12432 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012433 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012434#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12435 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12436#endif
12437 )
12438 sme_scan_flush_result(hHal);
12439
12440 EXIT();
12441 return 0;
12442}
12443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444/**
12445 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12446 * @pAdapter: Pointer to adapter
12447 * @pRoamInfo: Pointer to roam info
12448 * @index: Index
12449 * @preauth: Preauth flag
12450 *
12451 * This function is used to notify the supplicant of a new PMKSA candidate.
12452 *
12453 * Return: 0 for success, non-zero for failure
12454 */
12455int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12456 tCsrRoamInfo *pRoamInfo,
12457 int index, bool preauth)
12458{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012459 struct net_device *dev = pAdapter->dev;
12460 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12461
12462 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012463 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464
12465 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012466 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012467 return -EINVAL;
12468 }
12469
12470 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012471 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012472 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12473 cfg80211_pmksa_candidate_notify(dev, index,
12474 pRoamInfo->bssid.bytes,
12475 preauth, GFP_KERNEL);
12476 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 return 0;
12478}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012479
12480#ifdef FEATURE_WLAN_LFR_METRICS
12481/**
12482 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12483 * @pAdapter: Pointer to adapter
12484 * @pRoamInfo: Pointer to roam info
12485 *
12486 * 802.11r/LFR metrics reporting function to report preauth initiation
12487 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012488 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012489 */
12490#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012491QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492 tCsrRoamInfo *pRoamInfo)
12493{
12494 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12495 union iwreq_data wrqu;
12496
12497 ENTER();
12498
12499 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012500 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012501 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012502 }
12503
12504 /* create the event */
12505 memset(&wrqu, 0, sizeof(wrqu));
12506 memset(metrics_notification, 0, sizeof(metrics_notification));
12507
12508 wrqu.data.pointer = metrics_notification;
12509 wrqu.data.length = scnprintf(metrics_notification,
12510 sizeof(metrics_notification),
12511 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12512 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12513
12514 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12515 metrics_notification);
12516
12517 EXIT();
12518
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012519 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012520}
12521
12522/**
12523 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12524 * @pAdapter: Pointer to adapter
12525 * @pRoamInfo: Pointer to roam info
12526 * @preauth_status: Preauth status
12527 *
12528 * 802.11r/LFR metrics reporting function to report handover initiation
12529 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012530 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012531 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012532QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12534 tCsrRoamInfo *pRoamInfo,
12535 bool preauth_status)
12536{
12537 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12538 union iwreq_data wrqu;
12539
12540 ENTER();
12541
12542 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012543 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012544 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 }
12546
12547 /* create the event */
12548 memset(&wrqu, 0, sizeof(wrqu));
12549 memset(metrics_notification, 0, sizeof(metrics_notification));
12550
12551 scnprintf(metrics_notification, sizeof(metrics_notification),
12552 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12553 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12554
12555 if (1 == preauth_status)
12556 strlcat(metrics_notification, " true",
12557 sizeof(metrics_notification));
12558 else
12559 strlcat(metrics_notification, " false",
12560 sizeof(metrics_notification));
12561
12562 wrqu.data.pointer = metrics_notification;
12563 wrqu.data.length = strlen(metrics_notification);
12564
12565 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12566 metrics_notification);
12567
12568 EXIT();
12569
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012570 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012571}
12572
12573/**
12574 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12575 * @pAdapter: Pointer to adapter
12576 * @pRoamInfo: Pointer to roam info
12577 *
12578 * 802.11r/LFR metrics reporting function to report handover initiation
12579 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012580 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012581 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012582QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583 tCsrRoamInfo *pRoamInfo)
12584{
12585 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12586 union iwreq_data wrqu;
12587
12588 ENTER();
12589
12590 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012591 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012592 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012593 }
12594
12595 /* create the event */
12596 memset(&wrqu, 0, sizeof(wrqu));
12597 memset(metrics_notification, 0, sizeof(metrics_notification));
12598
12599 wrqu.data.pointer = metrics_notification;
12600 wrqu.data.length = scnprintf(metrics_notification,
12601 sizeof(metrics_notification),
12602 "QCOM: LFR_PREAUTH_HANDOVER "
12603 MAC_ADDRESS_STR,
12604 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12605
12606 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12607 metrics_notification);
12608
12609 EXIT();
12610
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012611 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612}
12613#endif
12614
12615/**
12616 * hdd_select_cbmode() - select channel bonding mode
12617 * @pAdapter: Pointer to adapter
12618 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012619 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620 *
12621 * Return: none
12622 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012623void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12624 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012625{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012626 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012627 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012628 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012629
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012630 /*
12631 * CDS api expects secondary channel for calculating
12632 * the channel params
12633 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012634 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012635 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12636 if (operationChannel >= 1 && operationChannel <= 5)
12637 sec_ch = operationChannel + 4;
12638 else if (operationChannel >= 6 && operationChannel <= 13)
12639 sec_ch = operationChannel - 4;
12640 }
12641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012642 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012643 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012644
12645 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012646 eHddDot11Mode hdd_dot11_mode;
12647 uint8_t iniDot11Mode =
12648 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12649
12650 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12651 switch (iniDot11Mode) {
12652 case eHDD_DOT11_MODE_AUTO:
12653 case eHDD_DOT11_MODE_11ac:
12654 case eHDD_DOT11_MODE_11ac_ONLY:
12655 if (sme_is_feature_supported_by_fw(DOT11AC))
12656 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12657 else
12658 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12659 break;
12660 case eHDD_DOT11_MODE_11n:
12661 case eHDD_DOT11_MODE_11n_ONLY:
12662 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12663 break;
12664 default:
12665 hdd_dot11_mode = iniDot11Mode;
12666 break;
12667 }
12668 ch_info->channel_width = ch_params->ch_width;
12669 ch_info->phy_mode =
12670 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012671 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012672 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012673 hdd_info("ch_info width %d, phymode %d channel %d",
12674 ch_info->channel_width, ch_info->phy_mode,
12675 ch_info->channel);
12676 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012677}
12678
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012679/**
12680 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12681 * @adapter: STA adapter
12682 * @roam_profile: STA roam profile
12683 *
12684 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12685 *
12686 * Return: false if sta-sap conc is not allowed, else return true
12687 */
12688static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12689 tCsrRoamProfile *roam_profile)
12690{
12691 hdd_context_t *hdd_ctx;
12692 hdd_adapter_t *ap_adapter;
12693 hdd_ap_ctx_t *hdd_ap_ctx;
12694 hdd_hostapd_state_t *hostapd_state;
12695 uint8_t channel = 0;
12696 QDF_STATUS status;
12697
12698 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12699 if (!hdd_ctx) {
12700 hdd_err("HDD context is NULL");
12701 return true;
12702 }
12703
12704 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12705 /* probably no sap running, no handling required */
12706 if (ap_adapter == NULL)
12707 return true;
12708
12709 /*
12710 * sap is not in started state, so it is fine to go ahead with sta.
12711 * if sap is currently doing CAC then don't allow sta to go further.
12712 */
12713 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12714 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12715 return true;
12716
12717 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12718 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12719 return false;
12720 }
12721
12722 /*
12723 * log and return error, if we allow STA to go through, we don't
12724 * know what is going to happen better stop sta connection
12725 */
12726 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12727 if (NULL == hdd_ap_ctx) {
12728 hdd_err("AP context not found");
12729 return false;
12730 }
12731
12732 /* sap is on non-dfs channel, nothing to handle */
12733 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12734 hdd_info("sap is on non-dfs channel, sta is allowed");
12735 return true;
12736 }
12737 /*
12738 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012739 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012740 */
12741 status = cds_get_channel_from_scan_result(adapter,
12742 roam_profile, &channel);
12743
Nitesh Shah59774522016-09-16 15:14:21 +053012744 /*
12745 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12746 * channels for roaming case.
12747 */
12748 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12749 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12750 return true;
12751 }
12752
12753 /*
12754 * If channel is 0 or DFS then better to call pcl and find out the
12755 * best channel. If channel is non-dfs 5 GHz then better move SAP
12756 * to STA's channel to make scc, so we have room for 3port MCC
12757 * scenario.
12758 */
12759 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012760 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12761 true);
12762
12763 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12764 qdf_event_reset(&hostapd_state->qdf_event);
12765 status = wlansap_set_channel_change_with_csa(
12766 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12767 hdd_ap_ctx->sapConfig.ch_width_orig);
12768
12769 if (QDF_STATUS_SUCCESS != status) {
12770 hdd_err("Set channel with CSA IE failed, can't allow STA");
12771 return false;
12772 }
12773
12774 /*
12775 * wait here for SAP to finish the channel switch. When channel
12776 * switch happens, SAP sends few beacons with CSA_IE. After
12777 * successfully Transmission of those beacons, it will move its
12778 * state from started to disconnected and move to new channel.
12779 * once it moves to new channel, sap again moves its state
12780 * machine from disconnected to started and set this event.
12781 * wait for 10 secs to finish this.
12782 */
12783 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12784 if (!QDF_IS_STATUS_SUCCESS(status)) {
12785 hdd_err("wait for qdf_event failed, STA not allowed!!");
12786 return false;
12787 }
12788
12789 return true;
12790}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012791
Krunal Soni31949422016-07-29 17:17:53 -070012792/**
12793 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012794 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012795 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012796 * @ssid_len: Length of ssid
12797 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012798 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012799 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012800 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012801 *
12802 * This function is used to start the association process
12803 *
12804 * Return: 0 for success, non-zero for failure
12805 */
Krunal Soni31949422016-07-29 17:17:53 -070012806static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012807 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012808 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012809 u8 operatingChannel,
12810 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012811{
12812 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012813 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012814 hdd_wext_state_t *pWextState;
12815 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012816 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012817 uint32_t roamId;
12818 tCsrRoamProfile *pRoamProfile;
12819 eCsrAuthType RSNAuthType;
12820 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012821 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822
12823 ENTER();
12824
12825 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12826 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012827 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012828
12829 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012830 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012831 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012832
12833 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012834 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012835 status = -EINVAL;
12836 goto ret_status;
12837 }
12838
12839 if (true == cds_is_connection_in_progress()) {
12840 hdd_err("Connection refused: conn in progress");
12841 status = -EINVAL;
12842 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012843 }
12844
12845 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012846 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12847 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012848
12849 if (pRoamProfile) {
12850 hdd_station_ctx_t *pHddStaCtx;
12851 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12852
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012853 /* Restart the opportunistic timer
12854 *
12855 * If hw_mode_change_in_progress is true, then wait
12856 * till firmware sends the callback for hw_mode change.
12857 *
12858 * Else set connect_in_progress as true and proceed.
12859 */
12860 cds_restart_opportunistic_timer(false);
12861 if (cds_is_hw_mode_change_in_progress()) {
12862 status = qdf_wait_for_connection_update();
12863 if (!QDF_IS_STATUS_SUCCESS(status)) {
12864 hdd_err("qdf wait for event failed!!");
12865 status = -EINVAL;
12866 goto ret_status;
12867 }
12868 }
12869 cds_set_connection_in_progress(true);
12870
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012871 if (HDD_WMM_USER_MODE_NO_QOS ==
12872 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12873 /*QoS not enabled in cfg file */
12874 pRoamProfile->uapsd_mask = 0;
12875 } else {
12876 /*QoS enabled, update uapsd mask from cfg file */
12877 pRoamProfile->uapsd_mask =
12878 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12879 }
12880
12881 pRoamProfile->SSIDs.numOfSSIDs = 1;
12882 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012883 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012884 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012885 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012886 ssid, ssid_len);
12887
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012888 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012889 /* cleanup bssid hint */
12890 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12891 QDF_MAC_ADDR_SIZE);
12892 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12893 QDF_MAC_ADDR_SIZE);
12894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012895 if (bssid) {
12896 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012897 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012898 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012899 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012900 /*
12901 * Save BSSID in seperate variable as
12902 * pRoamProfile's BSSID is getting zeroed out in the
12903 * association process. In case of join failure
12904 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012905 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012906 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012907 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012908 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012909 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012910 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12911 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012912 /*
12913 * Save BSSID in a separate variable as
12914 * pRoamProfile's BSSID is getting zeroed out in the
12915 * association process. In case of join failure
12916 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012918 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012919 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012920 hdd_info("bssid_hint is given by upper layer %pM",
12921 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012922 }
12923
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012924 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012925 pRoamProfile->SSIDs.SSIDList->SSID.length,
12926 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12927 operatingChannel);
12928
12929 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12930 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012931 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012932 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12933 }
12934#ifdef FEATURE_WLAN_WAPI
12935 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012936 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012937 switch (pAdapter->wapi_info.wapiAuthMode) {
12938 case WAPI_AUTH_MODE_PSK:
12939 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012940 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012941 pAdapter->wapi_info.wapiAuthMode);
12942 pRoamProfile->AuthType.authType[0] =
12943 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12944 break;
12945 }
12946 case WAPI_AUTH_MODE_CERT:
12947 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012948 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 pAdapter->wapi_info.wapiAuthMode);
12950 pRoamProfile->AuthType.authType[0] =
12951 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12952 break;
12953 }
12954 } /* End of switch */
12955 if (pAdapter->wapi_info.wapiAuthMode ==
12956 WAPI_AUTH_MODE_PSK
12957 || pAdapter->wapi_info.wapiAuthMode ==
12958 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012959 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012960 pRoamProfile->AuthType.numEntries = 1;
12961 pRoamProfile->EncryptionType.numEntries = 1;
12962 pRoamProfile->EncryptionType.encryptionType[0] =
12963 eCSR_ENCRYPT_TYPE_WPI;
12964 pRoamProfile->mcEncryptionType.numEntries = 1;
12965 pRoamProfile->mcEncryptionType.
12966 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12967 }
12968 }
Krunal Soni31949422016-07-29 17:17:53 -070012969#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970#ifdef WLAN_FEATURE_GTK_OFFLOAD
12971 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080012972 if ((QDF_STA_MODE == pAdapter->device_mode) ||
12973 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
12975 sizeof(tSirGtkOffloadParams));
12976 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12977 GTK_OFFLOAD_DISABLE;
12978 }
12979#endif
12980 pRoamProfile->csrPersona = pAdapter->device_mode;
12981
12982 if (operatingChannel) {
12983 pRoamProfile->ChannelInfo.ChannelList =
12984 &operatingChannel;
12985 pRoamProfile->ChannelInfo.numOfChannels = 1;
12986 } else {
12987 pRoamProfile->ChannelInfo.ChannelList = NULL;
12988 pRoamProfile->ChannelInfo.numOfChannels = 0;
12989 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012990 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 && operatingChannel) {
12992 /*
12993 * Need to post the IBSS power save parameters
12994 * to WMA. WMA will configure this parameters
12995 * to firmware if power save is enabled by the
12996 * firmware.
12997 */
12998 status = hdd_set_ibss_power_save_params(pAdapter);
12999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013000 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013001 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013002 status = -EINVAL;
13003 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013005 pRoamProfile->ch_params.ch_width =
13006 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013007 /*
13008 * In IBSS mode while operating in 2.4 GHz,
13009 * the device supports only 20 MHz.
13010 */
13011 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13012 pRoamProfile->ch_params.ch_width =
13013 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013014 hdd_select_cbmode(pAdapter, operatingChannel,
13015 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013016 }
Abhishek Singh99bce862016-06-20 15:10:51 +053013017 /*
13018 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13019 * or pmf=2 is an explicit configuration in the supplicant
13020 * configuration, drop the connection request.
13021 */
13022 if (pWextState->roamProfile.MFPEnabled &&
13023 !(pWextState->roamProfile.MFPRequired ||
13024 pWextState->roamProfile.MFPCapable)) {
13025 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13026 pWextState->roamProfile.MFPEnabled,
13027 pWextState->roamProfile.MFPRequired,
13028 pWextState->roamProfile.MFPCapable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013030 status = -EINVAL;
13031 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013032 }
13033
Krunal Soni31949422016-07-29 17:17:53 -070013034 /*
13035 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013036 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013037 * enhancements, the supplicant is not issuing the scan command
13038 * now. So the unicast frames which are sent from the host are
13039 * not having the additional IEs. If it is P2P CLIENT and there
13040 * is no additional IE present in roamProfile, then use the
13041 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013042 */
13043
Krunal Sonib4326f22016-03-10 13:05:51 -080013044 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013045 (!pRoamProfile->pAddIEScan)) {
13046 pRoamProfile->pAddIEScan =
13047 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13048 pRoamProfile->nAddIEScanLength =
13049 pAdapter->scan_info.scanAddIE.length;
13050 }
13051 /*
13052 * When policy manager is enabled from ini file, we shouldn't
13053 * check for other concurrency rules.
13054 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013055 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013056 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013057 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013058 pAdapter, pRoamProfile, &roamId)) {
13059 status = 0;
13060 goto conn_failure;
13061 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013062 }
13063
Krunal Soni3091bcc2016-06-23 12:28:21 -070013064 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013065 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13066 pRoamProfile))) {
13067 hdd_err("sap-sta conc will fail, can't allow sta");
13068 hdd_conn_set_connection_state(pAdapter,
13069 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013070 status = -ENOMEM;
13071 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013072 }
13073
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013074 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 if (!sme_config) {
13076 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013077 hdd_conn_set_connection_state(pAdapter,
13078 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013079 status = -ENOMEM;
13080 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013081 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082 sme_get_config_param(pHddCtx->hHal, sme_config);
13083 /* These values are not sessionized. So, any change in these SME
13084 * configs on an older or parallel interface will affect the
13085 * cb mode. So, restoring the default INI params before starting
13086 * interfaces such as sta, cli etc.,
13087 */
13088 sme_config->csrConfig.channelBondingMode5GHz =
13089 pHddCtx->config->nChannelBondingMode5GHz;
13090 sme_config->csrConfig.channelBondingMode24GHz =
13091 pHddCtx->config->nChannelBondingMode24GHz;
13092 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013093 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013094 /*
13095 * Change conn_state to connecting before sme_roam_connect(),
13096 * because sme_roam_connect() has a direct path to call
13097 * hdd_sme_roam_callback(), which will change the conn_state
13098 * If direct path, conn_state will be accordingly changed to
13099 * NotConnected or Associated by either
13100 * hdd_association_completion_handler() or
13101 * hdd_dis_connect_handler() in sme_RoamCallback()if
13102 * sme_RomConnect is to be queued,
13103 * Connecting state will remain until it is completed.
13104 *
13105 * If connection state is not changed, connection state will
13106 * remain in eConnectionState_NotConnected state.
13107 * In hdd_association_completion_handler, "hddDisconInProgress"
13108 * is set to true if conn state is
13109 * eConnectionState_NotConnected.
13110 * If "hddDisconInProgress" is set to true then cfg80211 layer
13111 * is not informed of connect result indication which
13112 * is an issue.
13113 */
13114 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013115 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013116 hdd_conn_set_connection_state(pAdapter,
13117 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118
Komal Seelama89be8d2016-09-29 11:09:26 +053013119 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13120 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013121 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 pAdapter->sessionId, pRoamProfile,
13123 &roamId);
13124
Rajeev Kumard31e1542017-01-13 14:37:42 -080013125 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013126 (QDF_STA_MODE == pAdapter->device_mode ||
13127 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013128 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013129 "qdf_status %d. -> NotConnected",
13130 pAdapter->sessionId, qdf_status);
13131 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013132 /* change back to NotAssociated */
13133 hdd_conn_set_connection_state(pAdapter,
13134 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013135 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13136 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013137 }
13138
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013139 /* Reset connect_in_progress */
13140 cds_set_connection_in_progress(false);
13141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013142 pRoamProfile->ChannelInfo.ChannelList = NULL;
13143 pRoamProfile->ChannelInfo.numOfChannels = 0;
13144
Nitesh Shah044fd672016-10-13 18:53:25 +053013145 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080013146 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013147 cds_get_channel_from_scan_result(pAdapter,
13148 pRoamProfile, &channel);
13149 if (channel)
13150 cds_checkn_update_hw_mode_single_mac_mode
13151 (channel);
13152 }
13153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013154 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013155 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013156 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013158 goto ret_status;
13159
13160conn_failure:
13161 /* Reset connect_in_progress */
13162 cds_set_connection_in_progress(false);
13163
13164ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013165 EXIT();
13166 return status;
13167}
13168
13169/**
13170 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13171 * @pAdapter: Pointer to adapter
13172 * @auth_type: Auth type
13173 *
13174 * This function is used to set the authentication type (OPEN/SHARED).
13175 *
13176 * Return: 0 for success, non-zero for failure
13177 */
13178static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13179 enum nl80211_auth_type auth_type)
13180{
13181 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13182 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013184 /*set authentication type */
13185 switch (auth_type) {
13186 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013187 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13189 break;
13190
13191 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013193 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13195 break;
13196
13197 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013198 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13200 break;
13201#ifdef FEATURE_WLAN_ESE
13202 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013203 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13205 break;
13206#endif
13207
13208 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013209 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013210 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13211 return -EINVAL;
13212 }
13213
13214 pWextState->roamProfile.AuthType.authType[0] =
13215 pHddStaCtx->conn_info.authType;
13216 return 0;
13217}
13218
13219/**
13220 * wlan_hdd_set_akm_suite() - set key management type
13221 * @pAdapter: Pointer to adapter
13222 * @key_mgmt: Key management type
13223 *
13224 * This function is used to set the key mgmt type(PSK/8021x).
13225 *
13226 * Return: 0 for success, non-zero for failure
13227 */
13228static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13229{
13230 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013232#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13233#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13234 /*set key mgmt type */
13235 switch (key_mgmt) {
13236 case WLAN_AKM_SUITE_PSK:
13237 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013239 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013240 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13241 break;
13242
13243 case WLAN_AKM_SUITE_8021X_SHA256:
13244 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013246 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13248 break;
13249#ifdef FEATURE_WLAN_ESE
13250#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13251#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13252 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013253 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013254 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13255 break;
13256#endif
13257#ifndef WLAN_AKM_SUITE_OSEN
13258#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13259#endif
13260 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013261 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013262 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13263 break;
13264
13265 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013266 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013267 return -EINVAL;
13268
13269 }
13270 return 0;
13271}
13272
13273/**
13274 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13275 * @pAdapter: Pointer to adapter
13276 * @cipher: Cipher type
13277 * @ucast: Unicast flag
13278 *
13279 * This function is used to set the encryption type
13280 * (NONE/WEP40/WEP104/TKIP/CCMP).
13281 *
13282 * Return: 0 for success, non-zero for failure
13283 */
13284static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13285 u32 cipher, bool ucast)
13286{
13287 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13288 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13289 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13290
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013292 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013293 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13294 } else {
13295
13296 /*set encryption method */
13297 switch (cipher) {
13298 case IW_AUTH_CIPHER_NONE:
13299 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13300 break;
13301
13302 case WLAN_CIPHER_SUITE_WEP40:
13303 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13304 break;
13305
13306 case WLAN_CIPHER_SUITE_WEP104:
13307 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13308 break;
13309
13310 case WLAN_CIPHER_SUITE_TKIP:
13311 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13312 break;
13313
13314 case WLAN_CIPHER_SUITE_CCMP:
13315 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13316 break;
13317#ifdef FEATURE_WLAN_WAPI
13318 case WLAN_CIPHER_SUITE_SMS4:
13319 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13320 break;
13321#endif
13322
13323#ifdef FEATURE_WLAN_ESE
13324 case WLAN_CIPHER_SUITE_KRK:
13325 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13326 break;
13327#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13328 case WLAN_CIPHER_SUITE_BTK:
13329 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13330 break;
13331#endif
13332#endif
13333 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013334 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335 return -EOPNOTSUPP;
13336 }
13337 }
13338
13339 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013340 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013341 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13342 pWextState->roamProfile.EncryptionType.numEntries = 1;
13343 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13344 encryptionType;
13345 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013346 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13348 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13349 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13350 encryptionType;
13351 }
13352
13353 return 0;
13354}
13355
13356/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013357 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13358 * @wext_state: Pointer to wext state
13359 * @gen_ie: Pointer to IE data
13360 * @len: length of IE data
13361 *
13362 * Return: 0 for success, non-zero for failure
13363 */
13364static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13365 const uint8_t *gen_ie, uint16_t len)
13366{
13367 uint16_t cur_add_ie_len =
13368 wext_state->assocAddIE.length;
13369
13370 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13371 (wext_state->assocAddIE.length + len)) {
13372 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13373 QDF_ASSERT(0);
13374 return -ENOMEM;
13375 }
13376 memcpy(wext_state->assocAddIE.addIEdata +
13377 cur_add_ie_len, gen_ie, len);
13378 wext_state->assocAddIE.length += len;
13379
13380 wext_state->roamProfile.pAddIEAssoc =
13381 wext_state->assocAddIE.addIEdata;
13382 wext_state->roamProfile.nAddIEAssocLength =
13383 wext_state->assocAddIE.length;
13384 return 0;
13385}
13386
13387/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013388 * wlan_hdd_cfg80211_set_ie() - set IEs
13389 * @pAdapter: Pointer to adapter
13390 * @ie: Pointer ot ie
13391 * @ie: IE length
13392 *
13393 * Return: 0 for success, non-zero for failure
13394 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013395static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013396 size_t ie_len)
13397{
13398 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13399 const uint8_t *genie = ie;
13400 uint16_t remLen = ie_len;
13401#ifdef FEATURE_WLAN_WAPI
13402 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13403 u16 *tmp;
13404 uint16_t akmsuiteCount;
13405 int *akmlist;
13406#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013407 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013408
13409 /* clear previous assocAddIE */
13410 pWextState->assocAddIE.length = 0;
13411 pWextState->roamProfile.bWPSAssociation = false;
13412 pWextState->roamProfile.bOSENAssociation = false;
13413
13414 while (remLen >= 2) {
13415 uint16_t eLen = 0;
13416 uint8_t elementId;
13417 elementId = *genie++;
13418 eLen = *genie++;
13419 remLen -= 2;
13420
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013421 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013422
13423 switch (elementId) {
13424 case DOT11F_EID_WPA:
13425 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 -070013426 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427 return -EINVAL;
13428 } else if (0 ==
13429 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13430 uint16_t curAddIELen =
13431 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013432 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013433
13434 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13435 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013436 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013437 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013438 return -ENOMEM;
13439 }
13440 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13441 memcpy(pWextState->assocAddIE.addIEdata +
13442 curAddIELen, genie - 2, eLen + 2);
13443 pWextState->assocAddIE.length += eLen + 2;
13444
13445 pWextState->roamProfile.bWPSAssociation = true;
13446 pWextState->roamProfile.pAddIEAssoc =
13447 pWextState->assocAddIE.addIEdata;
13448 pWextState->roamProfile.nAddIEAssocLength =
13449 pWextState->assocAddIE.length;
13450 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013451 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013452 memset(pWextState->WPARSNIE, 0,
13453 MAX_WPA_RSN_IE_LEN);
13454 memcpy(pWextState->WPARSNIE, genie - 2,
13455 (eLen + 2));
13456 pWextState->roamProfile.pWPAReqIE =
13457 pWextState->WPARSNIE;
13458 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13459 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13460 P2P_OUI_TYPE_SIZE))) {
13461 uint16_t curAddIELen =
13462 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013463 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464
13465 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13466 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013467 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013468 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013469 return -ENOMEM;
13470 }
13471 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13472 memcpy(pWextState->assocAddIE.addIEdata +
13473 curAddIELen, genie - 2, eLen + 2);
13474 pWextState->assocAddIE.length += eLen + 2;
13475
13476 pWextState->roamProfile.pAddIEAssoc =
13477 pWextState->assocAddIE.addIEdata;
13478 pWextState->roamProfile.nAddIEAssocLength =
13479 pWextState->assocAddIE.length;
13480 }
13481#ifdef WLAN_FEATURE_WFD
13482 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13483 WFD_OUI_TYPE_SIZE)) &&
13484 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013485 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013486 pAdapter->device_mode)) {
13487 uint16_t curAddIELen =
13488 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013489 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013490
13491 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13492 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013493 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013494 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013495 return -ENOMEM;
13496 }
13497 /* WFD IE is saved to Additional IE ; it should
13498 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013499 * WFD IE
13500 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013501 memcpy(pWextState->assocAddIE.addIEdata +
13502 curAddIELen, genie - 2, eLen + 2);
13503 pWextState->assocAddIE.length += eLen + 2;
13504
13505 pWextState->roamProfile.pAddIEAssoc =
13506 pWextState->assocAddIE.addIEdata;
13507 pWextState->roamProfile.nAddIEAssocLength =
13508 pWextState->assocAddIE.length;
13509 }
13510#endif
13511 /* Appending HS 2.0 Indication Element in Assiciation Request */
13512 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13513 HS20_OUI_TYPE_SIZE))) {
13514 uint16_t curAddIELen =
13515 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013516 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013517
13518 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13519 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013520 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013521 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013522 return -ENOMEM;
13523 }
13524 memcpy(pWextState->assocAddIE.addIEdata +
13525 curAddIELen, genie - 2, eLen + 2);
13526 pWextState->assocAddIE.length += eLen + 2;
13527
13528 pWextState->roamProfile.pAddIEAssoc =
13529 pWextState->assocAddIE.addIEdata;
13530 pWextState->roamProfile.nAddIEAssocLength =
13531 pWextState->assocAddIE.length;
13532 }
13533 /* Appending OSEN Information Element in Assiciation Request */
13534 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13535 OSEN_OUI_TYPE_SIZE))) {
13536 uint16_t curAddIELen =
13537 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013538 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539
13540 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13541 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013542 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013543 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013544 return -ENOMEM;
13545 }
13546 memcpy(pWextState->assocAddIE.addIEdata +
13547 curAddIELen, genie - 2, eLen + 2);
13548 pWextState->assocAddIE.length += eLen + 2;
13549
13550 pWextState->roamProfile.bOSENAssociation = true;
13551 pWextState->roamProfile.pAddIEAssoc =
13552 pWextState->assocAddIE.addIEdata;
13553 pWextState->roamProfile.nAddIEAssocLength =
13554 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013555 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13556 MBO_OUI_TYPE_SIZE))){
13557 hdd_info("Set MBO IE(len %d)", eLen + 2);
13558 status = wlan_hdd_add_assoc_ie(pWextState,
13559 genie - 2, eLen + 2);
13560 if (status)
13561 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013562 } else {
13563 uint16_t add_ie_len =
13564 pWextState->assocAddIE.length;
13565
13566 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13567
13568 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13569 (pWextState->assocAddIE.length + eLen)) {
13570 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013571 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572 return -ENOMEM;
13573 }
13574
13575 memcpy(pWextState->assocAddIE.addIEdata +
13576 add_ie_len, genie - 2, eLen + 2);
13577 pWextState->assocAddIE.length += eLen + 2;
13578
13579 pWextState->roamProfile.pAddIEAssoc =
13580 pWextState->assocAddIE.addIEdata;
13581 pWextState->roamProfile.nAddIEAssocLength =
13582 pWextState->assocAddIE.length;
13583 }
13584 break;
13585 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013586 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13588 memcpy(pWextState->WPARSNIE, genie - 2,
13589 (eLen + 2));
13590 pWextState->roamProfile.pRSNReqIE =
13591 pWextState->WPARSNIE;
13592 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13593 break;
13594 /*
13595 * Appending Extended Capabilities with Interworking bit set
13596 * in Assoc Req.
13597 *
13598 * In assoc req this EXT Cap will only be taken into account if
13599 * interworkingService bit is set to 1. Currently
13600 * driver is only interested in interworkingService capability
13601 * from supplicant. If in future any other EXT Cap info is
13602 * required from supplicat, it needs to be handled while
13603 * sending Assoc Req in LIM.
13604 */
13605 case DOT11F_EID_EXTCAP:
13606 {
13607 uint16_t curAddIELen =
13608 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013609 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610
13611 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13612 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013613 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013614 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013615 return -ENOMEM;
13616 }
13617 memcpy(pWextState->assocAddIE.addIEdata +
13618 curAddIELen, genie - 2, eLen + 2);
13619 pWextState->assocAddIE.length += eLen + 2;
13620
13621 pWextState->roamProfile.pAddIEAssoc =
13622 pWextState->assocAddIE.addIEdata;
13623 pWextState->roamProfile.nAddIEAssocLength =
13624 pWextState->assocAddIE.length;
13625 break;
13626 }
13627#ifdef FEATURE_WLAN_WAPI
13628 case WLAN_EID_WAPI:
13629 /* Setting WAPI Mode to ON=1 */
13630 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013631 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632 tmp = (u16 *) ie;
13633 tmp = tmp + 2; /* Skip element Id and Len, Version */
13634 akmsuiteCount = WPA_GET_LE16(tmp);
13635 tmp = tmp + 1;
13636 akmlist = (int *)(tmp);
13637 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13638 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13639 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013640 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013641 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013642 return -EINVAL;
13643 }
13644
13645 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013646 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013647 pAdapter->wapi_info.wapiAuthMode =
13648 WAPI_AUTH_MODE_PSK;
13649 }
13650 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013651 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013652 pAdapter->wapi_info.wapiAuthMode =
13653 WAPI_AUTH_MODE_CERT;
13654 }
13655 break;
13656#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013657 case DOT11F_EID_SUPPOPERATINGCLASSES:
13658 {
13659 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13660 status = wlan_hdd_add_assoc_ie(pWextState,
13661 genie - 2, eLen + 2);
13662 if (status)
13663 return status;
13664 break;
13665 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013666 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013667 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013668 /* when Unknown IE is received we break
13669 * and continue to the next IE in the buffer
13670 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 break;
13672 }
13673 genie += eLen;
13674 remLen -= eLen;
13675 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013676 return 0;
13677}
13678
13679/**
13680 * hdd_is_wpaie_present() - check for WPA ie
13681 * @ie: Pointer to ie
13682 * @ie_len: Ie length
13683 *
13684 * Parse the received IE to find the WPA IE
13685 *
13686 * Return: true if wpa ie is found else false
13687 */
13688static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13689{
13690 uint8_t eLen = 0;
13691 uint16_t remLen = ie_len;
13692 uint8_t elementId = 0;
13693
13694 while (remLen >= 2) {
13695 elementId = *ie++;
13696 eLen = *ie++;
13697 remLen -= 2;
13698 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013699 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 return false;
13701 }
13702 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13703 /* OUI - 0x00 0X50 0XF2
13704 * WPA Information Element - 0x01
13705 * WPA version - 0x01
13706 */
13707 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13708 return true;
13709 }
13710 ie += eLen;
13711 remLen -= eLen;
13712 }
13713 return false;
13714}
13715
13716/**
13717 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13718 * @pAdapter: Pointer to adapter
13719 * @req: Pointer to security parameters
13720 *
13721 * Return: 0 for success, non-zero for failure
13722 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013723static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13724 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725{
13726 int status = 0;
13727 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13728 ENTER();
13729
13730 /*set wpa version */
13731 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13732
13733 if (req->crypto.wpa_versions) {
13734 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13735 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13736 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13737 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13738 }
13739 }
13740
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013741 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013742
13743 /*set authentication type */
13744 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13745
13746 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013747 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748 return status;
13749 }
13750
13751 /*set key mgmt type */
13752 if (req->crypto.n_akm_suites) {
13753 status =
13754 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13755 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013756 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013757 return status;
13758 }
13759 }
13760
13761 /*set pairwise cipher type */
13762 if (req->crypto.n_ciphers_pairwise) {
13763 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13764 req->crypto.
13765 ciphers_pairwise[0],
13766 true);
13767 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013768 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 return status;
13770 }
13771 } else {
13772 /*Reset previous cipher suite to none */
13773 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13774 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013775 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013776 return status;
13777 }
13778 }
13779
13780 /*set group cipher type */
13781 status =
13782 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13783 false);
13784
13785 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013786 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013787 return status;
13788 }
13789#ifdef WLAN_FEATURE_11W
13790 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13791#endif
13792
13793 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13794 if (req->ie_len) {
13795 status =
13796 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13797 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013798 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 return status;
13800 }
13801 }
13802
13803 /*incase of WEP set default key information */
13804 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013805 u8 key_len = req->key_len;
13806 u8 key_idx = req->key_idx;
13807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13809 || (WLAN_CIPHER_SUITE_WEP104 ==
13810 req->crypto.ciphers_pairwise[0])
13811 ) {
13812 if (IW_AUTH_KEY_MGMT_802_1X
13813 ==
13814 (pWextState->
13815 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013816 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013818 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013819
Jeff Johnson68755312017-02-10 11:46:55 -080013820 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13821 && (CSR_MAX_NUM_KEY > key_idx)) {
13822 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13823 key_idx, key_len);
13824 qdf_mem_copy(&pWextState->roamProfile.
13825 Keys.
13826 KeyMaterial[key_idx][0],
13827 req->key, key_len);
13828 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013830 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013832 }
13833 }
13834 }
13835
13836 return status;
13837}
13838
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013839int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840{
13841 unsigned long rc;
13842 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013843 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013844
13845 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13846
Jeff Johnson9edf9572016-10-03 15:24:49 -070013847 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013848 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13849 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13850 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 hdd_conn_set_connection_state(pAdapter,
13852 eConnectionState_Disconnecting);
13853 /* Issue disconnect to CSR */
13854 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013855
13856 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13857 pAdapter->sessionId,
13858 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13859 /*
13860 * Wait here instead of returning directly, this will block the
13861 * next connect command and allow processing of the scan for
13862 * ssid and the previous connect command in CSR. Else we might
13863 * hit some race conditions leading to SME and HDD out of sync.
13864 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013865 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013866 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13867 } else if (0 != status) {
13868 hdd_err("csrRoamDisconnect failure, returned %d",
13869 (int)status);
13870 pHddStaCtx->staDebugState = status;
13871 result = -EINVAL;
13872 goto disconnected;
13873 }
13874
13875 rc = wait_for_completion_timeout(
13876 &pAdapter->disconnect_comp_var,
13877 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013878 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013879 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13880 pAdapter->sessionId, pHddStaCtx->staDebugState);
13881 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013882 }
13883 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013884 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013886 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013887 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013888 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013889 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013890 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891 }
13892 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013893disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013894 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13895 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896}
13897
13898/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013899 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13900 * @adapter: Pointer to the HDD adapter
13901 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013902 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013903 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013904 * This function will start reassociation if prev_bssid is set and bssid/
13905 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013906 *
Naveen Rawat07332902016-07-27 09:13:17 -070013907 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013908 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013909#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13910 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013911static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13912 struct cfg80211_connect_params *req,
13913 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013914{
Naveen Rawat07332902016-07-27 09:13:17 -070013915 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013916 const uint8_t *bssid = NULL;
13917 uint16_t channel = 0;
13918
13919 if (req->bssid)
13920 bssid = req->bssid;
13921 else if (req->bssid_hint)
13922 bssid = req->bssid_hint;
13923
13924 if (req->channel)
13925 channel = req->channel->hw_value;
13926 else if (req->channel_hint)
13927 channel = req->channel_hint->hw_value;
13928
13929 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013930 reassoc = true;
13931 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013932 channel, MAC_ADDR_ARRAY(bssid));
13933 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013934 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013935 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013936 }
Naveen Rawat07332902016-07-27 09:13:17 -070013937 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013938}
13939#else
Naveen Rawat07332902016-07-27 09:13:17 -070013940static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13941 struct cfg80211_connect_params *req,
13942 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013943{
Naveen Rawat07332902016-07-27 09:13:17 -070013944 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013945}
13946#endif
13947
13948/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013949 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13950 * @wiphy: Pointer to wiphy
13951 * @dev: Pointer to network device
13952 * @req: Pointer to cfg80211 connect request
13953 *
13954 * This function is used to start the association process
13955 *
13956 * Return: 0 for success, non-zero for failure
13957 */
13958static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13959 struct net_device *ndev,
13960 struct cfg80211_connect_params *req)
13961{
13962 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013963 u16 channel;
13964#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13965 const u8 *bssid_hint = req->bssid_hint;
13966#else
13967 const u8 *bssid_hint = NULL;
13968#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013969 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13970 hdd_context_t *pHddCtx;
13971
13972 ENTER();
13973
Anurag Chouhan6d760662016-02-20 16:05:43 +053013974 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013975 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976 return -EINVAL;
13977 }
13978
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013979 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13980 hdd_err("invalid session id: %d", pAdapter->sessionId);
13981 return -EINVAL;
13982 }
13983
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013984 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 TRACE_CODE_HDD_CFG80211_CONNECT,
13986 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013987 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013988 hdd_device_mode_to_string(pAdapter->device_mode),
13989 pAdapter->device_mode);
13990
Krunal Sonib4326f22016-03-10 13:05:51 -080013991 if (pAdapter->device_mode != QDF_STA_MODE &&
13992 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013993 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994 hdd_device_mode_to_string(pAdapter->device_mode),
13995 pAdapter->device_mode);
13996 return -EINVAL;
13997 }
13998
13999 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14000 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014001 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014002 return -EINVAL;
14003 }
14004
14005 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014006 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014007 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014008
Naveen Rawat07332902016-07-27 09:13:17 -070014009 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014010 return status;
14011
Agrawal Ashishf156e942016-08-04 14:54:47 +053014012 /* Try disconnecting if already in connected state */
14013 status = wlan_hdd_try_disconnect(pAdapter);
14014 if (0 > status) {
14015 hdd_err("Failed to disconnect the existing connection");
14016 return -EALREADY;
14017 }
14018
14019 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014021 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014022 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014023 pAdapter->device_mode),
14024 req->channel->hw_value, HW_MODE_20_MHZ)) {
14025 hdd_err("This concurrency combination is not allowed");
14026 return -ECONNREFUSED;
14027 }
14028 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014029 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014030 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14032 hdd_err("This concurrency combination is not allowed");
14033 return -ECONNREFUSED;
14034 }
14035 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014036
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014037 /*initialise security parameters */
14038 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14039
14040 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014041 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 return status;
14043 }
14044
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014045 if (req->channel)
14046 channel = req->channel->hw_value;
14047 else
14048 channel = 0;
14049 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14050 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014051 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014052 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014053 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054 return status;
14055 }
14056 EXIT();
14057 return status;
14058}
14059
14060/**
14061 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14062 * @wiphy: Pointer to wiphy
14063 * @dev: Pointer to network device
14064 * @req: Pointer to cfg80211 connect request
14065 *
14066 * Return: 0 for success, non-zero for failure
14067 */
14068static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14069 struct net_device *ndev,
14070 struct cfg80211_connect_params *req)
14071{
14072 int ret;
14073 cds_ssr_protect(__func__);
14074 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14075 cds_ssr_unprotect(__func__);
14076
14077 return ret;
14078}
14079
14080/**
14081 * wlan_hdd_disconnect() - hdd disconnect api
14082 * @pAdapter: Pointer to adapter
14083 * @reason: Disconnect reason code
14084 *
14085 * This function is used to issue a disconnect request to SME
14086 *
14087 * Return: 0 for success, non-zero for failure
14088 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014089static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014090{
14091 int status, result = 0;
14092 unsigned long rc;
14093 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14094 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14095
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014096 ENTER();
14097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098 status = wlan_hdd_validate_context(pHddCtx);
14099
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014100 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014101 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014102
14103 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014104 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014105 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
14106 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014107 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14109 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14110
14111 /*issue disconnect */
14112
14113 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14114 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053014115 /*
14116 * Wait here instead of returning directly, this will block the next
14117 * connect command and allow processing of the scan for ssid and
14118 * the previous connect command in CSR. Else we might hit some
14119 * race conditions leading to SME and HDD out of sync.
14120 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014121 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014122 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014123 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014124 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014125 (int)status);
14126 pHddStaCtx->staDebugState = status;
14127 result = -EINVAL;
14128 goto disconnected;
14129 }
14130 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14131 msecs_to_jiffies
14132 (WLAN_WAIT_TIME_DISCONNECT));
14133
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014134 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014135 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136 result = -ETIMEDOUT;
14137 }
14138disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014139 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14140#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14141 /* Sending disconnect event to userspace for kernel version < 3.11
14142 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14143 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014144 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014145 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14146 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014147#endif
14148
14149 return result;
14150}
14151
14152/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014153 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14154 * @reason: ieee80211 reason code.
14155 *
14156 * This utility function helps log string conversion of reason code.
14157 *
14158 * Return: string conversion of reason code, if match found;
14159 * "Unknown" otherwise.
14160 */
14161static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14162{
14163 switch (reason) {
14164 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14165 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14166 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14167 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14168 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14169 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14170 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14171 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14172 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14173 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14174 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14175 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14176 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14177 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14178 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14179 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14180 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14181 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14182 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14183 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14184 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14185 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14186 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14187 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14188 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14189 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14190 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14191 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14192 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14193 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14194 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14195 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14196 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14197 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14198 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14199 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14200 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14201 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14202 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14203 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14204 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14205 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14206 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14207 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14208 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14209 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14210 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14211 default:
14212 return "Unknown";
14213 }
14214}
14215
14216/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14218 * @wiphy: Pointer to wiphy
14219 * @dev: Pointer to network device
14220 * @reason: Disconnect reason code
14221 *
14222 * This function is used to issue a disconnect request to SME
14223 *
14224 * Return: 0 for success, non-zero for failure
14225 */
14226static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14227 struct net_device *dev, u16 reason)
14228{
14229 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14230 int status;
14231 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14232 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14233#ifdef FEATURE_WLAN_TDLS
14234 uint8_t staIdx;
14235#endif
14236
14237 ENTER();
14238
Anurag Chouhan6d760662016-02-20 16:05:43 +053014239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014240 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241 return -EINVAL;
14242 }
14243
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014244 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14245 hdd_err("invalid session id: %d", pAdapter->sessionId);
14246 return -EINVAL;
14247 }
14248
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014249 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014250 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14251 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014252 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014253 hdd_device_mode_to_string(pAdapter->device_mode),
14254 pAdapter->device_mode, reason);
14255
14256 status = wlan_hdd_validate_context(pHddCtx);
14257
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080014258 if (hdd_is_roaming_in_progress()) {
14259 hdd_err("Roaming In Progress. Ignore!!!");
14260 return -EAGAIN;
14261 }
14262
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014263 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014265
14266 /* Issue disconnect request to SME, if station is in connected state */
14267 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14268 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14269 eCsrRoamDisconnectReason reasonCode =
14270 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14271 hdd_scaninfo_t *pScanInfo;
14272
14273 switch (reason) {
14274 case WLAN_REASON_MIC_FAILURE:
14275 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14276 break;
14277
14278 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14279 case WLAN_REASON_DISASSOC_AP_BUSY:
14280 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14281 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14282 break;
14283
14284 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14285 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14286 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14287 break;
14288
14289 case WLAN_REASON_DEAUTH_LEAVING:
14290 reasonCode =
14291 pHddCtx->config->
14292 gEnableDeauthToDisassocMap ?
14293 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14294 eCSR_DISCONNECT_REASON_DEAUTH;
14295 break;
14296 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14297 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14298 break;
14299 default:
14300 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14301 break;
14302 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014303 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014305 pScanInfo = &pAdapter->scan_info;
14306 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014307 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014308 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014309 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014310 eCSR_SCAN_ABORT_DEFAULT);
14311 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014312 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014313#ifdef FEATURE_WLAN_TDLS
14314 /* First clean up the tdls peers if any */
14315 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14316 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14317 pAdapter->sessionId)
14318 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14319 uint8_t *mac;
14320 mac =
14321 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014322 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14323 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014324 pHddCtx->tdlsConnInfo[staIdx].staId,
14325 pAdapter->sessionId,
14326 MAC_ADDR_ARRAY(mac));
14327 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14328 (pAdapter),
14329 pAdapter->sessionId, mac);
14330 }
14331 }
14332#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014333 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014335 hdd_info("Disconnect request from user space with reason: %s",
14336 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14338 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014339 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014340 return -EINVAL;
14341 }
14342 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014343 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 pHddStaCtx->conn_info.connState);
14345 }
14346
14347 return status;
14348}
14349
14350/**
14351 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14352 * @wiphy: Pointer to wiphy
14353 * @dev: Pointer to network device
14354 * @reason: Disconnect reason code
14355 *
14356 * Return: 0 for success, non-zero for failure
14357 */
14358static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14359 struct net_device *dev, u16 reason)
14360{
14361 int ret;
14362 cds_ssr_protect(__func__);
14363 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14364 cds_ssr_unprotect(__func__);
14365
14366 return ret;
14367}
14368
14369/**
14370 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14371 * @pAdapter: Pointer to adapter
14372 * @param: Pointer to IBSS parameters
14373 *
14374 * This function is used to initialize the security settings in IBSS mode
14375 *
14376 * Return: 0 for success, non-zero for failure
14377 */
14378static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14379 struct cfg80211_ibss_params
14380 *params)
14381{
14382 int status = 0;
14383 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14384 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14385 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14386
14387 ENTER();
14388
14389 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014390 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014391 pHddStaCtx->ibss_enc_key_installed = 0;
14392
14393 if (params->ie_len && (NULL != params->ie)) {
14394 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14395 params->ie_len, WLAN_EID_RSN)) {
14396 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14397 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14398 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14399 tDot11fIEWPA dot11WPAIE;
14400 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14401 u8 *ie;
14402
14403 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14404 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14405 params->ie_len,
14406 DOT11F_EID_WPA);
14407 if (NULL != ie) {
14408 pWextState->wpaVersion =
14409 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014410 /* Unpack the WPA IE
14411 * Skip past the EID byte and length byte
14412 * and four byte WiFi OUI
14413 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014414 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14415 &ie[2 + 4],
14416 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014417 /* Extract the multicast cipher, the
14418 * encType for unicast cipher for
14419 * wpa-none is none
14420 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014421 encryptionType =
14422 hdd_translate_wpa_to_csr_encryption_type
14423 (dot11WPAIE.multicast_cipher);
14424 }
14425 }
14426
14427 status =
14428 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14429 params->ie_len);
14430
14431 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014432 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433 return status;
14434 }
14435 }
14436
14437 pWextState->roamProfile.AuthType.authType[0] =
14438 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14439
14440 if (params->privacy) {
14441 /* Security enabled IBSS, At this time there is no information
14442 * available about the security paramters, so initialise the
14443 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14444 * The correct security parameters will be updated later in
14445 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14446 * set inorder enable privacy bit in beacons
14447 */
14448
14449 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14450 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014451 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14453 pWextState->roamProfile.EncryptionType.numEntries = 1;
14454 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14455 encryptionType;
14456 return status;
14457}
14458
14459/**
14460 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14461 * @wiphy: Pointer to wiphy
14462 * @dev: Pointer to network device
14463 * @param: Pointer to IBSS join parameters
14464 *
14465 * This function is used to create/join an IBSS network
14466 *
14467 * Return: 0 for success, non-zero for failure
14468 */
14469static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14470 struct net_device *dev,
14471 struct cfg80211_ibss_params *params)
14472{
14473 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14474 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14475 tCsrRoamProfile *pRoamProfile;
14476 int status;
14477 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14478 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014479 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014480 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481
14482 ENTER();
14483
Anurag Chouhan6d760662016-02-20 16:05:43 +053014484 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014485 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 return -EINVAL;
14487 }
14488
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014489 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14490 hdd_err("invalid session id: %d", pAdapter->sessionId);
14491 return -EINVAL;
14492 }
14493
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014494 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014495 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14496 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014497 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014498 hdd_device_mode_to_string(pAdapter->device_mode),
14499 pAdapter->device_mode);
14500
14501 status = wlan_hdd_validate_context(pHddCtx);
14502
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014503 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014504 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014505
14506 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014507 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014508 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14509 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14510 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14511 int indx;
14512
14513 /* Get channel number */
14514 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 params->
14516 chandef.
14517 chan->
14518 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014519
14520 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14521 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014522 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 return -EOPNOTSUPP;
14524 }
14525
14526 for (indx = 0; indx < numChans; indx++) {
14527 if (channelNum == validChan[indx]) {
14528 break;
14529 }
14530 }
14531 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014532 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014533 return -EINVAL;
14534 }
14535 }
14536
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014537 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 HW_MODE_20_MHZ)) {
14539 hdd_err("This concurrency combination is not allowed");
14540 return -ECONNREFUSED;
14541 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014542
Krunal Soni3091bcc2016-06-23 12:28:21 -070014543 status = qdf_reset_connection_update();
14544 if (!QDF_IS_STATUS_SUCCESS(status))
14545 hdd_err("ERR: clear event failed");
14546
14547 status = cds_current_connections_update(pAdapter->sessionId,
14548 channelNum,
14549 SIR_UPDATE_REASON_JOIN_IBSS);
14550 if (QDF_STATUS_E_FAILURE == status) {
14551 hdd_err("ERROR: connections update failed!!");
14552 return -EINVAL;
14553 }
14554
14555 if (QDF_STATUS_SUCCESS == status) {
14556 status = qdf_wait_for_connection_update();
14557 if (!QDF_IS_STATUS_SUCCESS(status)) {
14558 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014559 return -EINVAL;
14560 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 }
14562
14563 /*Try disconnecting if already in connected state */
14564 status = wlan_hdd_try_disconnect(pAdapter);
14565 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014566 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 return -EALREADY;
14568 }
14569
14570 pRoamProfile = &pWextState->roamProfile;
14571
14572 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014573 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014574 return -EINVAL;
14575 }
14576
14577 /* enable selected protection checks in IBSS mode */
14578 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14579
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014580 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014581 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14582 pHddCtx->config->
14583 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014584 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014585 }
14586
14587 /* BSSID is provided by upper layers hence no need to AUTO generate */
14588 if (NULL != params->bssid) {
14589 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014590 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014591 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014592 return -EIO;
14593 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014594 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014595 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14596 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014597 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014598 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014599 return -EIO;
14600 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014601 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014602 }
14603 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14604 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14605 pRoamProfile->beaconInterval = params->beacon_interval;
14606 else {
14607 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014608 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014609 params->beacon_interval, pRoamProfile->beaconInterval);
14610 }
14611
14612 /* Set Channel */
14613 if (channelNum) {
14614 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014615 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014616 pRoamProfile->ChannelInfo.numOfChannels = 1;
14617 pHddStaCtx->conn_info.operationChannel = channelNum;
14618 pRoamProfile->ChannelInfo.ChannelList =
14619 &pHddStaCtx->conn_info.operationChannel;
14620 }
14621
14622 /* Initialize security parameters */
14623 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14624 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014625 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014626 return status;
14627 }
14628
14629 /* Issue connect start */
14630 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14631 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014632 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014633 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014634 operationChannel,
14635 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014636
14637 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014638 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014639 return status;
14640 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014641 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014642 return 0;
14643}
14644
14645/**
14646 * wlan_hdd_cfg80211_join_ibss() - join ibss
14647 * @wiphy: Pointer to wiphy
14648 * @dev: Pointer to network device
14649 * @param: Pointer to IBSS join parameters
14650 *
14651 * This function is used to create/join an IBSS network
14652 *
14653 * Return: 0 for success, non-zero for failure
14654 */
14655static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14656 struct net_device *dev,
14657 struct cfg80211_ibss_params *params)
14658{
14659 int ret = 0;
14660
14661 cds_ssr_protect(__func__);
14662 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14663 cds_ssr_unprotect(__func__);
14664
14665 return ret;
14666}
14667
14668/**
14669 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14670 * @wiphy: Pointer to wiphy
14671 * @dev: Pointer to network device
14672 *
14673 * This function is used to leave an IBSS network
14674 *
14675 * Return: 0 for success, non-zero for failure
14676 */
14677static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14678 struct net_device *dev)
14679{
14680 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14681 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14682 tCsrRoamProfile *pRoamProfile;
14683 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14684 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014685 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014686 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014687 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014688
14689 ENTER();
14690
Anurag Chouhan6d760662016-02-20 16:05:43 +053014691 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014692 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 return -EINVAL;
14694 }
14695
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014696 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14697 hdd_err("invalid session id: %d", pAdapter->sessionId);
14698 return -EINVAL;
14699 }
14700
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014701 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014702 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14703 pAdapter->sessionId,
14704 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14705 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014706 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014707 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014708
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014709 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014710 hdd_device_mode_to_string(pAdapter->device_mode),
14711 pAdapter->device_mode);
14712 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014713 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014714 return -EIO;
14715 }
14716
14717 pRoamProfile = &pWextState->roamProfile;
14718
14719 /* Issue disconnect only if interface type is set to IBSS */
14720 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014721 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722 return -EINVAL;
14723 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014724 /* Clearing add IE of beacon */
14725 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14726 sizeof(tSirMacAddr));
14727 updateIE.smeSessionId = pAdapter->sessionId;
14728 updateIE.ieBufferlength = 0;
14729 updateIE.pAdditionIEBuffer = NULL;
14730 updateIE.append = true;
14731 updateIE.notify = true;
14732 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14733 &updateIE,
14734 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014735 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014736 }
14737
14738 /* Reset WNI_CFG_PROBE_RSP Flags */
14739 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014740
14741 /* Issue Disconnect request */
14742 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14743 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14744 pAdapter->sessionId,
14745 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014746 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014747 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748 hal_status);
14749 return -EAGAIN;
14750 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014751
14752 /* wait for mc thread to cleanup and then return to upper stack
14753 * so by the time upper layer calls the change interface, we are
14754 * all set to proceed further
14755 */
14756 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14757 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14758 if (!rc) {
14759 hdd_err("Failed to disconnect, timed out");
14760 return -ETIMEDOUT;
14761 }
14762
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014763 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014764 return 0;
14765}
14766
14767/**
14768 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14769 * @wiphy: Pointer to wiphy
14770 * @dev: Pointer to network device
14771 *
14772 * This function is used to leave an IBSS network
14773 *
14774 * Return: 0 for success, non-zero for failure
14775 */
14776static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14777 struct net_device *dev)
14778{
14779 int ret = 0;
14780
14781 cds_ssr_protect(__func__);
14782 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14783 cds_ssr_unprotect(__func__);
14784
14785 return ret;
14786}
14787
14788/**
14789 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14790 * @wiphy: Pointer to wiphy
14791 * @changed: Parameters changed
14792 *
14793 * This function is used to set the phy parameters. RTS Threshold/FRAG
14794 * Threshold/Retry Count etc.
14795 *
14796 * Return: 0 for success, non-zero for failure
14797 */
14798static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14799 u32 changed)
14800{
14801 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14802 tHalHandle hHal = pHddCtx->hHal;
14803 int status;
14804
14805 ENTER();
14806
Anurag Chouhan6d760662016-02-20 16:05:43 +053014807 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014808 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 return -EINVAL;
14810 }
14811
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014812 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14814 NO_SESSION, wiphy->rts_threshold));
14815 status = wlan_hdd_validate_context(pHddCtx);
14816
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014817 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014819
14820 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14821 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14822 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14823
14824 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14825 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014826 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014827 rts_threshold);
14828 return -EINVAL;
14829 }
14830
14831 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14832 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014833 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014834 rts_threshold);
14835 return -EIO;
14836 }
14837
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014838 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014839 }
14840
14841 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14842 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14843 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14844 wiphy->frag_threshold;
14845
14846 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14847 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014848 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 frag_threshold);
14850 return -EINVAL;
14851 }
14852
14853 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14854 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014855 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856 frag_threshold);
14857 return -EIO;
14858 }
14859
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014860 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014861 }
14862
14863 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14864 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14865 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14866 wiphy->retry_short : wiphy->retry_long;
14867
14868 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14869 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014870 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014871 return -EINVAL;
14872 }
14873
14874 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14875 if (0 != sme_cfg_set_int(hHal,
14876 WNI_CFG_LONG_RETRY_LIMIT,
14877 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014878 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879 retry_value);
14880 return -EIO;
14881 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014882 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14884 if (0 != sme_cfg_set_int(hHal,
14885 WNI_CFG_SHORT_RETRY_LIMIT,
14886 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014887 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014888 retry_value);
14889 return -EIO;
14890 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014891 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014892 }
14893 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014894 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014895 return 0;
14896}
14897
14898/**
14899 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14900 * @wiphy: Pointer to wiphy
14901 * @changed: Parameters changed
14902 *
14903 * Return: 0 for success, non-zero for failure
14904 */
14905static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14906{
14907 int ret;
14908
14909 cds_ssr_protect(__func__);
14910 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14911 cds_ssr_unprotect(__func__);
14912
14913 return ret;
14914}
14915
14916/**
14917 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14918 * key
14919 * @wiphy: Pointer to wiphy
14920 * @dev: Pointer to network device
14921 * @key_index: Key index
14922 *
14923 * Return: 0
14924 */
14925static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14926 struct net_device *netdev,
14927 u8 key_index)
14928{
14929 ENTER();
14930 return 0;
14931}
14932
14933/**
14934 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14935 * wlan_hdd_set_default_mgmt_key
14936 * @wiphy: pointer to wiphy
14937 * @netdev: pointer to net_device structure
14938 * @key_index: key index
14939 *
14940 * Return: 0 on success, error number on failure
14941 */
14942static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14943 struct net_device *netdev,
14944 u8 key_index)
14945{
14946 int ret;
14947
14948 cds_ssr_protect(__func__);
14949 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14950 cds_ssr_unprotect(__func__);
14951
14952 return ret;
14953}
14954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014955/**
14956 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14957 * @wiphy: Pointer to wiphy
14958 * @dev: Pointer to network device
14959 * @params: Pointer to tx queue parameters
14960 *
14961 * Return: 0
14962 */
14963static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14964 struct net_device *dev,
14965 struct ieee80211_txq_params *params)
14966{
14967 ENTER();
14968 return 0;
14969}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970
14971/**
14972 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
14973 * @wiphy: pointer to wiphy
14974 * @netdev: pointer to net_device structure
14975 * @params: pointer to ieee80211_txq_params
14976 *
14977 * Return: 0 on success, error number on failure
14978 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014979static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14980 struct net_device *dev,
14981 struct ieee80211_txq_params *params)
14982{
14983 int ret;
14984
14985 cds_ssr_protect(__func__);
14986 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14987 cds_ssr_unprotect(__func__);
14988
14989 return ret;
14990}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014991
14992/**
14993 * __wlan_hdd_cfg80211_del_station() - delete station v2
14994 * @wiphy: Pointer to wiphy
14995 * @param: Pointer to delete station parameter
14996 *
14997 * Return: 0 for success, non-zero for failure
14998 */
14999static
15000int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15001 struct net_device *dev,
15002 struct tagCsrDelStaParams *pDelStaParams)
15003{
15004 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15005 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015006 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015007 hdd_hostapd_state_t *hapd_state;
15008 int status;
15009 uint8_t staId;
15010 uint8_t *mac;
15011
15012 ENTER();
15013
Anurag Chouhan6d760662016-02-20 16:05:43 +053015014 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015015 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015016 return -EINVAL;
15017 }
15018
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015019 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15020 hdd_err("invalid session id: %d", pAdapter->sessionId);
15021 return -EINVAL;
15022 }
15023
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015024 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025 TRACE_CODE_HDD_CFG80211_DEL_STA,
15026 pAdapter->sessionId, pAdapter->device_mode));
15027
15028 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15029 status = wlan_hdd_validate_context(pHddCtx);
15030
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015031 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015033
15034 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15035
Krunal Sonib4326f22016-03-10 13:05:51 -080015036 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15037 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015038
15039 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15040 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015041 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015042 return 0;
15043 }
15044
Anurag Chouhanc5548422016-02-24 18:33:27 +053015045 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015046 uint16_t i;
15047 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15048 if ((pAdapter->aStaInfo[i].isUsed) &&
15049 (!pAdapter->aStaInfo[i].
15050 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015051 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 mac,
15053 pAdapter->aStaInfo[i].
15054 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015055 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015056 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15057 hdd_ipa_wlan_evt(pAdapter,
15058 pAdapter->
15059 aStaInfo[i].
15060 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015061 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015062 mac);
15063 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015064 hdd_notice("Delete STA with MAC::"
15065 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015066 MAC_ADDR_ARRAY(mac));
15067
15068 if (pHddCtx->dev_dfs_cac_status ==
15069 DFS_CAC_IN_PROGRESS)
15070 goto fn_end;
15071
Wei Song2f76f642016-11-18 16:32:53 +080015072 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015073 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015074 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015075 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015076 hdd_softap_sta_deauth(pAdapter,
15077 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015078 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015079 pAdapter->aStaInfo[i].
15080 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015081 qdf_status =
15082 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015083 &hapd_state->
15084 qdf_sta_disassoc_event,
15085 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015086 if (!QDF_IS_STATUS_SUCCESS(
15087 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015088 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015089 }
15090 }
15091 }
15092 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015093 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015094 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015095 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015097 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015098 hdd_notice("Skip DEL STA as this is not used::"
15099 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015100 MAC_ADDR_ARRAY(mac));
15101 return -ENOENT;
15102 }
15103
15104 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15105 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015106 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015107 }
15108
15109 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15110 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015111 hdd_notice("Skip DEL STA as deauth is in progress::"
15112 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015113 MAC_ADDR_ARRAY(mac));
15114 return -ENOENT;
15115 }
15116
15117 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15118
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015119 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015120 MAC_ADDR_ARRAY(mac));
15121
15122 /* Case: SAP in ACS selected DFS ch and client connected
15123 * Now Radar detected. Then if random channel is another
15124 * DFS ch then new CAC is initiated and no TX allowed.
15125 * So do not send any mgmt frames as it will timeout
15126 * during CAC.
15127 */
15128
15129 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15130 goto fn_end;
15131
Wei Song2f76f642016-11-18 16:32:53 +080015132 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015133 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15134 (pAdapter), pAdapter->sessionId,
15135 (uint8_t *)&pDelStaParams->peerMacAddr,
15136 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015137 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015138 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015139 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015140 pAdapter->aStaInfo[staId].isDeauthInProgress =
15141 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015142 hdd_notice("STA removal failed for ::"
15143 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015144 MAC_ADDR_ARRAY(mac));
15145 return -ENOENT;
15146 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015147 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015148 &hapd_state->
15149 qdf_sta_disassoc_event,
15150 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015151 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015152 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015153 }
15154 }
15155 }
15156
15157fn_end:
15158 EXIT();
15159 return 0;
15160}
15161
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015162#if defined(USE_CFG80211_DEL_STA_V2)
15163/**
15164 * wlan_hdd_del_station() - delete station wrapper
15165 * @adapter: pointer to the hdd adapter
15166 *
15167 * Return: None
15168 */
15169void wlan_hdd_del_station(hdd_adapter_t *adapter)
15170{
15171 struct station_del_parameters del_sta;
15172 del_sta.mac = NULL;
15173 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15174 del_sta.reason_code = eCsrForcedDeauthSta;
15175
15176 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15177 &del_sta);
15178}
15179#else
15180void wlan_hdd_del_station(hdd_adapter_t *adapter)
15181{
15182 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15183}
15184#endif
15185
15186#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187/**
15188 * wlan_hdd_cfg80211_del_station() - delete station v2
15189 * @wiphy: Pointer to wiphy
15190 * @param: Pointer to delete station parameter
15191 *
15192 * Return: 0 for success, non-zero for failure
15193 */
15194int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15195 struct net_device *dev,
15196 struct station_del_parameters *param)
15197#else
15198/**
15199 * wlan_hdd_cfg80211_del_station() - delete station
15200 * @wiphy: Pointer to wiphy
15201 * @mac: Pointer to station mac address
15202 *
15203 * Return: 0 for success, non-zero for failure
15204 */
15205#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15206int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15207 struct net_device *dev,
15208 const uint8_t *mac)
15209#else
15210int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15211 struct net_device *dev,
15212 uint8_t *mac)
15213#endif
15214#endif
15215{
15216 int ret;
15217 struct tagCsrDelStaParams delStaParams;
15218
15219 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015220#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015221 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015222 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223 return -EINVAL;
15224 }
15225 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15226 param->subtype, &delStaParams);
15227#else
15228 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15229 (SIR_MAC_MGMT_DEAUTH >> 4),
15230 &delStaParams);
15231#endif
15232 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15233 cds_ssr_unprotect(__func__);
15234
15235 return ret;
15236}
15237
15238/**
15239 * __wlan_hdd_cfg80211_add_station() - add station
15240 * @wiphy: Pointer to wiphy
15241 * @mac: Pointer to station mac address
15242 * @pmksa: Pointer to add station parameter
15243 *
15244 * Return: 0 for success, non-zero for failure
15245 */
15246static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15247 struct net_device *dev,
15248 const uint8_t *mac,
15249 struct station_parameters *params)
15250{
15251 int status = -EPERM;
15252#ifdef FEATURE_WLAN_TDLS
15253 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15254 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15255 u32 mask, set;
15256
15257 ENTER();
15258
Anurag Chouhan6d760662016-02-20 16:05:43 +053015259 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015260 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015261 return -EINVAL;
15262 }
15263
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015264 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15265 hdd_err("invalid session id: %d", pAdapter->sessionId);
15266 return -EINVAL;
15267 }
15268
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015269 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270 TRACE_CODE_HDD_CFG80211_ADD_STA,
15271 pAdapter->sessionId, params->listen_interval));
15272
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015273 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015274 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015275
15276 mask = params->sta_flags_mask;
15277
15278 set = params->sta_flags_set;
15279
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015280 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015281 MAC_ADDR_ARRAY(mac));
15282
15283 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15284 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15285 status =
15286 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15287 }
15288 }
15289#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015290 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291 return status;
15292}
15293
15294/**
15295 * wlan_hdd_cfg80211_add_station() - add station
15296 * @wiphy: Pointer to wiphy
15297 * @mac: Pointer to station mac address
15298 * @pmksa: Pointer to add station parameter
15299 *
15300 * Return: 0 for success, non-zero for failure
15301 */
15302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15303static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15304 struct net_device *dev,
15305 const uint8_t *mac,
15306 struct station_parameters *params)
15307#else
15308static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15309 struct net_device *dev, uint8_t *mac,
15310 struct station_parameters *params)
15311#endif
15312{
15313 int ret;
15314
15315 cds_ssr_protect(__func__);
15316 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15317 cds_ssr_unprotect(__func__);
15318
15319 return ret;
15320}
15321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015322/**
15323 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15324 * @wiphy: Pointer to wiphy
15325 * @dev: Pointer to network device
15326 * @pmksa: Pointer to set pmksa parameter
15327 *
15328 * Return: 0 for success, non-zero for failure
15329 */
15330static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15331 struct net_device *dev,
15332 struct cfg80211_pmksa *pmksa)
15333{
15334 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15335 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15336 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015337 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015338 int status;
15339 tPmkidCacheInfo pmk_id;
15340
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015341 ENTER();
15342
Anurag Chouhan6d760662016-02-20 16:05:43 +053015343 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015344 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015345 return -EINVAL;
15346 }
15347
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015348 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15349 hdd_err("invalid session id: %d", pAdapter->sessionId);
15350 return -EINVAL;
15351 }
15352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015353 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015354 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015355 return -EINVAL;
15356 }
15357
15358 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015359 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015360 pmksa->bssid, pmksa->pmkid);
15361 return -EINVAL;
15362 }
15363
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015364 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015365 MAC_ADDR_ARRAY(pmksa->bssid));
15366
15367 status = wlan_hdd_validate_context(pHddCtx);
15368
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015369 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015370 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015371
15372 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15373
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015374 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15375 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015376
15377 /* Add to the PMKSA ID Cache in CSR */
15378 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15379 &pmk_id, 1, false);
15380
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015381 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015382 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15383 pAdapter->sessionId, result));
15384
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015385 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015386 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015387}
15388
15389/**
15390 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15391 * @wiphy: Pointer to wiphy
15392 * @dev: Pointer to network device
15393 * @pmksa: Pointer to set pmksa parameter
15394 *
15395 * Return: 0 for success, non-zero for failure
15396 */
15397static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15398 struct net_device *dev,
15399 struct cfg80211_pmksa *pmksa)
15400{
15401 int ret;
15402
15403 cds_ssr_protect(__func__);
15404 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15405 cds_ssr_unprotect(__func__);
15406
15407 return ret;
15408}
15409
15410/**
15411 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15412 * @wiphy: Pointer to wiphy
15413 * @dev: Pointer to network device
15414 * @pmksa: Pointer to pmksa parameter
15415 *
15416 * Return: 0 for success, non-zero for failure
15417 */
15418static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15419 struct net_device *dev,
15420 struct cfg80211_pmksa *pmksa)
15421{
15422 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15423 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15424 tHalHandle halHandle;
15425 int status = 0;
15426
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015427 ENTER();
15428
Anurag Chouhan6d760662016-02-20 16:05:43 +053015429 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015430 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015431 return -EINVAL;
15432 }
15433
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015434 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15435 hdd_err("invalid session id: %d", pAdapter->sessionId);
15436 return -EINVAL;
15437 }
15438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015439 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015440 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015441 return -EINVAL;
15442 }
15443
15444 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015445 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015446 return -EINVAL;
15447 }
15448
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015449 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015450 MAC_ADDR_ARRAY(pmksa->bssid));
15451
15452 status = wlan_hdd_validate_context(pHddCtx);
15453
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015454 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015455 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015456
15457 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15458
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015459 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015460 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15461 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015462 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015463 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015464 sme_roam_del_pmkid_from_cache(halHandle,
15465 pAdapter->sessionId, pmksa->bssid,
15466 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015467 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015468 MAC_ADDR_ARRAY(pmksa->bssid));
15469 status = -EINVAL;
15470 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015471 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015472 return status;
15473}
15474
15475/**
15476 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15477 * @wiphy: Pointer to wiphy
15478 * @dev: Pointer to network device
15479 * @pmksa: Pointer to pmksa parameter
15480 *
15481 * Return: 0 for success, non-zero for failure
15482 */
15483static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15484 struct net_device *dev,
15485 struct cfg80211_pmksa *pmksa)
15486{
15487 int ret;
15488
15489 cds_ssr_protect(__func__);
15490 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15491 cds_ssr_unprotect(__func__);
15492
15493 return ret;
15494
15495}
15496
15497/**
15498 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15499 * @wiphy: Pointer to wiphy
15500 * @dev: Pointer to network device
15501 *
15502 * Return: 0 for success, non-zero for failure
15503 */
15504static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15505 struct net_device *dev)
15506{
15507 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15508 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15509 tHalHandle halHandle;
15510 int status = 0;
15511
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015512 ENTER();
15513
Anurag Chouhan6d760662016-02-20 16:05:43 +053015514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015515 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015516 return -EINVAL;
15517 }
15518
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015519 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15520 hdd_err("invalid session id: %d", pAdapter->sessionId);
15521 return -EINVAL;
15522 }
15523
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015524 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015525
15526 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15527 status = wlan_hdd_validate_context(pHddCtx);
15528
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015529 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015530 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531
15532 /* Retrieve halHandle */
15533 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15534
15535 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015536 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015537 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15538 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015539 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015540 status = -EINVAL;
15541 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015542 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015543 return status;
15544}
15545
15546/**
15547 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15548 * @wiphy: Pointer to wiphy
15549 * @dev: Pointer to network device
15550 *
15551 * Return: 0 for success, non-zero for failure
15552 */
15553static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15554 struct net_device *dev)
15555{
15556 int ret;
15557
15558 cds_ssr_protect(__func__);
15559 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15560 cds_ssr_unprotect(__func__);
15561
15562 return ret;
15563}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015565#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015566/**
15567 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15568 * @wiphy: Pointer to wiphy
15569 * @dev: Pointer to network device
15570 * @ftie: Pointer to fast transition ie parameter
15571 *
15572 * Return: 0 for success, non-zero for failure
15573 */
15574static int
15575__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15576 struct net_device *dev,
15577 struct cfg80211_update_ft_ies_params *ftie)
15578{
15579 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15580 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15581 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15582 int status;
15583
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015584 ENTER();
15585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586 status = wlan_hdd_validate_context(hdd_ctx);
15587 if (status)
15588 return status;
15589
Anurag Chouhan6d760662016-02-20 16:05:43 +053015590 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015591 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592 return -EINVAL;
15593 }
15594
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015595 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15596 hdd_err("invalid session id: %d", pAdapter->sessionId);
15597 return -EINVAL;
15598 }
15599
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015600 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15602 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15603 /* Added for debug on reception of Re-assoc Req. */
15604 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015605 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015607 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015608 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015609 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015610 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015611
15612 /* Pass the received FT IEs to SME */
15613 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15614 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015615 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015616 return 0;
15617}
15618
15619/**
15620 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15621 * @wiphy: Pointer to wiphy
15622 * @dev: Pointer to network device
15623 * @ftie: Pointer to fast transition ie parameter
15624 *
15625 * Return: 0 for success, non-zero for failure
15626 */
15627static int
15628wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15629 struct net_device *dev,
15630 struct cfg80211_update_ft_ies_params *ftie)
15631{
15632 int ret;
15633
15634 cds_ssr_protect(__func__);
15635 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15636 cds_ssr_unprotect(__func__);
15637
15638 return ret;
15639}
15640#endif
15641
15642#ifdef WLAN_FEATURE_GTK_OFFLOAD
15643/**
15644 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
15645 * @callbackContext: Callback context
15646 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
15647 *
15648 * Callback rountine called upon receiving response for get offload info
15649 *
15650 * Return: none
15651 */
15652void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
15653 tpSirGtkOffloadGetInfoRspParams
15654 pGtkOffloadGetInfoRsp)
15655{
15656 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
15657 uint8_t tempReplayCounter[8];
15658 hdd_station_ctx_t *pHddStaCtx;
15659
15660 ENTER();
15661
15662 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015663 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015664 return;
15665 }
15666
15667 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015668 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015669 return;
15670 }
15671
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015672 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015673 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015674 return;
15675 }
15676
15677 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15678 /* Update replay counter */
15679 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
15680 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15681
15682 {
15683 /* changing from little to big endian since supplicant
15684 * works on big endian format
15685 */
15686 int i;
15687 uint8_t *p =
15688 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15689
15690 for (i = 0; i < 8; i++) {
15691 tempReplayCounter[7 - i] = (uint8_t) p[i];
15692 }
15693 }
15694
15695 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015696 cfg80211_gtk_rekey_notify(pAdapter->dev,
15697 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015698 tempReplayCounter, GFP_KERNEL);
15699}
15700
15701/**
15702 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15703 * @wiphy: Pointer to wiphy
15704 * @dev: Pointer to network device
15705 * @data: Pointer to rekey data
15706 *
15707 * This function is used to offload GTK rekeying job to the firmware.
15708 *
15709 * Return: 0 for success, non-zero for failure
15710 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015711static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015712int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15713 struct net_device *dev,
15714 struct cfg80211_gtk_rekey_data *data)
15715{
15716 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15717 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15718 hdd_station_ctx_t *pHddStaCtx;
15719 tHalHandle hHal;
15720 int result;
15721 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015722 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015723
15724 ENTER();
15725
Anurag Chouhan6d760662016-02-20 16:05:43 +053015726 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015727 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728 return -EINVAL;
15729 }
15730
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015731 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15732 hdd_err("invalid session id: %d", pAdapter->sessionId);
15733 return -EINVAL;
15734 }
15735
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015736 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015737 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15738 pAdapter->sessionId, pAdapter->device_mode));
15739
15740 result = wlan_hdd_validate_context(pHddCtx);
15741
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015742 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015743 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015744
15745 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15746 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15747 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015748 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015749 return -EAGAIN;
15750 }
15751
15752 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
15753 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
15754 NL80211_KCK_LEN);
15755 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
15756 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053015757 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015758 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015759 {
15760 /* changing from big to little endian since driver
15761 * works on little endian format
15762 */
15763 uint8_t *p =
15764 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
15765 ullKeyReplayCounter;
15766 int i;
15767
15768 for (i = 0; i < 8; i++) {
15769 p[7 - i] = data->replay_ctr[i];
15770 }
15771 }
15772
15773 if (true == pHddCtx->hdd_wlan_suspended) {
15774 /* if wlan is suspended, enable GTK offload directly from here */
15775 memcpy(&hddGtkOffloadReqParams,
15776 &pHddStaCtx->gtkOffloadReqParams,
15777 sizeof(tSirGtkOffloadParams));
15778 status =
15779 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
15780 pAdapter->sessionId);
15781
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015782 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015783 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015784 status);
15785 return -EINVAL;
15786 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015787 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015788 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015789 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015790 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015791 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015792 return result;
15793}
15794
15795/**
15796 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15797 * @wiphy: Pointer to wiphy
15798 * @dev: Pointer to network device
15799 * @data: Pointer to rekey data
15800 *
15801 * This function is used to offload GTK rekeying job to the firmware.
15802 *
15803 * Return: 0 for success, non-zero for failure
15804 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015805static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015806int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15807 struct net_device *dev,
15808 struct cfg80211_gtk_rekey_data *data)
15809{
15810 int ret;
15811
15812 cds_ssr_protect(__func__);
15813 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15814 cds_ssr_unprotect(__func__);
15815
15816 return ret;
15817}
15818#endif /*WLAN_FEATURE_GTK_OFFLOAD */
15819
15820/**
15821 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15822 * @wiphy: Pointer to wiphy
15823 * @dev: Pointer to network device
15824 * @param: Pointer to access control parameter
15825 *
15826 * Return: 0 for success, non-zero for failure
15827 */
15828static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15829 struct net_device *dev,
15830 const struct cfg80211_acl_data *params)
15831{
15832 int i;
15833 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15834 hdd_hostapd_state_t *pHostapdState;
15835 tsap_Config_t *pConfig;
15836 v_CONTEXT_t p_cds_context = NULL;
15837 hdd_context_t *pHddCtx;
15838 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015839 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015840
15841 ENTER();
15842
Anurag Chouhan6d760662016-02-20 16:05:43 +053015843 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015844 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015845 return -EINVAL;
15846 }
15847
15848 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015849 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015850 return -EINVAL;
15851 }
15852
15853 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15854 status = wlan_hdd_validate_context(pHddCtx);
15855
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015856 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015857 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015858
15859 p_cds_context = pHddCtx->pcds_context;
15860 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15861
15862 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015863 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015864 return -EINVAL;
15865 }
15866
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015867 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015868 params->n_acl_entries);
15869
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015870 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015871 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15872 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015873 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015874 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15875
15876 /* default value */
15877 pConfig->num_accept_mac = 0;
15878 pConfig->num_deny_mac = 0;
15879
15880 /**
15881 * access control policy
15882 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15883 * listed in hostapd.deny file.
15884 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15885 * listed in hostapd.accept file.
15886 */
15887 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15888 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15889 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15890 params->acl_policy) {
15891 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15892 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015893 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894 params->acl_policy);
15895 return -ENOTSUPP;
15896 }
15897
15898 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15899 pConfig->num_accept_mac = params->n_acl_entries;
15900 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015901 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15902 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015903 MAC_ADDR_ARRAY(
15904 params->mac_addrs[i].addr));
15905
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015906 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907 params->mac_addrs[i].addr,
15908 sizeof(qcmacaddr));
15909 }
15910 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15911 pConfig->num_deny_mac = params->n_acl_entries;
15912 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015913 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15914 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015915 MAC_ADDR_ARRAY(
15916 params->mac_addrs[i].addr));
15917
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015918 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015919 params->mac_addrs[i].addr,
15920 sizeof(qcmacaddr));
15921 }
15922 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015923 qdf_status = wlansap_set_mac_acl(
15924 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015925 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015926 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927 return -EINVAL;
15928 }
15929 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015930 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015931 hdd_device_mode_to_string(pAdapter->device_mode),
15932 pAdapter->device_mode);
15933 return -EINVAL;
15934 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015935 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015936 return 0;
15937}
15938
15939/**
15940 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15941 * __wlan_hdd_cfg80211_set_mac_acl
15942 * @wiphy: pointer to wiphy structure
15943 * @dev: pointer to net_device
15944 * @params: pointer to cfg80211_acl_data
15945 *
15946 * Return; 0 on success, error number otherwise
15947 */
15948static int
15949wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15950 struct net_device *dev,
15951 const struct cfg80211_acl_data *params)
15952{
15953 int ret;
15954
15955 cds_ssr_protect(__func__);
15956 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15957 cds_ssr_unprotect(__func__);
15958
15959 return ret;
15960}
15961
15962#ifdef WLAN_NL80211_TESTMODE
15963#ifdef FEATURE_WLAN_LPHB
15964/**
15965 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15966 * @pHddCtx: Pointer to hdd context
15967 * @lphbInd: Pointer to low power heart beat indication parameter
15968 *
15969 * Return: none
15970 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015971static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15972 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015973{
15974 struct sk_buff *skb;
15975
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015976 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015978 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015979 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015980
15981 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015982 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015983 return;
15984 }
15985
15986 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15987 wiphy, sizeof(tSirLPHBInd),
15988 GFP_ATOMIC);
15989 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015990 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015991 return;
15992 }
15993
15994 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015995 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015996 goto nla_put_failure;
15997 }
15998 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015999 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016000 goto nla_put_failure;
16001 }
16002 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016003 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016004 goto nla_put_failure;
16005 }
16006 cfg80211_testmode_event(skb, GFP_ATOMIC);
16007 return;
16008
16009nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016010 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016011 kfree_skb(skb);
16012
16013 return;
16014}
16015#endif /* FEATURE_WLAN_LPHB */
16016
16017/**
16018 * __wlan_hdd_cfg80211_testmode() - test mode
16019 * @wiphy: Pointer to wiphy
16020 * @data: Data pointer
16021 * @len: Data length
16022 *
16023 * Return: 0 for success, non-zero for failure
16024 */
16025static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16026 void *data, int len)
16027{
16028 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16029 int err;
16030 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16031
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016032 ENTER();
16033
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016034 err = wlan_hdd_validate_context(pHddCtx);
16035 if (err)
16036 return err;
16037
16038 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16039 len, wlan_hdd_tm_policy);
16040 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016041 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016042 return err;
16043 }
16044
16045 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016046 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016047 return -EINVAL;
16048 }
16049
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016050 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016051 TRACE_CODE_HDD_CFG80211_TESTMODE,
16052 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016053 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16054#ifdef FEATURE_WLAN_LPHB
16055 /* Low Power Heartbeat configuration request */
16056 case WLAN_HDD_TM_CMD_WLAN_HB:
16057 {
16058 int buf_len;
16059 void *buf;
16060 tSirLPHBReq *hb_params = NULL;
16061 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016062 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016063
16064 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016065 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016066 return -EINVAL;
16067 }
16068
16069 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16070 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16071
16072 hb_params_temp = (tSirLPHBReq *) buf;
16073 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16074 && (hb_params_temp->params.lphbTcpParamReq.
16075 timePeriodSec == 0))
16076 return -EINVAL;
16077
16078 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016079 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016081 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016082 return -ENOMEM;
16083 }
16084
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016085 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016086 smeStatus =
16087 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16088 hb_params,
16089 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016090 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016091 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016092 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016093 }
16094 return 0;
16095 }
16096#endif /* FEATURE_WLAN_LPHB */
16097
16098#if defined(QCA_WIFI_FTM)
16099 case WLAN_HDD_TM_CMD_WLAN_FTM:
16100 {
16101 int buf_len;
16102 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016103 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016104 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016105 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016106 return -EINVAL;
16107 }
16108
16109 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16110 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16111
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016112 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016113
16114 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16115
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016116 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016117 err = -EBUSY;
16118 break;
16119 }
16120#endif
16121
16122 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016123 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016124 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16125 return -EOPNOTSUPP;
16126 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016127 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016128 return err;
16129}
16130
16131/**
16132 * wlan_hdd_cfg80211_testmode() - test mode
16133 * @wiphy: Pointer to wiphy
16134 * @dev: Pointer to network device
16135 * @data: Data pointer
16136 * @len: Data length
16137 *
16138 * Return: 0 for success, non-zero for failure
16139 */
16140static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16141#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16142 struct wireless_dev *wdev,
16143#endif
16144 void *data, int len)
16145{
16146 int ret;
16147
16148 cds_ssr_protect(__func__);
16149 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16150 cds_ssr_unprotect(__func__);
16151
16152 return ret;
16153}
16154
16155#if defined(QCA_WIFI_FTM)
16156/**
16157 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16158 * @buf: Pointer to buffer
16159 * @buf_len: Buffer length
16160 *
16161 * Return: none
16162 */
16163void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16164{
16165 struct sk_buff *skb;
16166 hdd_context_t *hdd_ctx;
16167
16168 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016169 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016170 return;
16171 }
16172
Anurag Chouhan6d760662016-02-20 16:05:43 +053016173 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016175 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176 return;
16177 }
16178
16179 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16180 buf_len, GFP_KERNEL);
16181 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016182 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016183 return;
16184 }
16185
16186 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16187 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16188 goto nla_put_failure;
16189
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016190 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016191
16192 cfg80211_testmode_event(skb, GFP_KERNEL);
16193 return;
16194
16195nla_put_failure:
16196 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016197 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016198}
16199#endif
16200#endif /* CONFIG_NL80211_TESTMODE */
16201
16202#ifdef QCA_HT_2040_COEX
16203/**
16204 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16205 * @wiphy: Pointer to wiphy
16206 * @dev: Pointer to network device
16207 * @chandef: Pointer to channel definition parameter
16208 *
16209 * Return: 0 for success, non-zero for failure
16210 */
16211static int
16212__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16213 struct net_device *dev,
16214 struct cfg80211_chan_def *chandef)
16215{
16216 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16217 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016218 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016219 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016220 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016221
Anurag Chouhan6d760662016-02-20 16:05:43 +053016222 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016223 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016224 return -EINVAL;
16225 }
16226
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016227 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16228 hdd_err("invalid session id: %d", pAdapter->sessionId);
16229 return -EINVAL;
16230 }
16231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016232 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16233 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016234 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016237 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016238 sme_get_config_param(pHddCtx->hHal, &sme_config);
16239 switch (chandef->width) {
16240 case NL80211_CHAN_WIDTH_20:
16241 if (sme_config.csrConfig.channelBondingMode24GHz !=
16242 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16243 sme_config.csrConfig.channelBondingMode24GHz =
16244 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16245 sme_update_config(pHddCtx->hHal, &sme_config);
16246 cbModeChange = true;
16247 }
16248 break;
16249
16250 case NL80211_CHAN_WIDTH_40:
16251 if (sme_config.csrConfig.channelBondingMode24GHz ==
16252 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16253 if (NL80211_CHAN_HT40MINUS ==
16254 cfg80211_get_chandef_type(chandef))
16255 sme_config.csrConfig.channelBondingMode24GHz =
16256 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16257 else
16258 sme_config.csrConfig.channelBondingMode24GHz =
16259 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16260 sme_update_config(pHddCtx->hHal, &sme_config);
16261 cbModeChange = true;
16262 }
16263 break;
16264
16265 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016266 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016267 return -EINVAL;
16268 }
16269
16270 if (!cbModeChange)
16271 return 0;
16272
Krunal Sonib4326f22016-03-10 13:05:51 -080016273 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016274 return 0;
16275
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016276 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016277 sme_config.csrConfig.channelBondingMode24GHz);
16278
16279 /* Change SAP ht2040 mode */
16280 status = hdd_set_sap_ht2040_mode(pAdapter,
16281 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016282 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016283 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016284 return -EINVAL;
16285 }
16286
16287 return 0;
16288}
16289
16290/**
16291 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16292 * @wiphy: Pointer to wiphy
16293 * @dev: Pointer to network device
16294 * @chandef: Pointer to channel definition parameter
16295 *
16296 * Return: 0 for success, non-zero for failure
16297 */
16298static int
16299wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16300 struct net_device *dev,
16301 struct cfg80211_chan_def *chandef)
16302{
16303 int ret;
16304
16305 cds_ssr_protect(__func__);
16306 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16307 cds_ssr_unprotect(__func__);
16308
16309 return ret;
16310}
16311#endif
16312
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016313#ifdef CHANNEL_SWITCH_SUPPORTED
16314/**
16315 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16316 * channel in SAP/GO
16317 * @wiphy: wiphy pointer
16318 * @dev: dev pointer.
16319 * @csa_params: Change channel params
16320 *
16321 * This function is called to switch channel in SAP/GO
16322 *
16323 * Return: 0 if success else return non zero
16324 */
16325static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16326 struct net_device *dev,
16327 struct cfg80211_csa_settings *csa_params)
16328{
16329 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16330 hdd_context_t *hdd_ctx;
16331 uint8_t channel;
16332 uint16_t freq;
16333 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016334 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016335
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016336 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016337 csa_params->chandef.chan->center_freq);
16338
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016339 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16340 hdd_err("invalid session id: %d", adapter->sessionId);
16341 return -EINVAL;
16342 }
16343
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016344 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16345 ret = wlan_hdd_validate_context(hdd_ctx);
16346
16347 if (0 != ret)
16348 return ret;
16349
Krunal Sonib4326f22016-03-10 13:05:51 -080016350 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16351 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016352 return -ENOTSUPP;
16353
16354 freq = csa_params->chandef.chan->center_freq;
16355 channel = cds_freq_to_chan(freq);
16356
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016357 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16358
16359 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016360 return ret;
16361}
16362
16363/**
16364 * wlan_hdd_cfg80211_channel_switch()- function to switch
16365 * channel in SAP/GO
16366 * @wiphy: wiphy pointer
16367 * @dev: dev pointer.
16368 * @csa_params: Change channel params
16369 *
16370 * This function is called to switch channel in SAP/GO
16371 *
16372 * Return: 0 if success else return non zero
16373 */
16374static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16375 struct net_device *dev,
16376 struct cfg80211_csa_settings *csa_params)
16377{
16378 int ret;
16379
16380 cds_ssr_protect(__func__);
16381 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16382 cds_ssr_unprotect(__func__);
16383 return ret;
16384}
16385#endif
16386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016387/**
16388 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16389 * translation from NL to policy manager type
16390 * @type: Generic connection mode type defined in NL
16391 *
16392 *
16393 * This function provides the type translation
16394 *
16395 * Return: cds_con_mode enum
16396 */
16397enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16398 enum nl80211_iftype type)
16399{
16400 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16401 switch (type) {
16402 case NL80211_IFTYPE_STATION:
16403 mode = CDS_STA_MODE;
16404 break;
16405 case NL80211_IFTYPE_P2P_CLIENT:
16406 mode = CDS_P2P_CLIENT_MODE;
16407 break;
16408 case NL80211_IFTYPE_P2P_GO:
16409 mode = CDS_P2P_GO_MODE;
16410 break;
16411 case NL80211_IFTYPE_AP:
16412 mode = CDS_SAP_MODE;
16413 break;
16414 case NL80211_IFTYPE_ADHOC:
16415 mode = CDS_IBSS_MODE;
16416 break;
16417 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016418 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016419 type);
16420 }
16421 return mode;
16422}
16423
16424/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016425 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16426 * @wiphy: Handle to struct wiphy to get handle to module context.
16427 * @chandef: Contains information about the capture channel to be set.
16428 *
16429 * This interface is called if and only if monitor mode interface alone is
16430 * active.
16431 *
16432 * Return: 0 success or error code on failure.
16433 */
16434static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16435 struct cfg80211_chan_def *chandef)
16436{
16437 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16438 hdd_adapter_t *adapter;
16439 hdd_station_ctx_t *sta_ctx;
16440 struct hdd_mon_set_ch_info *ch_info;
16441 QDF_STATUS status;
16442 tHalHandle hal_hdl;
16443 struct qdf_mac_addr bssid;
16444 tCsrRoamProfile roam_profile;
16445 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016446 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016447 int ret;
16448 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16449
16450 ENTER();
16451
16452 ret = wlan_hdd_validate_context(hdd_ctx);
16453 if (ret)
16454 return ret;
16455
16456 hal_hdl = hdd_ctx->hHal;
16457
16458 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16459 if (!adapter)
16460 return -EIO;
16461
16462 hdd_info("%s: set monitor mode Channel %d and freq %d",
16463 adapter->dev->name, chan_num, chandef->chan->center_freq);
16464
16465 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16466 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016467 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16468 roam_profile.ChannelInfo.numOfChannels = 1;
16469 roam_profile.phyMode = ch_info->phy_mode;
16470 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016471 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016472
16473 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16474 QDF_MAC_ADDR_SIZE);
16475
16476 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016477 /*
16478 * CDS api expects secondary channel for calculating
16479 * the channel params
16480 */
16481 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16482 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16483 if (chan_num >= 1 && chan_num <= 5)
16484 sec_ch = chan_num + 4;
16485 else if (chan_num >= 6 && chan_num <= 13)
16486 sec_ch = chan_num - 4;
16487 }
16488 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016489 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16490 &roam_profile);
16491 if (status) {
16492 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16493 status);
16494 ret = qdf_status_to_os_return(status);
16495 return ret;
16496 }
16497 EXIT();
16498 return 0;
16499}
16500
16501/**
16502 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16503 * @wiphy: Handle to struct wiphy to get handle to module context.
16504 * @chandef: Contains information about the capture channel to be set.
16505 *
16506 * This interface is called if and only if monitor mode interface alone is
16507 * active.
16508 *
16509 * Return: 0 success or error code on failure.
16510 */
16511static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16512 struct cfg80211_chan_def *chandef)
16513{
16514 int ret;
16515
16516 cds_ssr_protect(__func__);
16517 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16518 cds_ssr_unprotect(__func__);
16519 return ret;
16520}
16521
16522/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016523 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16524 * @adapter: pointer to adapter
16525 *
16526 * Wrapper function to clear link layer stats.
16527 * return - void
16528 */
16529void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16530{
16531 tSirLLStatsClearReq link_layer_stats_clear_req;
16532 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16533
Mukul Sharma491021c2016-09-29 21:39:19 +053016534 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16535 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016536 link_layer_stats_clear_req.stopReq = 0;
16537 link_layer_stats_clear_req.reqId = 1;
16538 link_layer_stats_clear_req.staId = adapter->sessionId;
16539 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16540
16541 return;
16542}
16543
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016544#define CNT_DIFF(cur, prev) \
16545 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16546#define MAX_COUNT 0xffffffff
16547static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16548 struct scan_chan_info *chan,
16549 struct scan_chan_info *info, uint32_t cmd_flag)
16550{
16551 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16552 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16553 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16554
16555 mutex_lock(&hdd_ctx->chan_info_lock);
16556
16557 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16558 qdf_mem_zero(chan, sizeof(*chan));
16559
16560 chan->freq = info->freq;
16561 chan->noise_floor = info->noise_floor;
16562 chan->clock_freq = info->clock_freq;
16563 chan->cmd_flag = info->cmd_flag;
16564 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16565
16566 chan->rx_clear_count =
16567 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16568
16569 chan->tx_frame_count =
16570 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16571
16572 mutex_unlock(&hdd_ctx->chan_info_lock);
16573
16574}
16575#undef CNT_DIFF
16576#undef MAX_COUNT
16577
16578/**
16579 * wlan_hdd_chan_info_cb() - channel info callback
16580 * @chan_info: struct scan_chan_info
16581 *
16582 * Store channel info into HDD context
16583 *
16584 * Return: None.
16585 */
16586static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16587{
16588 hdd_context_t *hdd_ctx;
16589 struct scan_chan_info *chan;
16590 uint8_t idx;
16591
16592 ENTER();
16593
16594 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16595 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16596 hdd_err("hdd_ctx is invalid");
16597 return;
16598 }
16599
16600 if (!hdd_ctx->chan_info) {
16601 hdd_err("chan_info is NULL");
16602 return;
16603 }
16604
16605 chan = hdd_ctx->chan_info;
16606 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16607 if (chan[idx].freq == info->freq) {
16608 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16609 info->cmd_flag);
16610 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16611 chan[idx].cmd_flag, chan[idx].freq,
16612 chan[idx].noise_floor,
16613 chan[idx].cycle_count, chan[idx].rx_clear_count,
16614 chan[idx].clock_freq, chan[idx].cmd_flag,
16615 chan[idx].tx_frame_count, idx);
16616 if (chan[idx].freq == 0)
16617 break;
16618
16619 }
16620 }
16621
16622 EXIT();
16623}
16624
16625/**
16626 * wlan_hdd_init_chan_info() - init chan info in hdd context
16627 * @hdd_ctx: HDD context pointer
16628 *
16629 * Return: none
16630 */
16631void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16632{
16633 uint8_t num_2g, num_5g, index = 0;
16634
16635 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16636 hdd_info("SNR monitoring is disabled");
16637 return;
16638 }
16639
16640 hdd_ctx->chan_info =
16641 qdf_mem_malloc(sizeof(struct scan_chan_info)
16642 * QDF_MAX_NUM_CHAN);
16643 if (hdd_ctx->chan_info == NULL) {
16644 hdd_err("Failed to malloc for chan info");
16645 return;
16646 }
16647 mutex_init(&hdd_ctx->chan_info_lock);
16648
16649 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16650 for (; index < num_2g; index++) {
16651 hdd_ctx->chan_info[index].freq =
16652 hdd_channels_2_4_ghz[index].center_freq;
16653 }
16654
16655 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16656 for (; (index - num_2g) < num_5g; index++) {
16657 if (cds_is_dsrc_channel(
16658 hdd_channels_5_ghz[index - num_2g].center_freq))
16659 continue;
16660 hdd_ctx->chan_info[index].freq =
16661 hdd_channels_5_ghz[index - num_2g].center_freq;
16662 }
16663 sme_set_chan_info_callback(hdd_ctx->hHal,
16664 &wlan_hdd_chan_info_cb);
16665}
16666
16667/**
16668 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16669 * @hdd_ctx: hdd context pointer
16670 *
16671 * Return: none
16672 */
16673void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16674{
16675 struct scan_chan_info *chan;
16676
16677 chan = hdd_ctx->chan_info;
16678 hdd_ctx->chan_info = NULL;
16679 if (chan)
16680 qdf_mem_free(chan);
16681}
16682
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016683/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016684 * struct cfg80211_ops - cfg80211_ops
16685 *
16686 * @add_virtual_intf: Add virtual interface
16687 * @del_virtual_intf: Delete virtual interface
16688 * @change_virtual_intf: Change virtual interface
16689 * @change_station: Change station
16690 * @add_beacon: Add beacon in sap mode
16691 * @del_beacon: Delete beacon in sap mode
16692 * @set_beacon: Set beacon in sap mode
16693 * @start_ap: Start ap
16694 * @change_beacon: Change beacon
16695 * @stop_ap: Stop ap
16696 * @change_bss: Change bss
16697 * @add_key: Add key
16698 * @get_key: Get key
16699 * @del_key: Delete key
16700 * @set_default_key: Set default key
16701 * @set_channel: Set channel
16702 * @scan: Scan
16703 * @connect: Connect
16704 * @disconnect: Disconnect
16705 * @join_ibss = Join ibss
16706 * @leave_ibss = Leave ibss
16707 * @set_wiphy_params = Set wiphy params
16708 * @set_tx_power = Set tx power
16709 * @get_tx_power = get tx power
16710 * @remain_on_channel = Remain on channel
16711 * @cancel_remain_on_channel = Cancel remain on channel
16712 * @mgmt_tx = Tx management frame
16713 * @mgmt_tx_cancel_wait = Cancel management tx wait
16714 * @set_default_mgmt_key = Set default management key
16715 * @set_txq_params = Set tx queue parameters
16716 * @get_station = Get station
16717 * @set_power_mgmt = Set power management
16718 * @del_station = Delete station
16719 * @add_station = Add station
16720 * @set_pmksa = Set pmksa
16721 * @del_pmksa = Delete pmksa
16722 * @flush_pmksa = Flush pmksa
16723 * @update_ft_ies = Update FT IEs
16724 * @tdls_mgmt = Tdls management
16725 * @tdls_oper = Tdls operation
16726 * @set_rekey_data = Set rekey data
16727 * @sched_scan_start = Scheduled scan start
16728 * @sched_scan_stop = Scheduled scan stop
16729 * @resume = Resume wlan
16730 * @suspend = Suspend wlan
16731 * @set_mac_acl = Set mac acl
16732 * @testmode_cmd = Test mode command
16733 * @set_ap_chanwidth = Set AP channel bandwidth
16734 * @dump_survey = Dump survey
16735 * @key_mgmt_set_pmk = Set pmk key management
16736 */
16737static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16738 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16739 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16740 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16741 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016742 .start_ap = wlan_hdd_cfg80211_start_ap,
16743 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16744 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016745 .change_bss = wlan_hdd_cfg80211_change_bss,
16746 .add_key = wlan_hdd_cfg80211_add_key,
16747 .get_key = wlan_hdd_cfg80211_get_key,
16748 .del_key = wlan_hdd_cfg80211_del_key,
16749 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16750 .scan = wlan_hdd_cfg80211_scan,
16751 .connect = wlan_hdd_cfg80211_connect,
16752 .disconnect = wlan_hdd_cfg80211_disconnect,
16753 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16754 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16755 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16756 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16757 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16758 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16759 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16760 .mgmt_tx = wlan_hdd_mgmt_tx,
16761 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16762 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16763 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016764 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016765 .get_station = wlan_hdd_cfg80211_get_station,
16766 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16767 .del_station = wlan_hdd_cfg80211_del_station,
16768 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016769 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16770 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16771 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016772#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016773 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16774#endif
16775#ifdef FEATURE_WLAN_TDLS
16776 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16777 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16778#endif
16779#ifdef WLAN_FEATURE_GTK_OFFLOAD
16780 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16781#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16782#ifdef FEATURE_WLAN_SCAN_PNO
16783 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16784 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16785#endif /*FEATURE_WLAN_SCAN_PNO */
16786 .resume = wlan_hdd_cfg80211_resume_wlan,
16787 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16788 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16789#ifdef WLAN_NL80211_TESTMODE
16790 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16791#endif
16792#ifdef QCA_HT_2040_COEX
16793 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16794#endif
16795 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016796#ifdef CHANNEL_SWITCH_SUPPORTED
16797 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16798#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016799 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016800#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16801 defined(CFG80211_ABORT_SCAN)
16802 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16803#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016804};