blob: 9eb174eb3139acb2031e8e8f89e5b1208e981015 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
Ravi Joshideb5a8d2015-11-09 19:11:43 -080096#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053097#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070098#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070099#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530100#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800101
Leo Changfdb45c32016-10-28 11:09:23 -0700102#include <cdp_txrx_cmn.h>
103#include <cdp_txrx_misc.h>
104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define g_mode_rates_size (12)
106#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
108 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
109
110/*
111 * Android CTS verifier needs atleast this much wait time (in msec)
112 */
113#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
114
115/*
116 * Refer @tCfgProtection structure for definition of the bit map.
117 * below value is obtained by setting the following bit-fields.
118 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
119 */
120#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
121
122#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700123 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 .center_freq = (freq), \
125 .hw_value = (chan), \
126 .flags = (flag), \
127 .max_antenna_gain = 0, \
128 .max_power = 30, \
129}
130
131#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
137 .max_power = 30, \
138}
139
140#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
141 { \
142 .bitrate = rate, \
143 .hw_value = rate_id, \
144 .flags = flag, \
145 }
146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
148#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
150#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
Agrawal Ashish65634612016-08-18 13:24:32 +0530152#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
153 mode <= DFS_MODE_DEPRIORITIZE))
154#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
155 || (channel >= 36 && channel <= 184))
156
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530158#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160static const u32 hdd_cipher_suites[] = {
161 WLAN_CIPHER_SUITE_WEP40,
162 WLAN_CIPHER_SUITE_WEP104,
163 WLAN_CIPHER_SUITE_TKIP,
164#ifdef FEATURE_WLAN_ESE
165#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
166#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
167 WLAN_CIPHER_SUITE_BTK,
168 WLAN_CIPHER_SUITE_KRK,
169 WLAN_CIPHER_SUITE_CCMP,
170#else
171 WLAN_CIPHER_SUITE_CCMP,
172#endif
173#ifdef FEATURE_WLAN_WAPI
174 WLAN_CIPHER_SUITE_SMS4,
175#endif
176#ifdef WLAN_FEATURE_11W
177 WLAN_CIPHER_SUITE_AES_CMAC,
178#endif
179};
180
Abhishek Singhf512bf32016-05-04 16:47:46 +0530181static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 HDD2GHZCHAN(2412, 1, 0),
183 HDD2GHZCHAN(2417, 2, 0),
184 HDD2GHZCHAN(2422, 3, 0),
185 HDD2GHZCHAN(2427, 4, 0),
186 HDD2GHZCHAN(2432, 5, 0),
187 HDD2GHZCHAN(2437, 6, 0),
188 HDD2GHZCHAN(2442, 7, 0),
189 HDD2GHZCHAN(2447, 8, 0),
190 HDD2GHZCHAN(2452, 9, 0),
191 HDD2GHZCHAN(2457, 10, 0),
192 HDD2GHZCHAN(2462, 11, 0),
193 HDD2GHZCHAN(2467, 12, 0),
194 HDD2GHZCHAN(2472, 13, 0),
195 HDD2GHZCHAN(2484, 14, 0),
196};
197
Abhishek Singhf512bf32016-05-04 16:47:46 +0530198static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 HDD5GHZCHAN(5180, 36, 0),
200 HDD5GHZCHAN(5200, 40, 0),
201 HDD5GHZCHAN(5220, 44, 0),
202 HDD5GHZCHAN(5240, 48, 0),
203 HDD5GHZCHAN(5260, 52, 0),
204 HDD5GHZCHAN(5280, 56, 0),
205 HDD5GHZCHAN(5300, 60, 0),
206 HDD5GHZCHAN(5320, 64, 0),
207 HDD5GHZCHAN(5500, 100, 0),
208 HDD5GHZCHAN(5520, 104, 0),
209 HDD5GHZCHAN(5540, 108, 0),
210 HDD5GHZCHAN(5560, 112, 0),
211 HDD5GHZCHAN(5580, 116, 0),
212 HDD5GHZCHAN(5600, 120, 0),
213 HDD5GHZCHAN(5620, 124, 0),
214 HDD5GHZCHAN(5640, 128, 0),
215 HDD5GHZCHAN(5660, 132, 0),
216 HDD5GHZCHAN(5680, 136, 0),
217 HDD5GHZCHAN(5700, 140, 0),
218 HDD5GHZCHAN(5720, 144, 0),
219 HDD5GHZCHAN(5745, 149, 0),
220 HDD5GHZCHAN(5765, 153, 0),
221 HDD5GHZCHAN(5785, 157, 0),
222 HDD5GHZCHAN(5805, 161, 0),
223 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 HDD5GHZCHAN(5852, 170, 0),
225 HDD5GHZCHAN(5855, 171, 0),
226 HDD5GHZCHAN(5860, 172, 0),
227 HDD5GHZCHAN(5865, 173, 0),
228 HDD5GHZCHAN(5870, 174, 0),
229 HDD5GHZCHAN(5875, 175, 0),
230 HDD5GHZCHAN(5880, 176, 0),
231 HDD5GHZCHAN(5885, 177, 0),
232 HDD5GHZCHAN(5890, 178, 0),
233 HDD5GHZCHAN(5895, 179, 0),
234 HDD5GHZCHAN(5900, 180, 0),
235 HDD5GHZCHAN(5905, 181, 0),
236 HDD5GHZCHAN(5910, 182, 0),
237 HDD5GHZCHAN(5915, 183, 0),
238 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239};
240
241static struct ieee80211_rate g_mode_rates[] = {
242 HDD_G_MODE_RATETAB(10, 0x1, 0),
243 HDD_G_MODE_RATETAB(20, 0x2, 0),
244 HDD_G_MODE_RATETAB(55, 0x4, 0),
245 HDD_G_MODE_RATETAB(110, 0x8, 0),
246 HDD_G_MODE_RATETAB(60, 0x10, 0),
247 HDD_G_MODE_RATETAB(90, 0x20, 0),
248 HDD_G_MODE_RATETAB(120, 0x40, 0),
249 HDD_G_MODE_RATETAB(180, 0x80, 0),
250 HDD_G_MODE_RATETAB(240, 0x100, 0),
251 HDD_G_MODE_RATETAB(360, 0x200, 0),
252 HDD_G_MODE_RATETAB(480, 0x400, 0),
253 HDD_G_MODE_RATETAB(540, 0x800, 0),
254};
255
256static struct ieee80211_rate a_mode_rates[] = {
257 HDD_G_MODE_RATETAB(60, 0x10, 0),
258 HDD_G_MODE_RATETAB(90, 0x20, 0),
259 HDD_G_MODE_RATETAB(120, 0x40, 0),
260 HDD_G_MODE_RATETAB(180, 0x80, 0),
261 HDD_G_MODE_RATETAB(240, 0x100, 0),
262 HDD_G_MODE_RATETAB(360, 0x200, 0),
263 HDD_G_MODE_RATETAB(480, 0x400, 0),
264 HDD_G_MODE_RATETAB(540, 0x800, 0),
265};
266
267static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530268 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700270 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
278 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
279 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
280 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
281 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
282 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
283 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
284};
285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530287 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700289 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290 .bitrates = a_mode_rates,
291 .n_bitrates = a_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
297 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
298 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
299 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
300 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
301 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
302 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
303 .vht_cap.vht_supported = 1,
304};
305
306/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800307 * TX/RX direction for each kind of interface
308 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309static const struct ieee80211_txrx_stypes
310 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
311 [NL80211_IFTYPE_STATION] = {
312 .tx = 0xffff,
313 .rx = BIT(SIR_MAC_MGMT_ACTION) |
314 BIT(SIR_MAC_MGMT_PROBE_REQ),
315 },
316 [NL80211_IFTYPE_AP] = {
317 .tx = 0xffff,
318 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
319 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_PROBE_REQ) |
321 BIT(SIR_MAC_MGMT_DISASSOC) |
322 BIT(SIR_MAC_MGMT_AUTH) |
323 BIT(SIR_MAC_MGMT_DEAUTH) |
324 BIT(SIR_MAC_MGMT_ACTION),
325 },
326 [NL80211_IFTYPE_ADHOC] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_P2P_CLIENT] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ACTION) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ),
340 },
341 [NL80211_IFTYPE_P2P_GO] = {
342 /* This is also same as for SoftAP */
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ) |
347 BIT(SIR_MAC_MGMT_DISASSOC) |
348 BIT(SIR_MAC_MGMT_AUTH) |
349 BIT(SIR_MAC_MGMT_DEAUTH) |
350 BIT(SIR_MAC_MGMT_ACTION),
351 },
352};
353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354/* Interface limits and combinations registered by the driver */
355
356/* STA ( + STA ) combination */
357static const struct ieee80211_iface_limit
358 wlan_hdd_sta_iface_limit[] = {
359 {
360 .max = 3, /* p2p0 is a STA as well */
361 .types = BIT(NL80211_IFTYPE_STATION),
362 },
363};
364
365/* ADHOC (IBSS) limit */
366static const struct ieee80211_iface_limit
367 wlan_hdd_adhoc_iface_limit[] = {
368 {
369 .max = 1,
370 .types = BIT(NL80211_IFTYPE_STATION),
371 },
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_ADHOC),
375 },
376};
377
378/* AP ( + AP ) combination */
379static const struct ieee80211_iface_limit
380 wlan_hdd_ap_iface_limit[] = {
381 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530382 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 .types = BIT(NL80211_IFTYPE_AP),
384 },
385};
386
387/* P2P limit */
388static const struct ieee80211_iface_limit
389 wlan_hdd_p2p_iface_limit[] = {
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
393 },
394 {
395 .max = 1,
396 .types = BIT(NL80211_IFTYPE_P2P_GO),
397 },
398};
399
400static const struct ieee80211_iface_limit
401 wlan_hdd_sta_ap_iface_limit[] = {
402 {
403 /* We need 1 extra STA interface for OBSS scan when SAP starts
404 * with HT40 in STA+SAP concurrency mode
405 */
406 .max = (1 + SAP_MAX_OBSS_STA_CNT),
407 .types = BIT(NL80211_IFTYPE_STATION),
408 },
409 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530410 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 .types = BIT(NL80211_IFTYPE_AP),
412 },
413};
414
415/* STA + P2P combination */
416static const struct ieee80211_iface_limit
417 wlan_hdd_sta_p2p_iface_limit[] = {
418 {
419 /* One reserved for dedicated P2PDEV usage */
420 .max = 2,
421 .types = BIT(NL80211_IFTYPE_STATION)
422 },
423 {
424 /* Support for two identical (GO + GO or CLI + CLI)
425 * or dissimilar (GO + CLI) P2P interfaces
426 */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
429 },
430};
431
432/* STA + AP + P2PGO combination */
433static const struct ieee80211_iface_limit
434wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
435 /* Support for AP+P2PGO interfaces */
436 {
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_STATION)
439 },
440 {
441 .max = 1,
442 .types = BIT(NL80211_IFTYPE_P2P_GO)
443 },
444 {
445 .max = 1,
446 .types = BIT(NL80211_IFTYPE_AP)
447 }
448};
449
450/* SAP + P2P combination */
451static const struct ieee80211_iface_limit
452wlan_hdd_sap_p2p_iface_limit[] = {
453 {
454 /* 1 dedicated for p2p0 which is a STA type */
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_STATION)
457 },
458 {
459 /* The p2p interface in SAP+P2P can be GO/CLI.
460 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
461 */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
464 },
465 {
466 /* SAP+GO to support only one SAP interface */
467 .max = 1,
468 .types = BIT(NL80211_IFTYPE_AP)
469 }
470};
471
472/* P2P + P2P combination */
473static const struct ieee80211_iface_limit
474wlan_hdd_p2p_p2p_iface_limit[] = {
475 {
476 /* 1 dedicated for p2p0 which is a STA type */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_STATION)
479 },
480 {
481 /* The p2p interface in P2P+P2P can be GO/CLI.
482 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
483 */
484 .max = 2,
485 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
486 },
487};
488
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700489static const struct ieee80211_iface_limit
490 wlan_hdd_mon_iface_limit[] = {
491 {
492 .max = 3, /* Monitor interface */
493 .types = BIT(NL80211_IFTYPE_MONITOR),
494 },
495};
496
497static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800498 wlan_hdd_iface_combination[] = {
499 /* STA */
500 {
501 .limits = wlan_hdd_sta_iface_limit,
502 .num_different_channels = 2,
503 .max_interfaces = 3,
504 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
505 },
506 /* ADHOC */
507 {
508 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700509 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 .max_interfaces = 2,
511 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
512 },
513 /* AP */
514 {
515 .limits = wlan_hdd_ap_iface_limit,
516 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530517 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
519 },
520 /* P2P */
521 {
522 .limits = wlan_hdd_p2p_iface_limit,
523 .num_different_channels = 2,
524 .max_interfaces = 2,
525 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
526 },
527 /* STA + AP */
528 {
529 .limits = wlan_hdd_sta_ap_iface_limit,
530 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
533 .beacon_int_infra_match = true,
534 },
535 /* STA + P2P */
536 {
537 .limits = wlan_hdd_sta_p2p_iface_limit,
538 .num_different_channels = 2,
539 /* one interface reserved for P2PDEV dedicated usage */
540 .max_interfaces = 4,
541 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
542 .beacon_int_infra_match = true,
543 },
544 /* STA + P2P GO + SAP */
545 {
546 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
547 /* we can allow 3 channels for three different persona
548 * but due to firmware limitation, allow max 2 concrnt channels.
549 */
550 .num_different_channels = 2,
551 /* one interface reserved for P2PDEV dedicated usage */
552 .max_interfaces = 4,
553 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
554 .beacon_int_infra_match = true,
555 },
556 /* SAP + P2P */
557 {
558 .limits = wlan_hdd_sap_p2p_iface_limit,
559 .num_different_channels = 2,
560 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
561 .max_interfaces = 3,
562 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
563 .beacon_int_infra_match = true,
564 },
565 /* P2P + P2P */
566 {
567 .limits = wlan_hdd_p2p_p2p_iface_limit,
568 .num_different_channels = 2,
569 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
570 .max_interfaces = 3,
571 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
572 .beacon_int_infra_match = true,
573 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530574 /* Monitor */
575 {
576 .limits = wlan_hdd_mon_iface_limit,
577 .max_interfaces = 3,
578 .num_different_channels = 2,
579 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
580 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530584struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586#ifdef WLAN_NL80211_TESTMODE
587enum wlan_hdd_tm_attr {
588 WLAN_HDD_TM_ATTR_INVALID = 0,
589 WLAN_HDD_TM_ATTR_CMD = 1,
590 WLAN_HDD_TM_ATTR_DATA = 2,
591 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
592 WLAN_HDD_TM_ATTR_TYPE = 4,
593 /* keep last */
594 WLAN_HDD_TM_ATTR_AFTER_LAST,
595 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
596};
597
598enum wlan_hdd_tm_cmd {
599 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
600 WLAN_HDD_TM_CMD_WLAN_HB = 1,
601};
602
603#define WLAN_HDD_TM_DATA_MAX_LEN 5000
604
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530605enum wlan_hdd_vendor_ie_access_policy {
606 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
607 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
608};
609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
611 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
612 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
613 .len = WLAN_HDD_TM_DATA_MAX_LEN},
614};
615#endif /* WLAN_NL80211_TESTMODE */
616
617#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
618static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
619 .flags = WIPHY_WOWLAN_MAGIC_PKT,
620 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
621 .pattern_min_len = 1,
622 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
623};
624#endif
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530627 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
628 * @flags: Pointer to the flags to Add channel switch flag.
629 *
630 * This Function adds Channel Switch support flag, if channel switch is
631 * supported by kernel.
632 * Return: void.
633 */
634#ifdef CHANNEL_SWITCH_SUPPORTED
635static inline void hdd_add_channel_switch_support(uint32_t *flags)
636{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800637 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530638 return;
639}
640#else
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
643 return;
644}
645#endif
646
Manikandan Mohan22b83722015-12-15 15:03:23 -0800647#ifdef FEATURE_WLAN_TDLS
648
649/* TDLS capabilities params */
650#define PARAM_MAX_TDLS_SESSION \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
652#define PARAM_TDLS_FEATURE_SUPPORT \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
654
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
657 * @wiphy: WIPHY structure pointer
658 * @wdev: Wireless device structure pointer
659 * @data: Pointer to the data received
660 * @data_len: Length of the data received
661 *
662 * This function provides TDLS capabilities
663 *
664 * Return: 0 on success and errno on failure
665 */
666static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
667 struct wireless_dev *wdev,
668 const void *data,
669 int data_len)
670{
671 int status;
672 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
673 struct sk_buff *skb;
674 uint32_t set = 0;
675
Jeff Johnson1f61b612016-02-12 16:28:33 -0800676 ENTER_DEV(wdev->netdev);
677
Anurag Chouhan6d760662016-02-20 16:05:43 +0530678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 hdd_err("Command not allowed in FTM mode");
680 return -EPERM;
681 }
682
683 status = wlan_hdd_validate_context(hdd_ctx);
684 if (status)
685 return status;
686
687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
688 NLMSG_HDRLEN);
689 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700690 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 goto fail;
692 }
693
694 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
697 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701 } else {
702 set = set | WIFI_TDLS_SUPPORT;
703 set = set | (hdd_ctx->config->fTDLSExternalControl ?
704 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
705 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
706 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
709 hdd_ctx->max_num_tdls_sta) ||
710 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
711 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700712 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 goto fail;
714 }
715 }
716 return cfg80211_vendor_cmd_reply(skb);
717fail:
718 if (skb)
719 kfree_skb(skb);
720 return -EINVAL;
721}
722
723/**
724 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
725 * @wiphy: WIPHY structure pointer
726 * @wdev: Wireless device structure pointer
727 * @data: Pointer to the data received
728 * @data_len: Length of the data received
729 *
730 * This function provides TDLS capabilities
731 *
732 * Return: 0 on success and errno on failure
733 */
734static int
735wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
736 struct wireless_dev *wdev,
737 const void *data,
738 int data_len)
739{
740 int ret;
741
742 cds_ssr_protect(__func__);
743 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
744 data, data_len);
745 cds_ssr_unprotect(__func__);
746
747 return ret;
748}
749#endif
750
751#ifdef QCA_HT_2040_COEX
752static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
753#endif
754
755#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
756/*
757 * FUNCTION: wlan_hdd_send_avoid_freq_event
758 * This is called when wlan driver needs to send vendor specific
759 * avoid frequency range event to userspace
760 */
761int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
762 tHddAvoidFreqList *pAvoidFreqList)
763{
764 struct sk_buff *vendor_event;
765
766 ENTER();
767
768 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700769 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 return -EINVAL;
771 }
772
773 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700774 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return -EINVAL;
776 }
777
778 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
779 NULL,
780 sizeof(tHddAvoidFreqList),
781 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
782 GFP_KERNEL);
783 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700784 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 return -EINVAL;
786 }
787
788 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
789 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
790
791 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
792
793 EXIT();
794 return 0;
795}
796#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
797
798/* vendor specific events */
799static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
800#ifdef FEATURE_WLAN_CH_AVOID
801 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
806 },
807#endif /* FEATURE_WLAN_CH_AVOID */
808
809#ifdef WLAN_FEATURE_NAN
810 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_NAN
815 },
816#endif
817
818#ifdef WLAN_FEATURE_STATS_EXT
819 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
824 },
825#endif /* WLAN_FEATURE_STATS_EXT */
826#ifdef FEATURE_WLAN_EXTSCAN
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
832 },
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
840 .
841 vendor_id
842 =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .
853 subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd
863 =
864 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
865 },
866 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
867 .
868 vendor_id
869 =
870 QCA_NL80211_VENDOR_ID,
871 .subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
875 .vendor_id =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
881 .
882 vendor_id
883 =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .
912 subcmd =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd
922 =
923 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
924 },
925 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
926 .
927 vendor_id
928 =
929 QCA_NL80211_VENDOR_ID,
930 .
931 subcmd
932 =
933 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
938 },
939 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
940 .vendor_id = QCA_NL80211_VENDOR_ID,
941 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
942 },
943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
982#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
983 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
990 .vendor_id = QCA_NL80211_VENDOR_ID,
991 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
992 },
993#ifdef WLAN_FEATURE_ROAM_OFFLOAD
994 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
999 },
1000#endif
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1030 },
1031#ifdef FEATURE_WLAN_EXTSCAN
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1047 },
1048 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1051 },
1052#endif /* FEATURE_WLAN_EXTSCAN */
1053 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1056 },
1057#ifdef WLAN_FEATURE_MEMDUMP
1058 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1061 },
1062#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001063#ifdef WLAN_FEATURE_TSF
1064 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1067 },
1068#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1072 },
1073 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1076 },
1077 /* OCB events */
1078 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1081 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001082#ifdef FEATURE_LFR_SUBNET_DETECTION
1083 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1084 .vendor_id = QCA_NL80211_VENDOR_ID,
1085 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1086 },
1087#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001088
1089#ifdef WLAN_FEATURE_NAN_DATAPATH
1090 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1093 },
1094#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001095
1096 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1099 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301100 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1101 .vendor_id = QCA_NL80211_VENDOR_ID,
1102 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1103 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301104 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1105 .vendor_id = QCA_NL80211_VENDOR_ID,
1106 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1107 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001108#ifdef WLAN_UMAC_CONVERGENCE
1109 COMMON_VENDOR_EVENTS
1110#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111};
1112
1113/**
1114 * __is_driver_dfs_capable() - get driver DFS capability
1115 * @wiphy: pointer to wireless wiphy structure.
1116 * @wdev: pointer to wireless_dev structure.
1117 * @data: Pointer to the data to be passed via vendor interface
1118 * @data_len:Length of the data to be passed
1119 *
1120 * This function is called by userspace to indicate whether or not
1121 * the driver supports DFS offload.
1122 *
1123 * Return: 0 on success, negative errno on failure
1124 */
1125static int __is_driver_dfs_capable(struct wiphy *wiphy,
1126 struct wireless_dev *wdev,
1127 const void *data,
1128 int data_len)
1129{
1130 u32 dfs_capability = 0;
1131 struct sk_buff *temp_skbuff;
1132 int ret_val;
1133 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1134
Jeff Johnson1f61b612016-02-12 16:28:33 -08001135 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136
1137 ret_val = wlan_hdd_validate_context(hdd_ctx);
1138 if (ret_val)
1139 return ret_val;
1140
Anurag Chouhan6d760662016-02-20 16:05:43 +05301141 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 hdd_err("Command not allowed in FTM mode");
1143 return -EPERM;
1144 }
1145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147
1148 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1149 NLMSG_HDRLEN);
1150
1151 if (temp_skbuff != NULL) {
1152 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1153 dfs_capability);
1154 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001155 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 kfree_skb(temp_skbuff);
1157
1158 return ret_val;
1159 }
1160
1161 return cfg80211_vendor_cmd_reply(temp_skbuff);
1162 }
1163
Jeff Johnson020db452016-06-29 14:37:26 -07001164 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 return -ENOMEM;
1166}
1167
1168/**
1169 * is_driver_dfs_capable() - get driver DFS capability
1170 * @wiphy: pointer to wireless wiphy structure.
1171 * @wdev: pointer to wireless_dev structure.
1172 * @data: Pointer to the data to be passed via vendor interface
1173 * @data_len:Length of the data to be passed
1174 *
1175 * This function is called by userspace to indicate whether or not
1176 * the driver supports DFS offload. This is an SSR-protected
1177 * wrapper function.
1178 *
1179 * Return: 0 on success, negative errno on failure
1180 */
1181static int is_driver_dfs_capable(struct wiphy *wiphy,
1182 struct wireless_dev *wdev,
1183 const void *data,
1184 int data_len)
1185{
1186 int ret;
1187
1188 cds_ssr_protect(__func__);
1189 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1190 cds_ssr_unprotect(__func__);
1191
1192 return ret;
1193}
1194
1195/**
1196 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1197 *
1198 * @adapter: SAP adapter pointer
1199 *
1200 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1201 * radio. So in case of DFS MCC scenario override current SAP given config
1202 * to follow concurrent SAP DFS config
1203 *
1204 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1205 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1207{
1208 hdd_adapter_t *con_sap_adapter;
1209 tsap_Config_t *sap_config, *con_sap_config;
1210 int con_ch;
1211
1212 /*
1213 * Check if AP+AP case, once primary AP chooses a DFS
1214 * channel secondary AP should always follow primary APs channel
1215 */
1216 if (!cds_concurrent_beaconing_sessions_running())
1217 return 0;
1218
1219 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1220 if (!con_sap_adapter)
1221 return 0;
1222
1223 sap_config = &adapter->sessionCtx.ap.sapConfig;
1224 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1225 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1226
1227 if (!CDS_IS_DFS_CH(con_ch))
1228 return 0;
1229
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001232 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 sap_config->channel = con_ch;
1234
1235 if (con_sap_config->acs_cfg.acs_mode == true) {
1236 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1237 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001238 hdd_err("Primary AP channel config error");
1239 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 con_ch, con_sap_config->acs_cfg.pri_ch,
1241 con_sap_config->acs_cfg.ht_sec_ch);
1242 return -EINVAL;
1243 }
1244 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1245 * MCC restriction. So free ch list allocated in do_acs
1246 * func for Sec AP and realloc for Pri AP ch list size
1247 */
1248 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252 &con_sap_config->acs_cfg,
1253 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 sizeof(uint8_t) *
1256 con_sap_config->acs_cfg.ch_list_count);
1257 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001258 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 return -ENOMEM;
1260 }
1261
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301262 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 con_sap_config->acs_cfg.ch_list,
1264 con_sap_config->acs_cfg.ch_list_count);
1265
1266 } else {
1267 sap_config->acs_cfg.pri_ch = con_ch;
1268 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1269 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1270 }
1271
1272 return con_ch;
1273}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274
1275/**
1276 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1277 * @sap_cfg: pointer to SAP config struct
1278 *
1279 * This function sets the default ACS start and end channel for the given band
1280 * and also parses the given ACS channel list.
1281 *
1282 * Return: None
1283 */
1284
1285static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1286 bool vht_enabled)
1287{
1288 int i;
1289 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001303 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1304 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 }
1306
1307 if (ht_enabled)
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1309
1310 if (vht_enabled)
1311 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1312
1313
1314 /* Parse ACS Chan list from hostapd */
1315 if (!sap_cfg->acs_cfg.ch_list)
1316 return;
1317
1318 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1319 sap_cfg->acs_cfg.end_ch =
1320 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1321 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301322 /* avoid channel as start channel */
1323 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1324 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001325 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1326 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1327 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1328 }
1329}
1330
1331
1332static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1333
1334/**
1335 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1336 * @adapter: pointer to SAP adapter struct
1337 *
1338 * This function starts the ACS procedure if there are no
1339 * constraints like MBSSID DFS restrictions.
1340 *
1341 * Return: Status of ACS Start procedure
1342 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301343int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344{
1345
1346 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1347 tsap_Config_t *sap_config;
1348 tpWLAN_SAPEventCB acs_event_callback;
1349 int status;
1350
1351 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301352 if (hdd_ctx->acs_policy.acs_channel)
1353 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1354 else
1355 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356
1357 status = wlan_hdd_sap_cfg_dfs_override(adapter);
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,
3391 cdp_get_vdev_from_vdev_id(soc, pdev,
3392 adapter->sessionId),
3393 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003394err:
3395 EXIT();
3396 return ret_val;
3397}
3398
3399/**
3400 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3401 * @wiphy: corestack handler
3402 * @wdev: wireless device
3403 * @data: data
3404 * @data_len: data length
3405 *
3406 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3407 * setup WISA mode features.
3408 *
3409 * Return: Success(0) or reason code for failure
3410 */
3411static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3412 struct wireless_dev *wdev,
3413 const void *data,
3414 int data_len)
3415{
3416 int ret;
3417
3418 cds_ssr_protect(__func__);
3419 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3420 cds_ssr_unprotect(__func__);
3421
3422 return ret;
3423}
3424
Anurag Chouhan96919482016-07-13 16:36:57 +05303425/*
3426 * define short names for the global vendor params
3427 * used by __wlan_hdd_cfg80211_get_station_cmd()
3428 */
3429#define STATION_INVALID \
3430 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3431#define STATION_INFO \
3432 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3433#define STATION_ASSOC_FAIL_REASON \
3434 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3435#define STATION_MAX \
3436 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3437
3438static const struct nla_policy
3439hdd_get_station_policy[STATION_MAX + 1] = {
3440 [STATION_INFO] = {.type = NLA_FLAG},
3441 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3442};
3443
3444/**
3445 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3446 * @hdd_ctx: HDD context within host driver
3447 * @wdev: wireless device
3448 *
3449 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3450 * Validate cmd attributes and send the station info to upper layers.
3451 *
3452 * Return: Success(0) or reason code for failure
3453 */
3454static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3455 hdd_adapter_t *adapter)
3456{
3457 struct sk_buff *skb = NULL;
3458 uint32_t nl_buf_len;
3459 hdd_station_ctx_t *hdd_sta_ctx;
3460
3461 nl_buf_len = NLMSG_HDRLEN;
3462 nl_buf_len += sizeof(uint32_t);
3463 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3464
3465 if (!skb) {
3466 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3467 return -ENOMEM;
3468 }
3469
3470 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3471
3472 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3473 hdd_sta_ctx->conn_info.assoc_status_code)) {
3474 hdd_err("put fail");
3475 goto fail;
3476 }
3477 return cfg80211_vendor_cmd_reply(skb);
3478fail:
3479 if (skb)
3480 kfree_skb(skb);
3481 return -EINVAL;
3482}
3483
3484/**
3485 * hdd_map_auth_type() - transform auth type specific to
3486 * vendor command
3487 * @auth_type: csr auth type
3488 *
3489 * Return: Success(0) or reason code for failure
3490 */
3491static int hdd_convert_auth_type(uint32_t auth_type)
3492{
3493 uint32_t ret_val;
3494
3495 switch (auth_type) {
3496 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3497 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3498 break;
3499 case eCSR_AUTH_TYPE_SHARED_KEY:
3500 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3501 break;
3502 case eCSR_AUTH_TYPE_WPA:
3503 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3504 break;
3505 case eCSR_AUTH_TYPE_WPA_PSK:
3506 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3507 break;
3508 case eCSR_AUTH_TYPE_AUTOSWITCH:
3509 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3510 break;
3511 case eCSR_AUTH_TYPE_WPA_NONE:
3512 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3513 break;
3514 case eCSR_AUTH_TYPE_RSN:
3515 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3516 break;
3517 case eCSR_AUTH_TYPE_RSN_PSK:
3518 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3519 break;
3520 case eCSR_AUTH_TYPE_FT_RSN:
3521 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3522 break;
3523 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3524 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3525 break;
3526 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3527 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3528 break;
3529 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3530 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3531 break;
3532 case eCSR_AUTH_TYPE_CCKM_WPA:
3533 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3534 break;
3535 case eCSR_AUTH_TYPE_CCKM_RSN:
3536 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3537 break;
3538 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3539 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3540 break;
3541 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3542 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3543 break;
3544 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3545 case eCSR_AUTH_TYPE_FAILED:
3546 case eCSR_AUTH_TYPE_NONE:
3547 default:
3548 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3549 break;
3550 }
3551 return ret_val;
3552}
3553
3554/**
3555 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3556 * vendor command
3557 * @dot11mode: dot11mode
3558 *
3559 * Return: Success(0) or reason code for failure
3560 */
3561static int hdd_convert_dot11mode(uint32_t dot11mode)
3562{
3563 uint32_t ret_val;
3564
3565 switch (dot11mode) {
3566 case eCSR_CFG_DOT11_MODE_11A:
3567 ret_val = QCA_WLAN_802_11_MODE_11A;
3568 break;
3569 case eCSR_CFG_DOT11_MODE_11B:
3570 ret_val = QCA_WLAN_802_11_MODE_11B;
3571 break;
3572 case eCSR_CFG_DOT11_MODE_11G:
3573 ret_val = QCA_WLAN_802_11_MODE_11G;
3574 break;
3575 case eCSR_CFG_DOT11_MODE_11N:
3576 ret_val = QCA_WLAN_802_11_MODE_11N;
3577 break;
3578 case eCSR_CFG_DOT11_MODE_11AC:
3579 ret_val = QCA_WLAN_802_11_MODE_11AC;
3580 break;
3581 case eCSR_CFG_DOT11_MODE_AUTO:
3582 case eCSR_CFG_DOT11_MODE_ABG:
3583 default:
3584 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3585 }
3586 return ret_val;
3587}
3588
3589/**
3590 * hdd_add_tx_bitrate() - add tx bitrate attribute
3591 * @skb: pointer to sk buff
3592 * @hdd_sta_ctx: pointer to hdd station context
3593 * @idx: attribute index
3594 *
3595 * Return: Success(0) or reason code for failure
3596 */
3597static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3598 hdd_station_ctx_t *hdd_sta_ctx,
3599 int idx)
3600{
3601 struct nlattr *nla_attr;
3602 uint32_t bitrate, bitrate_compat;
3603
3604 nla_attr = nla_nest_start(skb, idx);
3605 if (!nla_attr)
3606 goto fail;
3607 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3608 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3609
3610 /* report 16-bit bitrate only if we can */
3611 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3612 if (bitrate > 0 &&
3613 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3614 hdd_err("put fail");
3615 goto fail;
3616 }
3617 if (bitrate_compat > 0 &&
3618 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3619 hdd_err("put fail");
3620 goto fail;
3621 }
3622 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3623 hdd_sta_ctx->conn_info.txrate.nss)) {
3624 hdd_err("put fail");
3625 goto fail;
3626 }
3627 nla_nest_end(skb, nla_attr);
3628 return 0;
3629fail:
3630 return -EINVAL;
3631}
3632
3633/**
3634 * hdd_add_sta_info() - add station info attribute
3635 * @skb: pointer to sk buff
3636 * @hdd_sta_ctx: pointer to hdd station context
3637 * @idx: attribute index
3638 *
3639 * Return: Success(0) or reason code for failure
3640 */
3641static int32_t hdd_add_sta_info(struct sk_buff *skb,
3642 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3643{
3644 struct nlattr *nla_attr;
3645
3646 nla_attr = nla_nest_start(skb, idx);
3647 if (!nla_attr)
3648 goto fail;
3649 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3650 (hdd_sta_ctx->conn_info.signal + 100))) {
3651 hdd_err("put fail");
3652 goto fail;
3653 }
3654 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3655 goto fail;
3656 nla_nest_end(skb, nla_attr);
3657 return 0;
3658fail:
3659 return -EINVAL;
3660}
3661
3662/**
3663 * hdd_add_survey_info() - add survey info attribute
3664 * @skb: pointer to sk buff
3665 * @hdd_sta_ctx: pointer to hdd station context
3666 * @idx: attribute index
3667 *
3668 * Return: Success(0) or reason code for failure
3669 */
3670static int32_t hdd_add_survey_info(struct sk_buff *skb,
3671 hdd_station_ctx_t *hdd_sta_ctx,
3672 int idx)
3673{
3674 struct nlattr *nla_attr;
3675
3676 nla_attr = nla_nest_start(skb, idx);
3677 if (!nla_attr)
3678 goto fail;
3679 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3680 hdd_sta_ctx->conn_info.freq) ||
3681 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3682 (hdd_sta_ctx->conn_info.noise + 100))) {
3683 hdd_err("put fail");
3684 goto fail;
3685 }
3686 nla_nest_end(skb, nla_attr);
3687 return 0;
3688fail:
3689 return -EINVAL;
3690}
3691
3692/**
3693 * hdd_add_link_standard_info() - add link info attribute
3694 * @skb: pointer to sk buff
3695 * @hdd_sta_ctx: pointer to hdd station context
3696 * @idx: attribute index
3697 *
3698 * Return: Success(0) or reason code for failure
3699 */
3700static int32_t
3701hdd_add_link_standard_info(struct sk_buff *skb,
3702 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3703{
3704 struct nlattr *nla_attr;
3705
3706 nla_attr = nla_nest_start(skb, idx);
3707 if (!nla_attr)
3708 goto fail;
3709 if (nla_put(skb,
3710 NL80211_ATTR_SSID,
3711 hdd_sta_ctx->conn_info.SSID.SSID.length,
3712 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3713 hdd_err("put fail");
3714 goto fail;
3715 }
3716 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3717 goto fail;
3718 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3719 goto fail;
3720 nla_nest_end(skb, nla_attr);
3721 return 0;
3722fail:
3723 return -EINVAL;
3724}
3725
3726/**
3727 * hdd_add_ap_standard_info() - add ap info attribute
3728 * @skb: pointer to sk buff
3729 * @hdd_sta_ctx: pointer to hdd station context
3730 * @idx: attribute index
3731 *
3732 * Return: Success(0) or reason code for failure
3733 */
3734static int32_t
3735hdd_add_ap_standard_info(struct sk_buff *skb,
3736 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3737{
3738 struct nlattr *nla_attr;
3739
3740 nla_attr = nla_nest_start(skb, idx);
3741 if (!nla_attr)
3742 goto fail;
3743 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3744 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3745 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3746 &hdd_sta_ctx->conn_info.vht_caps)) {
3747 hdd_err("put fail");
3748 goto fail;
3749 }
3750 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3751 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3752 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3753 &hdd_sta_ctx->conn_info.ht_caps)) {
3754 hdd_err("put fail");
3755 goto fail;
3756 }
3757 nla_nest_end(skb, nla_attr);
3758 return 0;
3759fail:
3760 return -EINVAL;
3761}
3762
3763/**
3764 * hdd_get_station_info() - send BSS information to supplicant
3765 * @hdd_ctx: pointer to hdd context
3766 * @adapter: pointer to adapter
3767 *
3768 * Return: 0 if success else error status
3769 */
3770static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3771 hdd_adapter_t *adapter)
3772{
3773 struct sk_buff *skb = NULL;
3774 uint8_t *tmp_hs20 = NULL;
3775 uint32_t nl_buf_len;
3776 hdd_station_ctx_t *hdd_sta_ctx;
3777
3778 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3779
3780 nl_buf_len = NLMSG_HDRLEN;
3781 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3782 sizeof(hdd_sta_ctx->conn_info.freq) +
3783 sizeof(hdd_sta_ctx->conn_info.noise) +
3784 sizeof(hdd_sta_ctx->conn_info.signal) +
3785 (sizeof(uint32_t) * 2) +
3786 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3787 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3788 sizeof(hdd_sta_ctx->conn_info.authType) +
3789 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3790 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3791 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3792 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3793 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3794 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3795 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3796 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3797 1);
3798 }
3799 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3800 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3801 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3802 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3803
3804
3805 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3806 if (!skb) {
3807 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3808 return -ENOMEM;
3809 }
3810
3811 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3812 LINK_INFO_STANDARD_NL80211_ATTR)) {
3813 hdd_err("put fail");
3814 goto fail;
3815 }
3816 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3817 AP_INFO_STANDARD_NL80211_ATTR)) {
3818 hdd_err("put fail");
3819 goto fail;
3820 }
3821 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3822 hdd_sta_ctx->conn_info.roam_count) ||
3823 nla_put_u32(skb, INFO_AKM,
3824 hdd_convert_auth_type(
3825 hdd_sta_ctx->conn_info.authType)) ||
3826 nla_put_u32(skb, WLAN802_11_MODE,
3827 hdd_convert_dot11mode(
3828 hdd_sta_ctx->conn_info.dot11Mode))) {
3829 hdd_err("put fail");
3830 goto fail;
3831 }
3832 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3833 if (nla_put(skb, HT_OPERATION,
3834 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3835 &hdd_sta_ctx->conn_info.ht_operation)) {
3836 hdd_err("put fail");
3837 goto fail;
3838 }
3839 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3840 if (nla_put(skb, VHT_OPERATION,
3841 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3842 &hdd_sta_ctx->conn_info.vht_operation)) {
3843 hdd_err("put fail");
3844 goto fail;
3845 }
3846 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3847 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3848 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3849 tmp_hs20 + 1)) {
3850 hdd_err("put fail");
3851 goto fail;
3852 }
3853
3854 return cfg80211_vendor_cmd_reply(skb);
3855fail:
3856 if (skb)
3857 kfree_skb(skb);
3858 return -EINVAL;
3859}
3860
3861/**
3862 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3863 * @wiphy: corestack handler
3864 * @wdev: wireless device
3865 * @data: data
3866 * @data_len: data length
3867 *
3868 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3869 * Validate cmd attributes and send the station info to upper layers.
3870 *
3871 * Return: Success(0) or reason code for failure
3872 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303873static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303874__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3875 struct wireless_dev *wdev,
3876 const void *data,
3877 int data_len)
3878{
3879 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3880 struct net_device *dev = wdev->netdev;
3881 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3882 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3883 int32_t status;
3884
3885 ENTER_DEV(dev);
3886 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3887 hdd_err("Command not allowed in FTM mode");
3888 status = -EPERM;
3889 goto out;
3890 }
3891
3892 status = wlan_hdd_validate_context(hdd_ctx);
3893 if (0 != status)
3894 goto out;
3895
3896
3897 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3898 data, data_len, NULL);
3899 if (status) {
3900 hdd_err("Invalid ATTR");
3901 goto out;
3902 }
3903
3904 /* Parse and fetch Command Type*/
3905 if (tb[STATION_INFO]) {
3906 status = hdd_get_station_info(hdd_ctx, adapter);
3907 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3908 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3909 } else {
3910 hdd_err("get station info cmd type failed");
3911 status = -EINVAL;
3912 goto out;
3913 }
3914 EXIT();
3915out:
3916 return status;
3917}
3918
3919/**
3920 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3921 * @wiphy: corestack handler
3922 * @wdev: wireless device
3923 * @data: data
3924 * @data_len: data length
3925 *
3926 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3927 * Validate cmd attributes and send the station info to upper layers.
3928 *
3929 * Return: Success(0) or reason code for failure
3930 */
3931static int32_t
3932hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3933 struct wireless_dev *wdev,
3934 const void *data,
3935 int data_len)
3936{
3937 int ret;
3938
3939 cds_ssr_protect(__func__);
3940 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3941 cds_ssr_unprotect(__func__);
3942
3943 return ret;
3944}
3945
3946/*
3947 * undef short names defined for get station command
3948 * used by __wlan_hdd_cfg80211_get_station_cmd()
3949 */
3950#undef STATION_INVALID
3951#undef STATION_INFO
3952#undef STATION_ASSOC_FAIL_REASON
3953#undef STATION_MAX
3954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3956/**
3957 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3958 * @wiphy: pointer to wireless wiphy structure.
3959 * @wdev: pointer to wireless_dev structure.
3960 * @data: Pointer to the Key data
3961 * @data_len:Length of the data passed
3962 *
3963 * This is called when wlan driver needs to save the keys received via
3964 * vendor specific command.
3965 *
3966 * Return: Return the Success or Failure code.
3967 */
3968static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3969 struct wireless_dev *wdev,
3970 const void *data, int data_len)
3971{
3972 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3973 struct net_device *dev = wdev->netdev;
3974 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3975 hdd_context_t *hdd_ctx_ptr;
3976 int status;
3977
Jeff Johnson1f61b612016-02-12 16:28:33 -08003978 ENTER_DEV(dev);
3979
Anurag Chouhan6d760662016-02-20 16:05:43 +05303980 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003981 hdd_err("Command not allowed in FTM mode");
3982 return -EPERM;
3983 }
3984
3985 if ((data == NULL) || (data_len == 0) ||
3986 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003987 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988 return -EINVAL;
3989 }
3990
3991 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3992 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003993 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994 return -EINVAL;
3995 }
3996
3997 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303998 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4001 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004002 true,
4003 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304004 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4005 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4007 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4008 return 0;
4009}
4010
4011/**
4012 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4013 * @wiphy: pointer to wireless wiphy structure.
4014 * @wdev: pointer to wireless_dev structure.
4015 * @data: Pointer to the Key data
4016 * @data_len:Length of the data passed
4017 *
4018 * This is called when wlan driver needs to save the keys received via
4019 * vendor specific command.
4020 *
4021 * Return: Return the Success or Failure code.
4022 */
4023static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4024 struct wireless_dev *wdev,
4025 const void *data, int data_len)
4026{
4027 int ret;
4028
4029 cds_ssr_protect(__func__);
4030 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4031 cds_ssr_unprotect(__func__);
4032
4033 return ret;
4034}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004035#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036
4037static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4038 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4039 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4040 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004041 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042};
4043
4044/**
4045 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4046 * @wiphy: pointer to wireless wiphy structure.
4047 * @wdev: pointer to wireless_dev structure.
4048 * @data: Pointer to the data to be passed via vendor interface
4049 * @data_len:Length of the data to be passed
4050 *
4051 * This is called when wlan driver needs to send wifi driver related info
4052 * (driver/fw version) to the user space application upon request.
4053 *
4054 * Return: Return the Success or Failure code.
4055 */
4056static int
4057__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4058 struct wireless_dev *wdev,
4059 const void *data, int data_len)
4060{
4061 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4062 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004063 tSirVersionString driver_version;
4064 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004067 struct sk_buff *reply_skb;
4068 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069
Jeff Johnson1f61b612016-02-12 16:28:33 -08004070 ENTER_DEV(wdev->netdev);
4071
Anurag Chouhan6d760662016-02-20 16:05:43 +05304072 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 hdd_err("Command not allowed in FTM mode");
4074 return -EPERM;
4075 }
4076
4077 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304078 if (status)
4079 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004080
4081 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4082 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004083 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 return -EINVAL;
4085 }
4086
4087 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004088 hdd_err("Rcvd req for Driver version");
4089 strlcpy(driver_version, QWLAN_VERSIONSTR,
4090 sizeof(driver_version));
4091 skb_len += strlen(driver_version) + 1;
4092 count++;
4093 }
4094
4095 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4096 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004097 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4098 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004099 snprintf(firmware_version, sizeof(firmware_version),
4100 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4101 skb_len += strlen(firmware_version) + 1;
4102 count++;
4103 }
4104
4105 if (count == 0) {
4106 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107 return -EINVAL;
4108 }
4109
Ryan Hsu7ac88852016-04-28 10:20:34 -07004110 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4111 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4112
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004114 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 return -ENOMEM;
4116 }
4117
Ryan Hsu7ac88852016-04-28 10:20:34 -07004118 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4119 if (nla_put_string(reply_skb,
4120 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4121 driver_version))
4122 goto error_nla_fail;
4123 }
4124
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304125 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004126 if (nla_put_string(reply_skb,
4127 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4128 firmware_version))
4129 goto error_nla_fail;
4130 }
4131
4132 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4133 if (nla_put_u32(reply_skb,
4134 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4135 hdd_ctx->radio_index))
4136 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 }
4138
4139 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004140
4141error_nla_fail:
4142 hdd_err("nla put fail");
4143 kfree_skb(reply_skb);
4144 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004145}
4146
4147/**
4148 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4149 * @wiphy: pointer to wireless wiphy structure.
4150 * @wdev: pointer to wireless_dev structure.
4151 * @data: Pointer to the data to be passed via vendor interface
4152 * @data_len:Length of the data to be passed
4153 *
4154 * This is called when wlan driver needs to send wifi driver related info
4155 * (driver/fw version) to the user space application upon request.
4156 *
4157 * Return: Return the Success or Failure code.
4158 */
4159static int
4160wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4161 struct wireless_dev *wdev,
4162 const void *data, int data_len)
4163{
4164 int ret;
4165
4166 cds_ssr_protect(__func__);
4167 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4168 cds_ssr_unprotect(__func__);
4169
4170 return ret;
4171}
4172
4173/**
4174 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4175 * @wiphy: pointer to wireless wiphy structure.
4176 * @wdev: pointer to wireless_dev structure.
4177 * @data: Pointer to the data to be passed via vendor interface
4178 * @data_len:Length of the data to be passed
4179 *
4180 * This is called by userspace to know the supported logger features
4181 *
4182 * Return: Return the Success or Failure code.
4183 */
4184static int
4185__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4186 struct wireless_dev *wdev,
4187 const void *data, int data_len)
4188{
4189 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4190 int status;
4191 uint32_t features;
4192 struct sk_buff *reply_skb = NULL;
4193
Jeff Johnson1f61b612016-02-12 16:28:33 -08004194 ENTER_DEV(wdev->netdev);
4195
Anurag Chouhan6d760662016-02-20 16:05:43 +05304196 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197 hdd_err("Command not allowed in FTM mode");
4198 return -EPERM;
4199 }
4200
4201 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304202 if (status)
4203 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204
4205 features = 0;
4206
4207 if (hdd_is_memdump_supported())
4208 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4209 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4210 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4211 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4212
4213 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4214 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4215 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004216 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004217 return -ENOMEM;
4218 }
4219
Jeff Johnson020db452016-06-29 14:37:26 -07004220 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4222 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004223 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 kfree_skb(reply_skb);
4225 return -EINVAL;
4226 }
4227
4228 return cfg80211_vendor_cmd_reply(reply_skb);
4229}
4230
4231/**
4232 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4233 * @wiphy: pointer to wireless wiphy structure.
4234 * @wdev: pointer to wireless_dev structure.
4235 * @data: Pointer to the data to be passed via vendor interface
4236 * @data_len:Length of the data to be passed
4237 *
4238 * This is called by userspace to know the supported logger features
4239 *
4240 * Return: Return the Success or Failure code.
4241 */
4242static int
4243wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4244 struct wireless_dev *wdev,
4245 const void *data, int data_len)
4246{
4247 int ret;
4248
4249 cds_ssr_protect(__func__);
4250 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4251 data, data_len);
4252 cds_ssr_unprotect(__func__);
4253
4254 return ret;
4255}
4256
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004257#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004258/**
4259 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304260 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 * @bssid: pointer to bssid of roamed AP.
4262 * @req_rsn_ie: Pointer to request RSN IE
4263 * @req_rsn_len: Length of the request RSN IE
4264 * @rsp_rsn_ie: Pointer to response RSN IE
4265 * @rsp_rsn_len: Length of the response RSN IE
4266 * @roam_info_ptr: Pointer to the roaming related information
4267 *
4268 * This is called when wlan driver needs to send the roaming and
4269 * authorization information after roaming.
4270 *
4271 * The information that would be sent is the request RSN IE, response
4272 * RSN IE and BSSID of the newly roamed AP.
4273 *
4274 * If the Authorized status is authenticated, then additional parameters
4275 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4276 * supplicant.
4277 *
4278 * The supplicant upon receiving this event would ignore the legacy
4279 * cfg80211_roamed call and use the entire information from this event.
4280 * The cfg80211_roamed should still co-exist since the kernel will
4281 * make use of the parameters even if the supplicant ignores it.
4282 *
4283 * Return: Return the Success or Failure code.
4284 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304285int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4287 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4288{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304289 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004290 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004291 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292 ENTER();
4293
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304294 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004295 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004297 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004298 !roam_info_ptr->roamSynchInProgress)
4299 return 0;
4300
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304302 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4304 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4305 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004306 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4308 GFP_KERNEL);
4309
4310 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004311 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 return -EINVAL;
4313 }
4314
4315 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4316 ETH_ALEN, bssid) ||
4317 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4318 req_rsn_len, req_rsn_ie) ||
4319 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4320 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004321 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 goto nla_put_failure;
4323 }
Jeff Johnson020db452016-06-29 14:37:26 -07004324 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 if (roam_info_ptr->synchAuthStatus ==
4326 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004327 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004328 if (nla_put_u8(skb,
4329 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4330 hdd_err("nla put fail");
4331 goto nla_put_failure;
4332 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004333 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4334 /* if FT or CCKM connection: dont send replay counter */
4335 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4336 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4337 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4338 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4339 nla_put(skb,
4340 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4341 SIR_REPLAY_CTR_LEN,
4342 roam_info_ptr->replay_ctr)) {
4343 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004344 hdd_err("failed to send replay counter.");
4345 goto nla_put_failure;
4346 }
4347 if (nla_put(skb,
4348 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4349 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4350 nla_put(skb,
4351 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4352 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4353 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 goto nla_put_failure;
4355 }
4356 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004357 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4359 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004360 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 goto nla_put_failure;
4362 }
4363 }
4364
Jeff Johnson020db452016-06-29 14:37:26 -07004365 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004366 roam_info_ptr->subnet_change_status);
4367
4368 /*
4369 * Add subnet change status if subnet has changed
4370 * 0 = unchanged
4371 * 1 = changed
4372 * 2 = unknown
4373 */
4374 if (roam_info_ptr->subnet_change_status) {
4375 if (nla_put_u8(skb,
4376 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4377 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004378 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004379 goto nla_put_failure;
4380 }
4381 }
4382
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 cfg80211_vendor_event(skb, GFP_KERNEL);
4384 return 0;
4385
4386nla_put_failure:
4387 kfree_skb(skb);
4388 return -EINVAL;
4389}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004390#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391
4392static const struct nla_policy
4393wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4394
4395 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4396 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4397 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304398 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304399 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4400 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004401 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4402 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4403 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4404 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4405 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304406 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407};
4408
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304410 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4411 *
4412 * @adapter: Pointer to HDD adapter
4413 * @ie_data: Pointer to Scan IEs buffer
4414 * @ie_len: Length of Scan IEs
4415 *
4416 * Return: 0 on success; error number otherwise
4417 */
4418static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4419 uint8_t *ie_data, uint8_t ie_len)
4420{
4421 hdd_scaninfo_t *scan_info = NULL;
4422 scan_info = &adapter->scan_info;
4423
4424 if (scan_info->default_scan_ies) {
4425 qdf_mem_free(scan_info->default_scan_ies);
4426 scan_info->default_scan_ies = NULL;
4427 }
4428
4429 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4430 if (!scan_info->default_scan_ies)
4431 return -ENOMEM;
4432
4433 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4434 scan_info->default_scan_ies_len = ie_len;
4435 return 0;
4436}
4437
4438/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4440 * vendor command
4441 *
4442 * @wiphy: wiphy device pointer
4443 * @wdev: wireless device pointer
4444 * @data: Vendor command data buffer
4445 * @data_len: Buffer length
4446 *
4447 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4448 *
4449 * Return: Error code.
4450 */
4451static int
4452__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4453 struct wireless_dev *wdev,
4454 const void *data,
4455 int data_len)
4456{
4457 struct net_device *dev = wdev->netdev;
4458 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4459 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4460 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4461 int ret_val = 0;
4462 u32 modulated_dtim;
4463 u16 stats_avg_factor;
4464 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304465 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004466 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004467 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304468 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304469 int attr_len;
4470 int access_policy = 0;
4471 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4472 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304473 uint16_t scan_ie_len = 0;
4474 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304475 struct sir_set_tx_rx_aggregation_size request;
4476 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004477 uint8_t retry, delay;
4478 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304479 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304480
Jeff Johnson1f61b612016-02-12 16:28:33 -08004481 ENTER_DEV(dev);
4482
Anurag Chouhan6d760662016-02-20 16:05:43 +05304483 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004484 hdd_err("Command not allowed in FTM mode");
4485 return -EPERM;
4486 }
4487
4488 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304489 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491
4492 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4493 data, data_len,
4494 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004495 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496 return -EINVAL;
4497 }
4498
Krunal Sonie3531942016-04-12 17:43:53 -07004499 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4500 ftm_capab = nla_get_u32(tb[
4501 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4502 hdd_ctx->config->fine_time_meas_cap =
4503 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4504 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304505 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004506 hdd_ctx->config->fine_time_meas_cap);
4507 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4508 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4509 hdd_ctx->config->fine_time_meas_cap);
4510 }
4511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004512 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4513 modulated_dtim = nla_get_u32(
4514 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4515
4516 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4517 adapter->sessionId,
4518 modulated_dtim);
4519
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304520 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 ret_val = -EPERM;
4522 }
4523
Kapil Gupta6213c012016-09-02 19:39:09 +05304524 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4525 qpower = nla_get_u8(
4526 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4527 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4528 ret_val = -EINVAL;
4529 }
4530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4532 stats_avg_factor = nla_get_u16(
4533 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4534 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4535 adapter->sessionId,
4536 stats_avg_factor);
4537
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304538 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004539 ret_val = -EPERM;
4540 }
4541
4542
4543 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4544 guard_time = nla_get_u32(
4545 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4546 status = sme_configure_guard_time(hdd_ctx->hHal,
4547 adapter->sessionId,
4548 guard_time);
4549
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304550 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 ret_val = -EPERM;
4552 }
4553
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304554 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4555 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4556 attr_len = nla_len(
4557 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4558 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4559 hdd_info("Invalid value. attr_len %d",
4560 attr_len);
4561 return -EINVAL;
4562 }
4563
4564 nla_memcpy(&vendor_ie,
4565 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4566 attr_len);
4567 vendor_ie_present = true;
4568 hdd_info("Access policy vendor ie present.attr_len %d",
4569 attr_len);
4570 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4571 &vendor_ie[0], attr_len);
4572 }
4573
4574 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4575 access_policy = (int) nla_get_u32(
4576 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4577 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4578 (access_policy >
4579 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4580 hdd_info("Invalid value. access_policy %d",
4581 access_policy);
4582 return -EINVAL;
4583 }
4584 access_policy_present = true;
4585 hdd_info("Access policy present. access_policy %d",
4586 access_policy);
4587 }
4588
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004589 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4590 retry = nla_get_u8(tb[
4591 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4592 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4593 CFG_NON_AGG_RETRY_MAX : retry;
4594 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4595 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4596 retry, PDEV_CMD);
4597 }
4598
4599 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4600 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4601 retry = retry > CFG_AGG_RETRY_MAX ?
4602 CFG_AGG_RETRY_MAX : retry;
4603
4604 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4605 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4606 CFG_AGG_RETRY_MIN : retry;
4607 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4608 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4609 retry, PDEV_CMD);
4610 }
4611
4612 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4613 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4614 retry = retry > CFG_MGMT_RETRY_MAX ?
4615 CFG_MGMT_RETRY_MAX : retry;
4616 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4617 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4618 retry, PDEV_CMD);
4619 }
4620
4621 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4622 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4623 retry = retry > CFG_CTRL_RETRY_MAX ?
4624 CFG_CTRL_RETRY_MAX : retry;
4625 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4626 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4627 retry, PDEV_CMD);
4628 }
4629
4630 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4631 delay = nla_get_u8(tb[
4632 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4633 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4634 CFG_PROPAGATION_DELAY_MAX : delay;
4635 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4636 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4637 delay, PDEV_CMD);
4638 }
4639
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304640 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4641 tx_fail_count = nla_get_u32(
4642 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4643 if (tx_fail_count) {
4644 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4645 adapter->sessionId, tx_fail_count);
4646 if (QDF_STATUS_SUCCESS != status) {
4647 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4648 status);
4649 return -EINVAL;
4650 }
4651 }
4652 }
4653
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304654 if (vendor_ie_present && access_policy_present) {
4655 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4656 access_policy =
4657 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304658 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304659 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304660 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304661
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304662 hdd_info("calling sme_update_access_policy_vendor_ie");
4663 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4664 adapter->sessionId, &vendor_ie[0],
4665 access_policy);
4666 if (QDF_STATUS_SUCCESS != status) {
4667 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304668 return -EINVAL;
4669 }
4670 }
4671
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304672 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4673 set_value = nla_get_u8(
4674 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4675 hdd_info("set_value: %d", set_value);
4676 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4677 }
4678
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304679 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4680 scan_ie_len = nla_len(
4681 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4682 hdd_info("Received default scan IE of len %d session %d device mode %d",
4683 scan_ie_len, adapter->sessionId,
4684 adapter->device_mode);
4685 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4686 scan_ie = (uint8_t *) nla_data(tb
4687 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304688
4689 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4690 scan_ie_len))
4691 hdd_err("Failed to save default scan IEs");
4692
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304693 if (adapter->device_mode == QDF_STA_MODE) {
4694 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4695 adapter->sessionId, scan_ie,
4696 scan_ie_len);
4697 if (QDF_STATUS_SUCCESS != status)
4698 ret_val = -EPERM;
4699 }
4700 } else
4701 ret_val = -EPERM;
4702 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304703
4704 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4705 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4706 /* if one is specified, both must be specified */
4707 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4708 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4709 hdd_err("Both TX and RX MPDU Aggregation required");
4710 return -EINVAL;
4711 }
4712
4713 request.tx_aggregation_size = nla_get_u8(
4714 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4715 request.rx_aggregation_size = nla_get_u8(
4716 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4717 request.vdev_id = adapter->sessionId;
4718
4719 if (request.tx_aggregation_size >=
4720 CFG_TX_AGGREGATION_SIZE_MIN &&
4721 request.tx_aggregation_size <=
4722 CFG_TX_AGGREGATION_SIZE_MAX &&
4723 request.rx_aggregation_size >=
4724 CFG_RX_AGGREGATION_SIZE_MIN &&
4725 request.rx_aggregation_size <=
4726 CFG_RX_AGGREGATION_SIZE_MAX) {
4727 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4728 if (qdf_status != QDF_STATUS_SUCCESS) {
4729 hdd_err("failed to set aggr sizes err %d",
4730 qdf_status);
4731 ret_val = -EPERM;
4732 }
4733 } else {
4734 hdd_err("TX %d RX %d MPDU aggr size not in range",
4735 request.tx_aggregation_size,
4736 request.rx_aggregation_size);
4737 ret_val = -EINVAL;
4738 }
4739 }
4740
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304741 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4742 uint8_t ignore_assoc_disallowed;
4743
4744 ignore_assoc_disallowed
4745 = nla_get_u8(tb[
4746 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4747 hdd_info("Set ignore_assoc_disallowed value - %d",
4748 ignore_assoc_disallowed);
4749 if ((ignore_assoc_disallowed <
4750 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4751 (ignore_assoc_disallowed >
4752 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4753 return -EPERM;
4754
4755 sme_update_session_param(hdd_ctx->hHal,
4756 adapter->sessionId,
4757 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4758 ignore_assoc_disallowed);
4759 }
4760
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004761 return ret_val;
4762}
4763
4764/**
4765 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4766 * vendor command
4767 *
4768 * @wiphy: wiphy device pointer
4769 * @wdev: wireless device pointer
4770 * @data: Vendor command data buffer
4771 * @data_len: Buffer length
4772 *
4773 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4774 *
4775 * Return: EOK or other error codes.
4776 */
4777static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4778 struct wireless_dev *wdev,
4779 const void *data,
4780 int data_len)
4781{
4782 int ret;
4783
4784 cds_ssr_protect(__func__);
4785 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4786 data, data_len);
4787 cds_ssr_unprotect(__func__);
4788
4789 return ret;
4790}
4791
4792static const struct
4793nla_policy
4794qca_wlan_vendor_wifi_logger_start_policy
4795[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4796 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4797 = {.type = NLA_U32 },
4798 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4799 = {.type = NLA_U32 },
4800 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4801 = {.type = NLA_U32 },
4802};
4803
4804/**
4805 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4806 * or disable the collection of packet statistics from the firmware
4807 * @wiphy: WIPHY structure pointer
4808 * @wdev: Wireless device structure pointer
4809 * @data: Pointer to the data received
4810 * @data_len: Length of the data received
4811 *
4812 * This function enables or disables the collection of packet statistics from
4813 * the firmware
4814 *
4815 * Return: 0 on success and errno on failure
4816 */
4817static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4818 struct wireless_dev *wdev,
4819 const void *data,
4820 int data_len)
4821{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304822 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4824 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4825 struct sir_wifi_start_log start_log;
4826
Jeff Johnson1f61b612016-02-12 16:28:33 -08004827 ENTER_DEV(wdev->netdev);
4828
Anurag Chouhan6d760662016-02-20 16:05:43 +05304829 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004830 hdd_err("Command not allowed in FTM mode");
4831 return -EPERM;
4832 }
4833
4834 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304835 if (status)
4836 return status;
4837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838
4839 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4840 data, data_len,
4841 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004842 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 return -EINVAL;
4844 }
4845
4846 /* Parse and fetch ring id */
4847 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004848 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 return -EINVAL;
4850 }
4851 start_log.ring_id = nla_get_u32(
4852 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004853 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854
4855 /* Parse and fetch verbose level */
4856 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004857 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858 return -EINVAL;
4859 }
4860 start_log.verbose_level = nla_get_u32(
4861 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004862 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863
4864 /* Parse and fetch flag */
4865 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004866 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 return -EINVAL;
4868 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304869 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304871 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304873 /* size is buff size which can be set using iwpriv command*/
4874 start_log.size = 0;
4875
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004876 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4877
4878 if (start_log.ring_id == RING_ID_WAKELOCK) {
4879 /* Start/stop wakelock events */
4880 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4881 cds_set_wakelock_logging(true);
4882 else
4883 cds_set_wakelock_logging(false);
4884 return 0;
4885 }
4886
4887 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304888 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 status);
4891 return -EINVAL;
4892 }
4893 return 0;
4894}
4895
4896/**
4897 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4898 * or disable the collection of packet statistics from the firmware
4899 * @wiphy: WIPHY structure pointer
4900 * @wdev: Wireless device structure pointer
4901 * @data: Pointer to the data received
4902 * @data_len: Length of the data received
4903 *
4904 * This function is used to enable or disable the collection of packet
4905 * statistics from the firmware
4906 *
4907 * Return: 0 on success and errno on failure
4908 */
4909static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4910 struct wireless_dev *wdev,
4911 const void *data,
4912 int data_len)
4913{
4914 int ret = 0;
4915
4916 cds_ssr_protect(__func__);
4917 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4918 wdev, data, data_len);
4919 cds_ssr_unprotect(__func__);
4920
4921 return ret;
4922}
4923
4924static const struct
4925nla_policy
4926qca_wlan_vendor_wifi_logger_get_ring_data_policy
4927[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4928 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4929 = {.type = NLA_U32 },
4930};
4931
4932/**
4933 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4934 * @wiphy: WIPHY structure pointer
4935 * @wdev: Wireless device structure pointer
4936 * @data: Pointer to the data received
4937 * @data_len: Length of the data received
4938 *
4939 * This function is used to flush or retrieve the per packet statistics from
4940 * the driver
4941 *
4942 * Return: 0 on success and errno on failure
4943 */
4944static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4945 struct wireless_dev *wdev,
4946 const void *data,
4947 int data_len)
4948{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304949 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004950 uint32_t ring_id;
4951 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4952 struct nlattr *tb
4953 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4954
Jeff Johnson1f61b612016-02-12 16:28:33 -08004955 ENTER_DEV(wdev->netdev);
4956
Anurag Chouhan6d760662016-02-20 16:05:43 +05304957 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004958 hdd_err("Command not allowed in FTM mode");
4959 return -EPERM;
4960 }
4961
4962 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304963 if (status)
4964 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004965
4966 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4967 data, data_len,
4968 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004969 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970 return -EINVAL;
4971 }
4972
4973 /* Parse and fetch ring id */
4974 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004975 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 return -EINVAL;
4977 }
4978
4979 ring_id = nla_get_u32(
4980 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4981
4982 if (ring_id == RING_ID_PER_PACKET_STATS) {
4983 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004984 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304985 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4986 /*
4987 * As part of DRIVER ring ID, flush both driver and fw logs.
4988 * For other Ring ID's driver doesn't have any rings to flush
4989 */
4990 hdd_notice("Bug report triggered by framework");
4991
4992 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4993 WLAN_LOG_INDICATOR_FRAMEWORK,
4994 WLAN_LOG_REASON_CODE_UNUSED,
4995 true, false);
4996 if (QDF_STATUS_SUCCESS != status) {
4997 hdd_err("Failed to trigger bug report");
4998 return -EINVAL;
4999 }
5000 } else {
5001 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5002 WLAN_LOG_INDICATOR_FRAMEWORK,
5003 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 return 0;
5006}
5007
5008/**
5009 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5010 * @wiphy: WIPHY structure pointer
5011 * @wdev: Wireless device structure pointer
5012 * @data: Pointer to the data received
5013 * @data_len: Length of the data received
5014 *
5015 * This function is used to flush or retrieve the per packet statistics from
5016 * the driver
5017 *
5018 * Return: 0 on success and errno on failure
5019 */
5020static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5021 struct wireless_dev *wdev,
5022 const void *data,
5023 int data_len)
5024{
5025 int ret = 0;
5026
5027 cds_ssr_protect(__func__);
5028 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5029 wdev, data, data_len);
5030 cds_ssr_unprotect(__func__);
5031
5032 return ret;
5033}
5034
5035#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5036/**
5037 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5038 * @hdd_ctx: HDD context
5039 * @request_id: [input] request id
5040 * @pattern_id: [output] pattern id
5041 *
5042 * This function loops through request id to pattern id array
5043 * if the slot is available, store the request id and return pattern id
5044 * if entry exists, return the pattern id
5045 *
5046 * Return: 0 on success and errno on failure
5047 */
5048static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5049 uint32_t request_id,
5050 uint8_t *pattern_id)
5051{
5052 uint32_t i;
5053
5054 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5055 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5056 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5057 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5058 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5059 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5060 return 0;
5061 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5062 request_id) {
5063 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5064 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5065 return 0;
5066 }
5067 }
5068 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5069 return -EINVAL;
5070}
5071
5072/**
5073 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5074 * @hdd_ctx: HDD context
5075 * @request_id: [input] request id
5076 * @pattern_id: [output] pattern id
5077 *
5078 * This function loops through request id to pattern id array
5079 * reset request id to 0 (slot available again) and
5080 * return pattern id
5081 *
5082 * Return: 0 on success and errno on failure
5083 */
5084static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5085 uint32_t request_id,
5086 uint8_t *pattern_id)
5087{
5088 uint32_t i;
5089
5090 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5091 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5092 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5093 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5094 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5095 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5096 return 0;
5097 }
5098 }
5099 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5100 return -EINVAL;
5101}
5102
5103
5104/*
5105 * define short names for the global vendor params
5106 * used by __wlan_hdd_cfg80211_offloaded_packets()
5107 */
5108#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5109#define PARAM_REQUEST_ID \
5110 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5111#define PARAM_CONTROL \
5112 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5113#define PARAM_IP_PACKET \
5114 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5115#define PARAM_SRC_MAC_ADDR \
5116 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5117#define PARAM_DST_MAC_ADDR \
5118 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5119#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5120
5121/**
5122 * wlan_hdd_add_tx_ptrn() - add tx pattern
5123 * @adapter: adapter pointer
5124 * @hdd_ctx: hdd context
5125 * @tb: nl attributes
5126 *
5127 * This function reads the NL attributes and forms a AddTxPtrn message
5128 * posts it to SME.
5129 *
5130 */
5131static int
5132wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5133 struct nlattr **tb)
5134{
5135 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305136 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137 uint32_t request_id, ret, len;
5138 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305139 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005140 uint16_t eth_type = htons(ETH_P_IP);
5141
5142 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005143 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005144 return -ENOTSUPP;
5145 }
5146
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305147 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005149 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 return -ENOMEM;
5151 }
5152
5153 /* Parse and fetch request Id */
5154 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005155 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005156 goto fail;
5157 }
5158
5159 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5160 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005161 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005162 return -EINVAL;
5163 }
Jeff Johnson77848112016-06-29 14:52:06 -07005164 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165
5166 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005167 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168 goto fail;
5169 }
5170 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005171 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005172 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005173 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174 goto fail;
5175 }
5176
5177 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005178 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005179 goto fail;
5180 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005181 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305182 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005183 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005184 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185
Anurag Chouhanc5548422016-02-24 18:33:27 +05305186 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005187 &adapter->macAddressCurrent)) {
5188 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189 goto fail;
5190 }
5191
5192 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005193 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194 goto fail;
5195 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305196 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005197 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005198 MAC_ADDR_ARRAY(dst_addr.bytes));
5199
5200 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005201 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 goto fail;
5203 }
5204 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005205 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206
5207 if (add_req->ucPtrnSize < 0 ||
5208 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5209 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 add_req->ucPtrnSize);
5212 goto fail;
5213 }
5214
5215 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305216 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305217 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305218 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305219 QDF_MAC_ADDR_SIZE);
5220 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305221 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 len += 2;
5223
5224 /*
5225 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5226 * ------------------------------------------------------------
5227 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5228 * ------------------------------------------------------------
5229 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305230 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 nla_data(tb[PARAM_IP_PACKET]),
5232 add_req->ucPtrnSize);
5233 add_req->ucPtrnSize += len;
5234
5235 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5236 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005237 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238 goto fail;
5239 }
5240 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005241 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005242
5243 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305244 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005245 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246 goto fail;
5247 }
5248
5249 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305250 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 return 0;
5252
5253fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305254 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 return -EINVAL;
5256}
5257
5258/**
5259 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5260 * @adapter: adapter pointer
5261 * @hdd_ctx: hdd context
5262 * @tb: nl attributes
5263 *
5264 * This function reads the NL attributes and forms a DelTxPtrn message
5265 * posts it to SME.
5266 *
5267 */
5268static int
5269wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5270 struct nlattr **tb)
5271{
5272 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305273 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005274 uint32_t request_id, ret;
5275 uint8_t pattern_id = 0;
5276
5277 /* Parse and fetch request Id */
5278 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005279 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 return -EINVAL;
5281 }
5282 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5283 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005284 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 return -EINVAL;
5286 }
5287
5288 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5289 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005290 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291 return -EINVAL;
5292 }
5293
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305294 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005296 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 return -ENOMEM;
5298 }
5299
Anurag Chouhanc5548422016-02-24 18:33:27 +05305300 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005301 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005302 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005303 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 request_id, del_req->ucPtrnId);
5305
5306 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305307 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005308 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309 goto fail;
5310 }
5311
5312 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305313 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 return 0;
5315
5316fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305317 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005318 return -EINVAL;
5319}
5320
5321
5322/**
5323 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5324 * @wiphy: Pointer to wireless phy
5325 * @wdev: Pointer to wireless device
5326 * @data: Pointer to data
5327 * @data_len: Data length
5328 *
5329 * Return: 0 on success, negative errno on failure
5330 */
5331static int
5332__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5333 struct wireless_dev *wdev,
5334 const void *data,
5335 int data_len)
5336{
5337 struct net_device *dev = wdev->netdev;
5338 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5339 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5340 struct nlattr *tb[PARAM_MAX + 1];
5341 uint8_t control;
5342 int ret;
5343 static const struct nla_policy policy[PARAM_MAX + 1] = {
5344 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5345 [PARAM_CONTROL] = { .type = NLA_U32 },
5346 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305347 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305349 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005350 [PARAM_PERIOD] = { .type = NLA_U32 },
5351 };
5352
Jeff Johnson1f61b612016-02-12 16:28:33 -08005353 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354
Anurag Chouhan6d760662016-02-20 16:05:43 +05305355 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 hdd_err("Command not allowed in FTM mode");
5357 return -EPERM;
5358 }
5359
5360 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305361 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363
5364 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005365 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 return -ENOTSUPP;
5367 }
5368
5369 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005370 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 return -EINVAL;
5372 }
5373
5374 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005375 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 return -EINVAL;
5377 }
5378 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005379 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380
5381 if (control == WLAN_START_OFFLOADED_PACKETS)
5382 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005383 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005384 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005385
5386 hdd_err("Invalid control: %d", control);
5387
5388 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389}
5390
5391/*
5392 * done with short names for the global vendor params
5393 * used by __wlan_hdd_cfg80211_offloaded_packets()
5394 */
5395#undef PARAM_MAX
5396#undef PARAM_REQUEST_ID
5397#undef PARAM_CONTROL
5398#undef PARAM_IP_PACKET
5399#undef PARAM_SRC_MAC_ADDR
5400#undef PARAM_DST_MAC_ADDR
5401#undef PARAM_PERIOD
5402
5403/**
5404 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5405 * @wiphy: wiphy structure pointer
5406 * @wdev: Wireless device structure pointer
5407 * @data: Pointer to the data received
5408 * @data_len: Length of @data
5409 *
5410 * Return: 0 on success; errno on failure
5411 */
5412static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5413 struct wireless_dev *wdev,
5414 const void *data,
5415 int data_len)
5416{
5417 int ret = 0;
5418
5419 cds_ssr_protect(__func__);
5420 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5421 wdev, data, data_len);
5422 cds_ssr_unprotect(__func__);
5423
5424 return ret;
5425}
5426#endif
5427
5428/*
5429 * define short names for the global vendor params
5430 * used by __wlan_hdd_cfg80211_monitor_rssi()
5431 */
5432#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5433#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5434#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5435#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5436#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5437
5438/**
5439 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5440 * @wiphy: Pointer to wireless phy
5441 * @wdev: Pointer to wireless device
5442 * @data: Pointer to data
5443 * @data_len: Data length
5444 *
5445 * Return: 0 on success, negative errno on failure
5446 */
5447static int
5448__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5449 struct wireless_dev *wdev,
5450 const void *data,
5451 int data_len)
5452{
5453 struct net_device *dev = wdev->netdev;
5454 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5455 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5456 struct nlattr *tb[PARAM_MAX + 1];
5457 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305458 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005459 int ret;
5460 uint32_t control;
5461 static const struct nla_policy policy[PARAM_MAX + 1] = {
5462 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5463 [PARAM_CONTROL] = { .type = NLA_U32 },
5464 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5465 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5466 };
5467
Jeff Johnson1f61b612016-02-12 16:28:33 -08005468 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305470 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5471 hdd_err("invalid session id: %d", adapter->sessionId);
5472 return -EINVAL;
5473 }
5474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305476 if (ret)
5477 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005478
5479 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005480 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481 return -ENOTSUPP;
5482 }
5483
5484 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005485 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486 return -EINVAL;
5487 }
5488
5489 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005490 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005491 return -EINVAL;
5492 }
5493
5494 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005495 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 return -EINVAL;
5497 }
5498
5499 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5500 req.session_id = adapter->sessionId;
5501 control = nla_get_u32(tb[PARAM_CONTROL]);
5502
5503 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5504 req.control = true;
5505 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005506 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005507 return -EINVAL;
5508 }
5509
5510 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005511 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005512 return -EINVAL;
5513 }
5514
5515 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5516 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5517
5518 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005519 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 req.min_rssi, req.max_rssi);
5521 return -EINVAL;
5522 }
Jeff Johnson77848112016-06-29 14:52:06 -07005523 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524 req.min_rssi, req.max_rssi);
5525
5526 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5527 req.control = false;
5528 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005529 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530 return -EINVAL;
5531 }
Jeff Johnson77848112016-06-29 14:52:06 -07005532 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 req.request_id, req.session_id, req.control);
5534
5535 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305536 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005537 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 return -EINVAL;
5539 }
5540
5541 return 0;
5542}
5543
5544/*
5545 * done with short names for the global vendor params
5546 * used by __wlan_hdd_cfg80211_monitor_rssi()
5547 */
5548#undef PARAM_MAX
5549#undef PARAM_CONTROL
5550#undef PARAM_REQUEST_ID
5551#undef PARAM_MAX_RSSI
5552#undef PARAM_MIN_RSSI
5553
5554/**
5555 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5556 * @wiphy: wiphy structure pointer
5557 * @wdev: Wireless device structure pointer
5558 * @data: Pointer to the data received
5559 * @data_len: Length of @data
5560 *
5561 * Return: 0 on success; errno on failure
5562 */
5563static int
5564wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5565 const void *data, int data_len)
5566{
5567 int ret;
5568
5569 cds_ssr_protect(__func__);
5570 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5571 cds_ssr_unprotect(__func__);
5572
5573 return ret;
5574}
5575
5576/**
5577 * hdd_rssi_threshold_breached() - rssi breached NL event
5578 * @hddctx: HDD context
5579 * @data: rssi breached event data
5580 *
5581 * This function reads the rssi breached event %data and fill in the skb with
5582 * NL attributes and send up the NL event.
5583 *
5584 * Return: none
5585 */
5586void hdd_rssi_threshold_breached(void *hddctx,
5587 struct rssi_breach_event *data)
5588{
5589 hdd_context_t *hdd_ctx = hddctx;
5590 struct sk_buff *skb;
5591
5592 ENTER();
5593
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305594 if (wlan_hdd_validate_context(hdd_ctx))
5595 return;
5596 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005597 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 return;
5599 }
5600
5601 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5602 NULL,
5603 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5604 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5605 GFP_KERNEL);
5606
5607 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005608 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005609 return;
5610 }
5611
Jeff Johnson77848112016-06-29 14:52:06 -07005612 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005614 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5616
5617 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5618 data->request_id) ||
5619 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5620 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5621 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5622 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005623 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624 goto fail;
5625 }
5626
5627 cfg80211_vendor_event(skb, GFP_KERNEL);
5628 return;
5629
5630fail:
5631 kfree_skb(skb);
5632 return;
5633}
5634
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305635static const struct nla_policy
5636ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5637 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5638};
5639
5640/**
5641 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5642 * @wiphy: Pointer to wireless phy
5643 * @wdev: Pointer to wireless device
5644 * @data: Pointer to data
5645 * @data_len: Length of @data
5646 *
5647 * Return: 0 on success, negative errno on failure
5648 */
5649static int
5650__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5651 struct wireless_dev *wdev,
5652 const void *data, int data_len)
5653{
5654 int status;
5655 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5656 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005657 struct net_device *dev = wdev->netdev;
5658 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305659
5660 ENTER_DEV(wdev->netdev);
5661
5662 status = wlan_hdd_validate_context(pHddCtx);
5663 if (0 != status)
5664 return status;
5665 if (!pHddCtx->config->fhostNSOffload) {
5666 hdd_err("ND Offload not supported");
5667 return -EINVAL;
5668 }
5669
5670 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5671 (struct nlattr *)data,
5672 data_len, ns_offload_set_policy)) {
5673 hdd_err("nla_parse failed");
5674 return -EINVAL;
5675 }
5676
5677 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5678 hdd_err("ND Offload flag attribute not present");
5679 return -EINVAL;
5680 }
5681
5682 pHddCtx->ns_offload_enable =
5683 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5684
Dustin Brownd8279d22016-09-07 14:52:57 -07005685 /* update ns offload in case it is already enabled/disabled */
5686 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5687
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305688 return 0;
5689}
5690
5691/**
5692 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5693 * @wiphy: pointer to wireless wiphy structure.
5694 * @wdev: pointer to wireless_dev structure.
5695 * @data: Pointer to the data to be passed via vendor interface
5696 * @data_len:Length of the data to be passed
5697 *
5698 * Return: Return the Success or Failure code.
5699 */
5700static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5701 struct wireless_dev *wdev,
5702 const void *data, int data_len)
5703{
5704 int ret;
5705
5706 cds_ssr_protect(__func__);
5707 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5708 cds_ssr_unprotect(__func__);
5709
5710 return ret;
5711}
5712
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005713/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5714 * @wiphy: Pointer to wireless phy
5715 * @wdev: Pointer to wireless device
5716 * @data: Pointer to data
5717 * @data_len: Data length
5718 *
5719 * This function return the preferred frequency list generated by the policy
5720 * manager.
5721 *
5722 * Return: success or failure code
5723 */
5724static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5725 struct wireless_dev
5726 *wdev, const void *data,
5727 int data_len)
5728{
5729 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5730 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305731 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305732 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305734 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735 enum cds_con_mode intf_mode;
5736 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5737 struct sk_buff *reply_skb;
5738
Jeff Johnson1f61b612016-02-12 16:28:33 -08005739 ENTER_DEV(wdev->netdev);
5740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005741 ret = wlan_hdd_validate_context(hdd_ctx);
5742 if (ret)
5743 return -EINVAL;
5744
5745 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5746 data, data_len, NULL)) {
5747 hdd_err("Invalid ATTR");
5748 return -EINVAL;
5749 }
5750
5751 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5752 hdd_err("attr interface type failed");
5753 return -EINVAL;
5754 }
5755
5756 intf_mode = nla_get_u32(tb
5757 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5758
5759 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5760 hdd_err("Invalid interface type");
5761 return -EINVAL;
5762 }
5763
5764 hdd_debug("Userspace requested pref freq list");
5765
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305766 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5767 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305768 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005769 hdd_err("Get pcl failed");
5770 return -EINVAL;
5771 }
5772
5773 /* convert channel number to frequency */
5774 for (i = 0; i < pcl_len; i++) {
5775 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5776 freq_list[i] =
5777 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005778 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 else
5780 freq_list[i] =
5781 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005782 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005783 }
5784
5785 /* send the freq_list back to supplicant */
5786 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5787 sizeof(u32) *
5788 pcl_len +
5789 NLMSG_HDRLEN);
5790
5791 if (!reply_skb) {
5792 hdd_err("Allocate reply_skb failed");
5793 return -EINVAL;
5794 }
5795
5796 if (nla_put_u32(reply_skb,
5797 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5798 intf_mode) ||
5799 nla_put(reply_skb,
5800 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5801 sizeof(uint32_t) * pcl_len,
5802 freq_list)) {
5803 hdd_err("nla put fail");
5804 kfree_skb(reply_skb);
5805 return -EINVAL;
5806 }
5807
5808 return cfg80211_vendor_cmd_reply(reply_skb);
5809}
5810
5811/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5812 * @wiphy: Pointer to wireless phy
5813 * @wdev: Pointer to wireless device
5814 * @data: Pointer to data
5815 * @data_len: Data length
5816 *
5817 * This function return the preferred frequency list generated by the policy
5818 * manager.
5819 *
5820 * Return: success or failure code
5821 */
5822static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5823 struct wireless_dev
5824 *wdev, const void *data,
5825 int data_len)
5826{
5827 int ret = 0;
5828
5829 cds_ssr_protect(__func__);
5830 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5831 data, data_len);
5832 cds_ssr_unprotect(__func__);
5833
5834 return ret;
5835}
5836
5837/**
5838 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5839 * @wiphy: Pointer to wireless phy
5840 * @wdev: Pointer to wireless device
5841 * @data: Pointer to data
5842 * @data_len: Data length
5843 *
5844 * Return: 0 on success, negative errno on failure
5845 */
5846static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5847 struct wireless_dev *wdev,
5848 const void *data,
5849 int data_len)
5850{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305851 struct net_device *ndev = wdev->netdev;
5852 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5854 int ret = 0;
5855 enum cds_con_mode intf_mode;
5856 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5857 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005858
Jeff Johnson1f61b612016-02-12 16:28:33 -08005859 ENTER_DEV(ndev);
5860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 ret = wlan_hdd_validate_context(hdd_ctx);
5862 if (ret)
5863 return ret;
5864
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5866 data, data_len, NULL)) {
5867 hdd_err("Invalid ATTR");
5868 return -EINVAL;
5869 }
5870
5871 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5872 hdd_err("attr interface type failed");
5873 return -EINVAL;
5874 }
5875
5876 intf_mode = nla_get_u32(tb
5877 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5878
5879 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5880 hdd_err("Invalid interface type");
5881 return -EINVAL;
5882 }
5883
5884 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5885 hdd_err("attr probable freq failed");
5886 return -EINVAL;
5887 }
5888
5889 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5890 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5891
5892 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005893 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005894 channel_hint, HW_MODE_20_MHZ)) {
5895 hdd_err("Set channel hint failed due to concurrency check");
5896 return -EINVAL;
5897 }
5898
Krunal Soni09e55032016-06-07 10:06:55 -07005899 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5900 hdd_warn("Remain On Channel Pending");
5901
Krunal Soni3091bcc2016-06-23 12:28:21 -07005902 ret = qdf_reset_connection_update();
5903 if (!QDF_IS_STATUS_SUCCESS(ret))
5904 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905
Krunal Soni3091bcc2016-06-23 12:28:21 -07005906 ret = cds_current_connections_update(adapter->sessionId,
5907 channel_hint,
5908 SIR_UPDATE_REASON_SET_OPER_CHAN);
5909 if (QDF_STATUS_E_FAILURE == ret) {
5910 /* return in the failure case */
5911 hdd_err("ERROR: connections update failed!!");
5912 return -EINVAL;
5913 }
5914
5915 if (QDF_STATUS_SUCCESS == ret) {
5916 /*
5917 * Success is the only case for which we expect hw mode
5918 * change to take place, hence we need to wait.
5919 * For any other return value it should be a pass
5920 * through
5921 */
5922 ret = qdf_wait_for_connection_update();
5923 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5924 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005925 return -EINVAL;
5926 }
5927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 }
5929
5930 return 0;
5931}
5932
5933/**
5934 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5935 * @wiphy: Pointer to wireless phy
5936 * @wdev: Pointer to wireless device
5937 * @data: Pointer to data
5938 * @data_len: Data length
5939 *
5940 * Return: 0 on success, negative errno on failure
5941 */
5942static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5943 struct wireless_dev *wdev,
5944 const void *data,
5945 int data_len)
5946{
5947 int ret = 0;
5948
5949 cds_ssr_protect(__func__);
5950 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5951 data, data_len);
5952 cds_ssr_unprotect(__func__);
5953
5954 return ret;
5955}
5956
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305957static const struct
5958nla_policy
5959qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5960 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5961};
5962
5963/**
5964 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5965 * @wiphy: WIPHY structure pointer
5966 * @wdev: Wireless device structure pointer
5967 * @data: Pointer to the data received
5968 * @data_len: Length of the data received
5969 *
5970 * This function is used to get link properties like nss, rate flags and
5971 * operating frequency for the active connection with the given peer.
5972 *
5973 * Return: 0 on success and errno on failure
5974 */
5975static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5976 struct wireless_dev *wdev,
5977 const void *data,
5978 int data_len)
5979{
5980 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5981 struct net_device *dev = wdev->netdev;
5982 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5983 hdd_station_ctx_t *hdd_sta_ctx;
5984 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305985 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305986 uint32_t sta_id;
5987 struct sk_buff *reply_skb;
5988 uint32_t rate_flags = 0;
5989 uint8_t nss;
5990 uint8_t final_rate_flags = 0;
5991 uint32_t freq;
5992
Jeff Johnson1f61b612016-02-12 16:28:33 -08005993 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305994
Anurag Chouhan6d760662016-02-20 16:05:43 +05305995 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305996 hdd_err("Command not allowed in FTM mode");
5997 return -EPERM;
5998 }
5999
6000 if (0 != wlan_hdd_validate_context(hdd_ctx))
6001 return -EINVAL;
6002
6003 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6004 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006005 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306006 return -EINVAL;
6007 }
6008
6009 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006010 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306011 adapter->device_mode);
6012 return -EINVAL;
6013 }
6014
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306015 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306016 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006017 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306018 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6019
Krunal Sonib4326f22016-03-10 13:05:51 -08006020 if (adapter->device_mode == QDF_STA_MODE ||
6021 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306022 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6023 if ((hdd_sta_ctx->conn_info.connState !=
6024 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306025 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306026 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006027 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306028 MAC_ADDR_ARRAY(peer_mac));
6029 return -EINVAL;
6030 }
6031
6032 nss = hdd_sta_ctx->conn_info.nss;
6033 freq = cds_chan_to_freq(
6034 hdd_sta_ctx->conn_info.operationChannel);
6035 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006036 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6037 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306038
6039 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6040 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306041 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306042 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306043 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306044 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306045 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306046 break;
6047 }
6048
6049 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006050 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306051 MAC_ADDR_ARRAY(peer_mac));
6052 return -EINVAL;
6053 }
6054
6055 nss = adapter->aStaInfo[sta_id].nss;
6056 freq = cds_chan_to_freq(
6057 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6058 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6059 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006060 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306061 MAC_ADDR_ARRAY(peer_mac));
6062 return -EINVAL;
6063 }
6064
6065 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6066 if (rate_flags & eHAL_TX_RATE_VHT80) {
6067 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006068#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306069 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006070#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306071 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6072 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006073#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306074 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006075#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306076 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6077 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6078 } else if (rate_flags &
6079 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6080 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006081#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306082 if (rate_flags & eHAL_TX_RATE_HT40)
6083 final_rate_flags |=
6084 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006085#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306086 }
6087
6088 if (rate_flags & eHAL_TX_RATE_SGI) {
6089 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6090 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6091 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6092 }
6093 }
6094
6095 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6096 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6097
6098 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006099 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306100 return -EINVAL;
6101 }
6102
6103 if (nla_put_u8(reply_skb,
6104 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6105 nss) ||
6106 nla_put_u8(reply_skb,
6107 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6108 final_rate_flags) ||
6109 nla_put_u32(reply_skb,
6110 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6111 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006112 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306113 kfree_skb(reply_skb);
6114 return -EINVAL;
6115 }
6116
6117 return cfg80211_vendor_cmd_reply(reply_skb);
6118}
6119
6120/**
6121 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6122 * properties.
6123 * @wiphy: WIPHY structure pointer
6124 * @wdev: Wireless device structure pointer
6125 * @data: Pointer to the data received
6126 * @data_len: Length of the data received
6127 *
6128 * This function is used to get link properties like nss, rate flags and
6129 * operating frequency for the active connection with the given peer.
6130 *
6131 * Return: 0 on success and errno on failure
6132 */
6133static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6134 struct wireless_dev *wdev,
6135 const void *data,
6136 int data_len)
6137{
6138 int ret = 0;
6139
6140 cds_ssr_protect(__func__);
6141 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6142 wdev, data, data_len);
6143 cds_ssr_unprotect(__func__);
6144
6145 return ret;
6146}
6147
Peng Xu278d0122015-09-24 16:34:17 -07006148static const struct
6149nla_policy
6150qca_wlan_vendor_ota_test_policy
6151[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6152 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6153};
6154
6155/**
6156 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6157 * @wiphy: Pointer to wireless phy
6158 * @wdev: Pointer to wireless device
6159 * @data: Pointer to data
6160 * @data_len: Data length
6161 *
6162 * Return: 0 on success, negative errno on failure
6163 */
6164static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6165 struct wireless_dev *wdev,
6166 const void *data,
6167 int data_len)
6168{
6169 struct net_device *dev = wdev->netdev;
6170 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6171 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6172 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6173 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6174 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306175 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006176 uint32_t current_roam_state;
6177
Jeff Johnson1f61b612016-02-12 16:28:33 -08006178 ENTER_DEV(dev);
6179
Anurag Chouhan6d760662016-02-20 16:05:43 +05306180 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006181 hdd_err("Command not allowed in FTM mode");
6182 return -EPERM;
6183 }
6184
6185 if (0 != wlan_hdd_validate_context(hdd_ctx))
6186 return -EINVAL;
6187
6188 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6189 data, data_len,
6190 qca_wlan_vendor_ota_test_policy)) {
6191 hdd_err("invalid attr");
6192 return -EINVAL;
6193 }
6194
6195 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6196 hdd_err("attr ota test failed");
6197 return -EINVAL;
6198 }
6199
6200 ota_enable = nla_get_u8(
6201 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6202
6203 hdd_info(" OTA test enable = %d", ota_enable);
6204 if (ota_enable != 1) {
6205 hdd_err("Invalid value, only enable test mode is supported!");
6206 return -EINVAL;
6207 }
6208
6209 current_roam_state =
6210 sme_get_current_roam_state(hal, adapter->sessionId);
6211 status = sme_stop_roaming(hal, adapter->sessionId,
6212 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306213 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006214 hdd_err("Enable/Disable roaming failed");
6215 return -EINVAL;
6216 }
6217
6218 status = sme_ps_enable_disable(hal, adapter->sessionId,
6219 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306220 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006221 hdd_err("Enable/Disable power save failed");
6222 /* restore previous roaming setting */
6223 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6224 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6225 status = sme_start_roaming(hal, adapter->sessionId,
6226 eCsrHddIssued);
6227 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6228 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6229 status = sme_stop_roaming(hal, adapter->sessionId,
6230 eCsrHddIssued);
6231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306232 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006233 hdd_err("Restoring roaming state failed");
6234
6235 return -EINVAL;
6236 }
6237
6238
6239 return 0;
6240}
6241
6242/**
6243 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6244 * @wiphy: Pointer to wireless phy
6245 * @wdev: Pointer to wireless device
6246 * @data: Pointer to data
6247 * @data_len: Data length
6248 *
6249 * Return: 0 on success, negative errno on failure
6250 */
6251static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6252 struct wireless_dev *wdev,
6253 const void *data,
6254 int data_len)
6255{
6256 int ret = 0;
6257
6258 cds_ssr_protect(__func__);
6259 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6260 cds_ssr_unprotect(__func__);
6261
6262 return ret;
6263}
6264
Peng Xu4d67c8f2015-10-16 16:02:26 -07006265/**
6266 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6267 * @wiphy: Pointer to wireless phy
6268 * @wdev: Pointer to wireless device
6269 * @data: Pointer to data
6270 * @data_len: Data length
6271 *
6272 * Return: 0 on success, negative errno on failure
6273 */
6274static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6275 struct wireless_dev *wdev,
6276 const void *data,
6277 int data_len)
6278{
6279 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6280 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006281 hdd_adapter_t *adapter;
6282 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006283 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6284 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006285 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006286
Jeff Johnson1f61b612016-02-12 16:28:33 -08006287 ENTER_DEV(dev);
6288
Peng Xu4d67c8f2015-10-16 16:02:26 -07006289 ret = wlan_hdd_validate_context(hdd_ctx);
6290 if (ret)
6291 return ret;
6292
6293 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6294
6295 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6296 data, data_len, NULL)) {
6297 hdd_err("Invalid ATTR");
6298 return -EINVAL;
6299 }
6300
6301 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6302 hdd_err("attr tx power scale failed");
6303 return -EINVAL;
6304 }
6305
6306 scale_value = nla_get_u8(tb
6307 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6308
6309 if (scale_value > MAX_TXPOWER_SCALE) {
6310 hdd_err("Invalid tx power scale level");
6311 return -EINVAL;
6312 }
6313
Peng Xu62c8c432016-05-09 15:23:02 -07006314 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006315
Peng Xu62c8c432016-05-09 15:23:02 -07006316 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006317 hdd_err("Set tx power scale failed");
6318 return -EINVAL;
6319 }
6320
6321 return 0;
6322}
6323
6324/**
6325 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6326 * @wiphy: Pointer to wireless phy
6327 * @wdev: Pointer to wireless device
6328 * @data: Pointer to data
6329 * @data_len: Data length
6330 *
6331 * Return: 0 on success, negative errno on failure
6332 */
6333static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6334 struct wireless_dev *wdev,
6335 const void *data,
6336 int data_len)
6337{
Peng Xu62c8c432016-05-09 15:23:02 -07006338 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006339
6340 cds_ssr_protect(__func__);
6341 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6342 data, data_len);
6343 cds_ssr_unprotect(__func__);
6344
6345 return ret;
6346}
6347
6348/**
6349 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6350 * @wiphy: Pointer to wireless phy
6351 * @wdev: Pointer to wireless device
6352 * @data: Pointer to data
6353 * @data_len: Data length
6354 *
6355 * Return: 0 on success, negative errno on failure
6356 */
6357static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6358 struct wireless_dev *wdev,
6359 const void *data,
6360 int data_len)
6361{
6362 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6363 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006364 hdd_adapter_t *adapter;
6365 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006366 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6367 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006368 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006369
Jeff Johnson1f61b612016-02-12 16:28:33 -08006370 ENTER_DEV(dev);
6371
Peng Xu4d67c8f2015-10-16 16:02:26 -07006372 ret = wlan_hdd_validate_context(hdd_ctx);
6373 if (ret)
6374 return ret;
6375
6376 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6377
6378 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6379 data, data_len, NULL)) {
6380 hdd_err("Invalid ATTR");
6381 return -EINVAL;
6382 }
6383
6384 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6385 hdd_err("attr tx power decrease db value failed");
6386 return -EINVAL;
6387 }
6388
6389 scale_value = nla_get_u8(tb
6390 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6391
Peng Xu62c8c432016-05-09 15:23:02 -07006392 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6393 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006394
Peng Xu62c8c432016-05-09 15:23:02 -07006395 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006396 hdd_err("Set tx power decrease db failed");
6397 return -EINVAL;
6398 }
6399
6400 return 0;
6401}
6402
6403/**
6404 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6405 * @wiphy: Pointer to wireless phy
6406 * @wdev: Pointer to wireless device
6407 * @data: Pointer to data
6408 * @data_len: Data length
6409 *
6410 * Return: 0 on success, negative errno on failure
6411 */
6412static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6413 struct wireless_dev *wdev,
6414 const void *data,
6415 int data_len)
6416{
Peng Xu62c8c432016-05-09 15:23:02 -07006417 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006418
6419 cds_ssr_protect(__func__);
6420 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6421 data, data_len);
6422 cds_ssr_unprotect(__func__);
6423
6424 return ret;
6425}
Peng Xu8fdaa492016-06-22 10:20:47 -07006426
6427/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306428 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6429 * @wiphy: Pointer to wireless phy
6430 * @wdev: Pointer to wireless device
6431 * @data: Pointer to data
6432 * @data_len: Data length
6433 *
6434 * Processes the conditional channel switch request and invokes the helper
6435 * APIs to process the channel switch request.
6436 *
6437 * Return: 0 on success, negative errno on failure
6438 */
6439static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6440 struct wireless_dev *wdev,
6441 const void *data,
6442 int data_len)
6443{
6444 int ret;
6445 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6446 struct net_device *dev = wdev->netdev;
6447 hdd_adapter_t *adapter;
6448 struct nlattr
6449 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6450 uint32_t freq_len, i;
6451 uint32_t *freq;
6452 uint8_t chans[QDF_MAX_NUM_CHAN];
6453
6454 ENTER_DEV(dev);
6455
6456 ret = wlan_hdd_validate_context(hdd_ctx);
6457 if (ret)
6458 return ret;
6459
6460 if (!hdd_ctx->config->enableDFSMasterCap) {
6461 hdd_err("DFS master capability is not present in the driver");
6462 return -EINVAL;
6463 }
6464
6465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6466 hdd_err("Command not allowed in FTM mode");
6467 return -EPERM;
6468 }
6469
6470 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6471 if (adapter->device_mode != QDF_SAP_MODE) {
6472 hdd_err("Invalid device mode %d", adapter->device_mode);
6473 return -EINVAL;
6474 }
6475
6476 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6477 data, data_len, NULL)) {
6478 hdd_err("Invalid ATTR");
6479 return -EINVAL;
6480 }
6481
6482 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6483 hdd_err("Frequency list is missing");
6484 return -EINVAL;
6485 }
6486
6487 freq_len = nla_len(
6488 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6489 sizeof(uint32_t);
6490
6491 if (freq_len > QDF_MAX_NUM_CHAN) {
6492 hdd_err("insufficient space to hold channels");
6493 return -ENOMEM;
6494 }
6495
6496 hdd_debug("freq_len=%d", freq_len);
6497
6498 freq = nla_data(
6499 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6500
6501
6502 for (i = 0; i < freq_len; i++) {
6503 if (freq[i] == 0)
6504 chans[i] = 0;
6505 else
6506 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6507
6508 hdd_debug("freq[%d]=%d", i, freq[i]);
6509 }
6510
6511 /*
6512 * The input frequency list from user space is designed to be a
6513 * priority based frequency list. This is only to accommodate any
6514 * future request. But, current requirement is only to perform CAC
6515 * on a single channel. So, the first entry from the list is picked.
6516 *
6517 * If channel is zero, any channel in the available outdoor regulatory
6518 * domain will be selected.
6519 */
6520 ret = wlan_hdd_request_pre_cac(chans[0]);
6521 if (ret) {
6522 hdd_err("pre cac request failed with reason:%d", ret);
6523 return ret;
6524 }
6525
6526 return 0;
6527}
6528
6529/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006530 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6531 * @wiphy: Pointer to wireless phy
6532 * @wdev: Pointer to wireless device
6533 * @data: Pointer to data
6534 * @data_len: Data length
6535 *
6536 * This function is to process the p2p listen offload start vendor
6537 * command. It parses the input parameters and invoke WMA API to
6538 * send the command to firmware.
6539 *
6540 * Return: 0 on success, negative errno on failure
6541 */
6542static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6543 struct wireless_dev *wdev,
6544 const void *data,
6545 int data_len)
6546{
6547 int ret;
6548 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6549 struct net_device *dev = wdev->netdev;
6550 hdd_adapter_t *adapter;
6551 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6552 struct sir_p2p_lo_start params;
6553 QDF_STATUS status;
6554
6555 ENTER_DEV(dev);
6556
6557 ret = wlan_hdd_validate_context(hdd_ctx);
6558 if (ret)
6559 return ret;
6560
6561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6562 hdd_err("Command not allowed in FTM mode");
6563 return -EPERM;
6564 }
6565
6566 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6567 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6568 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6569 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6570 hdd_err("Invalid device mode %d", adapter->device_mode);
6571 return -EINVAL;
6572 }
6573
6574 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6575 data, data_len, NULL)) {
6576 hdd_err("Invalid ATTR");
6577 return -EINVAL;
6578 }
6579
6580 memset(&params, 0, sizeof(params));
6581
6582 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6583 params.ctl_flags = 1; /* set to default value */
6584 else
6585 params.ctl_flags = nla_get_u32(tb
6586 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6587
6588 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6589 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6590 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6591 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6592 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6593 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6594 hdd_err("Attribute parsing failed");
6595 return -EINVAL;
6596 }
6597
6598 params.vdev_id = adapter->sessionId;
6599 params.freq = nla_get_u32(tb
6600 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6601 if ((params.freq != 2412) && (params.freq != 2437) &&
6602 (params.freq != 2462)) {
6603 hdd_err("Invalid listening channel: %d", params.freq);
6604 return -EINVAL;
6605 }
6606
6607 params.period = nla_get_u32(tb
6608 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6609 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6610 hdd_err("Invalid period: %d", params.period);
6611 return -EINVAL;
6612 }
6613
6614 params.interval = nla_get_u32(tb
6615 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6616 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6617 hdd_err("Invalid interval: %d", params.interval);
6618 return -EINVAL;
6619 }
6620
6621 params.count = nla_get_u32(tb
6622 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006623 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006624 hdd_err("Invalid count: %d", params.count);
6625 return -EINVAL;
6626 }
6627
6628 params.device_types = nla_data(tb
6629 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6630 if (params.device_types == NULL) {
6631 hdd_err("Invalid device types");
6632 return -EINVAL;
6633 }
6634
6635 params.dev_types_len = nla_len(tb
6636 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6637 if (params.dev_types_len < 8) {
6638 hdd_err("Invalid device type length: %d", params.dev_types_len);
6639 return -EINVAL;
6640 }
6641
6642 params.probe_resp_tmplt = nla_data(tb
6643 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6644 if (params.probe_resp_tmplt == NULL) {
6645 hdd_err("Invalid probe response template");
6646 return -EINVAL;
6647 }
6648
6649 params.probe_resp_len = nla_len(tb
6650 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6651 if (params.probe_resp_len == 0) {
6652 hdd_err("Invalid probe resp template length: %d",
6653 params.probe_resp_len);
6654 return -EINVAL;
6655 }
6656
6657 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6658 params.freq, params.period, params.interval, params.count);
6659
6660 status = wma_p2p_lo_start(&params);
6661
6662 if (!QDF_IS_STATUS_SUCCESS(status)) {
6663 hdd_err("P2P LO start failed");
6664 return -EINVAL;
6665 }
6666
6667 return 0;
6668}
6669
6670
6671/**
6672 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6673 * @wiphy: Pointer to wireless phy
6674 * @wdev: Pointer to wireless device
6675 * @data: Pointer to data
6676 * @data_len: Data length
6677 *
6678 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6679 * to process p2p listen offload start vendor command.
6680 *
6681 * Return: 0 on success, negative errno on failure
6682 */
6683static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6684 struct wireless_dev *wdev,
6685 const void *data,
6686 int data_len)
6687{
6688 int ret = 0;
6689
6690 cds_ssr_protect(__func__);
6691 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6692 data, data_len);
6693 cds_ssr_unprotect(__func__);
6694
6695 return ret;
6696}
6697
6698/**
6699 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6700 * @wiphy: Pointer to wireless phy
6701 * @wdev: Pointer to wireless device
6702 * @data: Pointer to data
6703 * @data_len: Data length
6704 *
6705 * This function is to process the p2p listen offload stop vendor
6706 * command. It invokes WMA API to send command to firmware.
6707 *
6708 * Return: 0 on success, negative errno on failure
6709 */
6710static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6711 struct wireless_dev *wdev,
6712 const void *data,
6713 int data_len)
6714{
6715 QDF_STATUS status;
6716 hdd_adapter_t *adapter;
6717 struct net_device *dev = wdev->netdev;
6718
6719 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6720 hdd_err("Command not allowed in FTM mode");
6721 return -EPERM;
6722 }
6723
6724 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6725 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6726 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6727 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6728 hdd_err("Invalid device mode");
6729 return -EINVAL;
6730 }
6731
6732 status = wma_p2p_lo_stop(adapter->sessionId);
6733
6734 if (!QDF_IS_STATUS_SUCCESS(status)) {
6735 hdd_err("P2P LO stop failed");
6736 return -EINVAL;
6737 }
6738
6739 return 0;
6740}
6741
6742/**
6743 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6744 * @wiphy: Pointer to wireless phy
6745 * @wdev: Pointer to wireless device
6746 * @data: Pointer to data
6747 * @data_len: Data length
6748 *
6749 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6750 * to process p2p listen offload stop vendor command.
6751 *
6752 * Return: 0 on success, negative errno on failure
6753 */
6754static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6755 struct wireless_dev *wdev,
6756 const void *data,
6757 int data_len)
6758{
6759 int ret = 0;
6760
6761 cds_ssr_protect(__func__);
6762 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6763 data, data_len);
6764 cds_ssr_unprotect(__func__);
6765
6766 return ret;
6767}
6768
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306769/**
6770 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6771 * @wiphy: Pointer to wireless phy
6772 * @wdev: Pointer to wireless device
6773 * @data: Pointer to data
6774 * @data_len: Data length
6775 *
6776 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6777 * to process the conditional channel switch request.
6778 *
6779 * Return: 0 on success, negative errno on failure
6780 */
6781static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6782 struct wireless_dev *wdev,
6783 const void *data,
6784 int data_len)
6785{
6786 int ret;
6787
6788 cds_ssr_protect(__func__);
6789 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6790 data, data_len);
6791 cds_ssr_unprotect(__func__);
6792
6793 return ret;
6794}
6795
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306796/*
6797 * define short names for the global vendor params
6798 * used by __wlan_hdd_cfg80211_bpf_offload()
6799 */
6800#define BPF_INVALID \
6801 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6802#define BPF_SET_RESET \
6803 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6804#define BPF_VERSION \
6805 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6806#define BPF_FILTER_ID \
6807 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6808#define BPF_PACKET_SIZE \
6809 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6810#define BPF_CURRENT_OFFSET \
6811 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6812#define BPF_PROGRAM \
6813 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6814#define BPF_MAX \
6815 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006816
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306817static const struct nla_policy
6818wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6819 [BPF_SET_RESET] = {.type = NLA_U32},
6820 [BPF_VERSION] = {.type = NLA_U32},
6821 [BPF_FILTER_ID] = {.type = NLA_U32},
6822 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6823 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6824 [BPF_PROGRAM] = {.type = NLA_U8},
6825};
6826
6827/**
6828 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6829 * @hdd_context: hdd_context
6830 * @bpf_get_offload: struct for get offload
6831 *
6832 * This function receives the response/data from the lower layer and
6833 * checks to see if the thread is still waiting then post the results to
6834 * upper layer, if the request has timed out then ignore.
6835 *
6836 * Return: None
6837 */
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006838static void hdd_get_bpf_offload_cb(void *hdd_context,
6839 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306840{
6841 hdd_context_t *hdd_ctx = hdd_context;
6842 struct hdd_bpf_context *context;
6843
6844 ENTER();
6845
6846 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006847 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306848 data);
6849 return;
6850 }
6851
6852 spin_lock(&hdd_context_lock);
6853
6854 context = &bpf_context;
6855 /* The caller presumably timed out so there is nothing we can do */
6856 if (context->magic != BPF_CONTEXT_MAGIC) {
6857 spin_unlock(&hdd_context_lock);
6858 return;
6859 }
6860
6861 /* context is valid so caller is still waiting */
6862 /* paranoia: invalidate the magic */
6863 context->magic = 0;
6864
6865 context->capability_response = *data;
6866 complete(&context->completion);
6867
6868 spin_unlock(&hdd_context_lock);
6869
6870 return;
6871}
6872
6873/**
6874 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6875 * @hdd_context: hdd_context
6876 * @bpf_get_offload: struct for get offload
6877 *
6878 * Return: 0 on success, error number otherwise.
6879 */
6880static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6881 struct sir_bpf_get_offload *bpf_get_offload)
6882{
6883 struct sk_buff *skb;
6884 uint32_t nl_buf_len;
6885
6886 ENTER();
6887
6888 nl_buf_len = NLMSG_HDRLEN;
6889 nl_buf_len +=
6890 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6891 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6892
6893 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6894 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006895 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306896 return -ENOMEM;
6897 }
6898
Jeff Johnson77848112016-06-29 14:52:06 -07006899 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306900 bpf_get_offload->bpf_version,
6901 bpf_get_offload->max_bytes_for_bpf_inst);
6902
6903 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6904 bpf_get_offload->max_bytes_for_bpf_inst) ||
6905 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006906 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306907 goto nla_put_failure;
6908 }
6909
6910 cfg80211_vendor_cmd_reply(skb);
6911 EXIT();
6912 return 0;
6913
6914nla_put_failure:
6915 kfree_skb(skb);
6916 return -EINVAL;
6917}
6918
6919/**
6920 * hdd_get_bpf_offload - Get BPF offload Capabilities
6921 * @hdd_ctx: Hdd context
6922 *
6923 * Return: 0 on success, errno on failure
6924 */
6925static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6926{
6927 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006928 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306929 QDF_STATUS status;
6930 int ret;
6931
6932 ENTER();
6933
6934 spin_lock(&hdd_context_lock);
6935 context = &bpf_context;
6936 context->magic = BPF_CONTEXT_MAGIC;
6937 INIT_COMPLETION(context->completion);
6938 spin_unlock(&hdd_context_lock);
6939
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006940 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6941 hdd_get_bpf_offload_cb,
6942 hdd_ctx);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306943 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006944 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306945 return -EINVAL;
6946 }
6947 /* request was sent -- wait for the response */
6948 rc = wait_for_completion_timeout(&context->completion,
6949 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6950 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006951 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306952 spin_lock(&hdd_context_lock);
6953 context->magic = 0;
6954 spin_unlock(&hdd_context_lock);
6955
6956 return -ETIMEDOUT;
6957 }
6958 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6959 &bpf_context.capability_response);
6960 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006961 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306962
6963 EXIT();
6964 return ret;
6965}
6966
6967/**
6968 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6969 * @hdd_ctx: Hdd context
6970 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306971 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306972 *
6973 * Return: 0 on success; errno on failure
6974 */
6975static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6976 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306977 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306978{
6979 struct sir_bpf_set_offload *bpf_set_offload;
6980 QDF_STATUS status;
6981 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306982 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983
6984 ENTER();
6985
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306986 if (adapter->device_mode == QDF_STA_MODE ||
6987 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6988 if (!hdd_conn_is_connected(
6989 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6990 hdd_err("Not in Connected state!");
6991 return -ENOTSUPP;
6992 }
6993 }
6994
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306995 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6996 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006997 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306998 return -ENOMEM;
6999 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000
7001 /* Parse and fetch bpf packet size */
7002 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007003 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307004 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307005 goto fail;
7006 }
7007 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7008
7009 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007010 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307011 goto post_sme;
7012 }
7013
7014 /* Parse and fetch bpf program */
7015 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007016 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307017 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307018 goto fail;
7019 }
7020
7021 prog_len = nla_len(tb[BPF_PROGRAM]);
7022 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307023
7024 if (bpf_set_offload->program == NULL) {
7025 hdd_err("qdf_mem_malloc failed for bpf offload program");
7026 ret = -ENOMEM;
7027 goto fail;
7028 }
7029
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307030 bpf_set_offload->current_length = prog_len;
7031 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307032 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307033
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307034 hdd_info("BPF set instructions");
7035 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7036 bpf_set_offload->program, prog_len);
7037
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307038 /* Parse and fetch filter Id */
7039 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007040 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307041 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307042 goto fail;
7043 }
7044 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7045
7046 /* Parse and fetch current offset */
7047 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007048 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307049 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307050 goto fail;
7051 }
7052 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7053
7054post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007055 hdd_notice("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307056 bpf_set_offload->session_id,
7057 bpf_set_offload->version,
7058 bpf_set_offload->filter_id,
7059 bpf_set_offload->total_length,
7060 bpf_set_offload->current_length,
7061 bpf_set_offload->current_offset);
7062
7063 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7064 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007065 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307066 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307067 goto fail;
7068 }
7069 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307070
7071fail:
7072 if (bpf_set_offload->current_length)
7073 qdf_mem_free(bpf_set_offload->program);
7074 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307075 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076}
7077
7078/**
7079 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7080 * @wiphy: wiphy structure pointer
7081 * @wdev: Wireless device structure pointer
7082 * @data: Pointer to the data received
7083 * @data_len: Length of @data
7084 *
7085 * Return: 0 on success; errno on failure
7086 */
7087static int
7088__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7089 struct wireless_dev *wdev,
7090 const void *data, int data_len)
7091{
7092 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7093 struct net_device *dev = wdev->netdev;
7094 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7095 struct nlattr *tb[BPF_MAX + 1];
7096 int ret_val, packet_filter_subcmd;
7097
7098 ENTER();
7099
7100 ret_val = wlan_hdd_validate_context(hdd_ctx);
7101 if (ret_val)
7102 return ret_val;
7103
7104 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007105 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307106 return -EINVAL;
7107 }
7108
7109 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007110 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307111 return -ENOTSUPP;
7112 }
7113
7114 if (nla_parse(tb, BPF_MAX, data, data_len,
7115 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007116 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307117 return -EINVAL;
7118 }
7119
7120 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007121 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307122 return -EINVAL;
7123 }
7124
7125 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7126
7127 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7128 return hdd_get_bpf_offload(hdd_ctx);
7129 else
7130 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307131 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307132}
7133
7134/**
7135 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7136 * @wiphy: wiphy structure pointer
7137 * @wdev: Wireless device structure pointer
7138 * @data: Pointer to the data received
7139 * @data_len: Length of @data
7140 *
7141 * Return: 0 on success; errno on failure
7142 */
7143
7144static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7145 struct wireless_dev *wdev,
7146 const void *data, int data_len)
7147{
7148 int ret;
7149
7150 cds_ssr_protect(__func__);
7151 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7152 cds_ssr_unprotect(__func__);
7153
7154 return ret;
7155}
7156
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307157/**
7158 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7159 * @pre_cac_adapter: AP adapter used for pre cac
7160 * @status: Status (true or false)
7161 * @handle: Global handle
7162 *
7163 * Sets the status of pre cac i.e., whether the pre cac is active or not
7164 *
7165 * Return: Zero on success, non-zero on failure
7166 */
7167static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7168 bool status, tHalHandle handle)
7169{
7170 QDF_STATUS ret;
7171
7172 ret = wlan_sap_set_pre_cac_status(
7173 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7174 if (QDF_IS_STATUS_ERROR(ret))
7175 return -EINVAL;
7176
7177 return 0;
7178}
7179
7180/**
7181 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7182 * @ap_adapter: AP adapter
7183 * @chan_before_pre_cac: Channel
7184 *
7185 * Saves the channel which the AP was beaconing on before moving to the pre
7186 * cac channel. If radar is detected on the pre cac channel, this saved
7187 * channel will be used for AP operations.
7188 *
7189 * Return: Zero on success, non-zero on failure
7190 */
7191static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7192 uint8_t chan_before_pre_cac)
7193{
7194 QDF_STATUS ret;
7195
7196 ret = wlan_sap_set_chan_before_pre_cac(
7197 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7198 if (QDF_IS_STATUS_ERROR(ret))
7199 return -EINVAL;
7200
7201 return 0;
7202}
7203
7204/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307205 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7206 * are in nol list from provided channel list
7207 * @adapter: AP adapter
7208 * @channel_count: channel count
7209 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307210 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307211 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307212 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307213static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7214 uint32_t *channel_count,
7215 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307216{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307217 uint8_t i, j;
7218 uint32_t nol_len = 0;
7219 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7220 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7221 uint32_t chan_count;
7222 bool found;
7223 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307224
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307225 if (!hdd_ctx) {
7226 hdd_err("hdd ctx not found");
7227 *channel_count = 0;
7228 return;
7229 }
7230
7231 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7232 hdd_err("invalid channel count %d", *channel_count);
7233 return;
7234 }
7235
7236 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7237 if (nol_len == 0)
7238 return;
7239
7240 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7241 chan_count = *channel_count;
7242 qdf_mem_zero(channel_list, chan_count);
7243 *channel_count = 0;
7244
7245 for (i = 0 ; i < chan_count; i++) {
7246 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7247 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7248 continue;
7249 found = false;
7250 for (j = 0; j < nol_len; j++) {
7251 if (tmp_chan_list[i] == nol[j]) {
7252 found = true;
7253 hdd_notice("skipped channel %d due to nol",
7254 nol[j]);
7255 break;
7256 }
7257 }
7258 if (!found) {
7259 channel_list[*channel_count] = tmp_chan_list[i];
7260 *channel_count = *channel_count + 1;
7261 }
7262 }
7263}
7264
7265int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7266 uint32_t *channel_count,
7267 uint8_t *channel_list)
7268{
7269 tsap_Config_t *sap_config;
7270
7271 sap_config = &adapter->sessionCtx.ap.sapConfig;
7272
7273 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7274 sap_config->acs_cfg.ch_list_count);
7275 *channel_count = sap_config->acs_cfg.ch_list_count;
7276 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7277
7278 if (*channel_count == 0) {
7279 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307280 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307281 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307282
7283 return 0;
7284}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307285
7286/**
7287 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7288 * @hdd_ctx: HDD context
7289 * @ap_adapter: AP adapter
7290 * @channel: Channel requested by userspace
7291 * @pre_cac_chan: Pointer to the pre CAC channel
7292 *
7293 * Validates the channel provided by userspace. If user provided channel 0,
7294 * a valid outdoor channel must be selected from the regulatory channel.
7295 *
7296 * Return: Zero on success and non zero value on error
7297 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007298static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7299 hdd_adapter_t *ap_adapter,
7300 uint8_t channel,
7301 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307302{
7303 uint32_t i, j;
7304 QDF_STATUS status;
7305 int ret;
7306 uint8_t nol[QDF_MAX_NUM_CHAN];
7307 uint32_t nol_len = 0, weight_len = 0;
7308 bool found;
7309 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7310 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7311 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7312
7313 if (0 == channel) {
7314 /* Channel is not obtained from PCL because PCL may not have
7315 * the entire channel list. For example: if SAP is up on
7316 * channel 6 and PCL is queried for the next SAP interface,
7317 * if SCC is preferred, the PCL will contain only the channel
7318 * 6. But, we are in need of a DFS channel. So, going with the
7319 * first channel from the valid channel list.
7320 */
7321 status = cds_get_valid_chans(channel_list, &len);
7322 if (QDF_IS_STATUS_ERROR(status)) {
7323 hdd_err("Failed to get channel list");
7324 return -EINVAL;
7325 }
7326 cds_update_with_safe_channel_list(channel_list, &len,
7327 pcl_weights, weight_len);
7328 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7329 for (i = 0; i < len; i++) {
7330 found = false;
7331 for (j = 0; j < nol_len; j++) {
7332 if (channel_list[i] == nol[j]) {
7333 found = true;
7334 break;
7335 }
7336 }
7337 if (found)
7338 continue;
7339 if (CDS_IS_DFS_CH(channel_list[i])) {
7340 *pre_cac_chan = channel_list[i];
7341 break;
7342 }
7343 }
7344 if (*pre_cac_chan == 0) {
7345 hdd_err("unable to find outdoor channel");
7346 return -EINVAL;
7347 }
7348 } else {
7349 /* Only when driver selects a channel, check is done for
7350 * unnsafe and NOL channels. When user provides a fixed channel
7351 * the user is expected to take care of this.
7352 */
7353 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7354 !CDS_IS_DFS_CH(channel)) {
7355 hdd_err("Invalid channel for pre cac:%d", channel);
7356 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307357 }
Jeff Johnson68755312017-02-10 11:46:55 -08007358
7359 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307360 }
7361 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7362 return 0;
7363}
7364
7365/**
7366 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7367 * @channel: Channel option provided by userspace
7368 *
7369 * Sets the driver to the required hardware mode and start an adapater for
7370 * pre CAC which will mimic an AP.
7371 *
7372 * Return: Zero on success, non-zero value on error
7373 */
7374int wlan_hdd_request_pre_cac(uint8_t channel)
7375{
Krunal Sonib37bb352016-12-20 14:12:21 -08007376 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307377 hdd_context_t *hdd_ctx;
7378 int ret;
7379 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7380 hdd_ap_ctx_t *hdd_ap_ctx;
7381 QDF_STATUS status;
7382 struct wiphy *wiphy;
7383 struct net_device *dev;
7384 struct cfg80211_chan_def chandef;
7385 enum nl80211_channel_type channel_type;
7386 uint32_t freq;
7387 struct ieee80211_channel *chan;
7388 tHalHandle handle;
7389 bool val;
7390
7391 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7392 if (0 != wlan_hdd_validate_context(hdd_ctx))
7393 return -EINVAL;
7394
7395 if (cds_get_connection_count() > 1) {
7396 hdd_err("pre cac not allowed in concurrency");
7397 return -EINVAL;
7398 }
7399
7400 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7401 if (!ap_adapter) {
7402 hdd_err("unable to get SAP adapter");
7403 return -EINVAL;
7404 }
7405
7406 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7407 if (!handle) {
7408 hdd_err("Invalid handle");
7409 return -EINVAL;
7410 }
7411
7412 val = wlan_sap_is_pre_cac_active(handle);
7413 if (val) {
7414 hdd_err("pre cac is already in progress");
7415 return -EINVAL;
7416 }
7417
7418 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7419 if (!hdd_ap_ctx) {
7420 hdd_err("SAP context is NULL");
7421 return -EINVAL;
7422 }
7423
7424 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7425 hdd_err("SAP is already on DFS channel:%d",
7426 hdd_ap_ctx->operatingChannel);
7427 return -EINVAL;
7428 }
7429
7430 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7431 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7432 hdd_ap_ctx->operatingChannel);
7433 return -EINVAL;
7434 }
7435
Krunal Sonib37bb352016-12-20 14:12:21 -08007436 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7437 if (!mac_addr) {
7438 hdd_err("can't add virtual intf: Not getting valid mac addr");
7439 return -EINVAL;
7440 }
7441
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307442 hdd_info("channel:%d", channel);
7443
7444 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7445 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007446 if (ret != 0) {
7447 hdd_err("can't validate pre-cac channel");
7448 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307449 }
7450
7451 hdd_debug("starting pre cac SAP adapter");
7452
7453 /* Starting a SAP adapter:
7454 * Instead of opening an adapter, we could just do a SME open session
7455 * for AP type. But, start BSS would still need an adapter.
7456 * So, this option is not taken.
7457 *
7458 * hdd open adapter is going to register this precac interface with
7459 * user space. This interface though exposed to user space will be in
7460 * DOWN state. Consideration was done to avoid this registration to the
7461 * user space. But, as part of SAP operations multiple events are sent
7462 * to user space. Some of these events received from unregistered
7463 * interface was causing crashes. So, retaining the registration.
7464 *
7465 * So, this interface would remain registered and will remain in DOWN
7466 * state for the CAC duration. We will add notes in the feature
7467 * announcement to not use this temporary interface for any activity
7468 * from user space.
7469 */
7470 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007471 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307472 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307473 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007474 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307475 }
7476
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307477 /*
7478 * This interface is internally created by the driver. So, no interface
7479 * up comes for this interface from user space and hence starting
7480 * the adapter internally.
7481 */
7482 if (hdd_start_adapter(pre_cac_adapter)) {
7483 hdd_err("error starting the pre cac adapter");
7484 goto close_pre_cac_adapter;
7485 }
7486
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307487 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7488
7489 wiphy = hdd_ctx->wiphy;
7490 dev = pre_cac_adapter->dev;
7491
7492 /* Since this is only a dummy interface lets us use the IEs from the
7493 * other active SAP interface. In regular scenarios, these IEs would
7494 * come from the user space entity
7495 */
7496 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7497 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7498 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7499 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307500 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307501 }
7502 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7503 ap_adapter->sessionCtx.ap.beacon,
7504 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7505 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7506 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7507 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7508 ap_adapter->sessionCtx.ap.sapConfig.authType;
7509
7510 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7511 * to operate on the same bandwidth as that of the 2.4GHz operations.
7512 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7513 */
7514 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7515 case CH_WIDTH_20MHZ:
7516 channel_type = NL80211_CHAN_HT20;
7517 break;
7518 case CH_WIDTH_40MHZ:
7519 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7520 ap_adapter->sessionCtx.ap.sapConfig.channel)
7521 channel_type = NL80211_CHAN_HT40PLUS;
7522 else
7523 channel_type = NL80211_CHAN_HT40MINUS;
7524 break;
7525 default:
7526 channel_type = NL80211_CHAN_NO_HT;
7527 break;
7528 }
7529
7530 freq = cds_chan_to_freq(pre_cac_chan);
7531 chan = __ieee80211_get_channel(wiphy, freq);
7532 if (!chan) {
7533 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307534 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307535 }
7536
7537 cfg80211_chandef_create(&chandef, chan, channel_type);
7538
7539 hdd_debug("orig width:%d channel_type:%d freq:%d",
7540 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7541 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007542 /*
7543 * Doing update after opening and starting pre-cac adapter will make
7544 * sure that driver won't do hardware mode change if there are any
7545 * initial hick-ups or issues in pre-cac adapter's configuration.
7546 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7547 * connection update should result in DBS mode
7548 */
7549 status = cds_update_and_wait_for_connection_update(
7550 ap_adapter->sessionId,
7551 pre_cac_chan,
7552 SIR_UPDATE_REASON_PRE_CAC);
7553 if (QDF_IS_STATUS_ERROR(status)) {
7554 hdd_err("error in moving to DBS mode");
7555 goto stop_close_pre_cac_adapter;
7556 }
7557
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307558
7559 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7560 if (0 != ret) {
7561 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307562 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307563 }
7564
7565 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7566 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007567 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307568 if (QDF_IS_STATUS_ERROR(status)) {
7569 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307570 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307571 }
7572
7573 /*
7574 * The pre cac status is set here. But, it would not be reset explicitly
7575 * anywhere, since after the pre cac success/failure, the pre cac
7576 * adapter itself would be removed.
7577 */
7578 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7579 if (0 != ret) {
7580 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307581 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307582 }
7583
7584 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7585 hdd_ap_ctx->operatingChannel);
7586 if (0 != ret) {
7587 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307588 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307589 }
7590
7591 ap_adapter->pre_cac_chan = pre_cac_chan;
7592
7593 return 0;
7594
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307595stop_close_pre_cac_adapter:
7596 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307597 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7598 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307599close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307600 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007601release_intf_addr_and_return_failure:
7602 /*
7603 * Release the interface address as the adapter
7604 * failed to start, if you don't release then next
7605 * adapter which is trying to come wouldn't get valid
7606 * mac address. Remember we have limited pool of mac addresses
7607 */
7608 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307609 return -EINVAL;
7610}
7611
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307612/**
7613 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7614 *
7615 * Return: None
7616 */
7617void hdd_init_bpf_completion(void)
7618{
7619 init_completion(&bpf_context.completion);
7620}
7621
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307622static const struct nla_policy
7623wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7624 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7625};
7626
Agrawal Ashish65634612016-08-18 13:24:32 +05307627static const struct nla_policy
7628wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7629 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7630 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7631};
7632
7633/**
7634 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7635 * @wiphy: Pointer to wireless phy
7636 * @wdev: Pointer to wireless device
7637 * @data: Pointer to data
7638 * @data_len: Length of @data
7639 *
7640 * This function parses the incoming NL vendor command data attributes and
7641 * updates the SAP context about channel_hint and DFS mode.
7642 * If channel_hint is set, SAP will choose that channel
7643 * as operating channel.
7644 *
7645 * If DFS mode is enabled, driver will include DFS channels
7646 * in ACS else driver will skip DFS channels.
7647 *
7648 * Return: 0 on success, negative errno on failure
7649 */
7650static int
7651__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7652 struct wireless_dev *wdev,
7653 const void *data, int data_len)
7654{
7655 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7656 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7657 int ret;
7658 struct acs_dfs_policy *acs_policy;
7659 int mode = DFS_MODE_NONE;
7660 int channel_hint = 0;
7661
7662 ENTER_DEV(wdev->netdev);
7663
7664 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7665 hdd_err("Command not allowed in FTM mode");
7666 return -EINVAL;
7667 }
7668
7669 ret = wlan_hdd_validate_context(hdd_ctx);
7670 if (0 != ret)
7671 return ret;
7672
7673 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7674 data, data_len,
7675 wlan_hdd_set_acs_dfs_config_policy)) {
7676 hdd_err("invalid attr");
7677 return -EINVAL;
7678 }
7679
7680 acs_policy = &hdd_ctx->acs_policy;
7681 /*
7682 * SCM sends this attribute to restrict SAP from choosing
7683 * DFS channels from ACS.
7684 */
7685 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7686 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7687
7688 if (!IS_DFS_MODE_VALID(mode)) {
7689 hdd_err("attr acs dfs mode is not valid");
7690 return -EINVAL;
7691 }
7692 acs_policy->acs_dfs_mode = mode;
7693
7694 /*
7695 * SCM sends this attribute to provide an active channel,
7696 * to skip redundant ACS between drivers, and save driver start up time
7697 */
7698 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7699 channel_hint = nla_get_u8(
7700 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7701
7702 if (!IS_CHANNEL_VALID(channel_hint)) {
7703 hdd_err("acs channel is not valid");
7704 return -EINVAL;
7705 }
7706 acs_policy->acs_channel = channel_hint;
7707
7708 return 0;
7709}
7710
7711/**
7712 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7713 * @wiphy: wiphy structure pointer
7714 * @wdev: Wireless device structure pointer
7715 * @data: Pointer to the data received
7716 * @data_len: Length of @data
7717 *
7718 * This function parses the incoming NL vendor command data attributes and
7719 * updates the SAP context about channel_hint and DFS mode.
7720 *
7721 * Return: 0 on success; errno on failure
7722 */
7723static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7724 struct wireless_dev *wdev,
7725 const void *data, int data_len)
7726{
7727 int ret;
7728
7729 cds_ssr_protect(__func__);
7730 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7731 cds_ssr_unprotect(__func__);
7732
7733 return ret;
7734}
7735
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307736/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307737 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7738 * @mode : cfg80211 dfs mode
7739 *
7740 * Return: return csr sta roam dfs mode else return NONE
7741 */
7742static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7743 enum dfs_mode mode)
7744{
7745 switch (mode) {
7746 case DFS_MODE_ENABLE:
7747 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7748 break;
7749 case DFS_MODE_DISABLE:
7750 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7751 break;
7752 case DFS_MODE_DEPRIORITIZE:
7753 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7754 break;
7755 default:
7756 hdd_err("STA Roam policy dfs mode is NONE");
7757 return CSR_STA_ROAM_POLICY_NONE;
7758 }
7759}
7760
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307761/*
7762 * hdd_get_sap_operating_band: Get current operating channel
7763 * for sap.
7764 * @hdd_ctx: hdd context
7765 *
7766 * Return : Corresponding band for SAP operating channel
7767 */
7768uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7769{
7770 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7771 QDF_STATUS status;
7772 hdd_adapter_t *adapter;
7773 uint8_t operating_channel = 0;
7774 uint8_t sap_operating_band = 0;
7775 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7776 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7777 adapter = adapter_node->pAdapter;
7778
7779 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7780 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7781 &next);
7782 adapter_node = next;
7783 continue;
7784 }
7785 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7786 if (IS_24G_CH(operating_channel))
7787 sap_operating_band = eCSR_BAND_24;
7788 else if (IS_5G_CH(operating_channel))
7789 sap_operating_band = eCSR_BAND_5G;
7790 else
7791 sap_operating_band = eCSR_BAND_ALL;
7792 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7793 &next);
bings373b99b2017-01-23 10:35:08 +08007794 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307795 }
7796 return sap_operating_band;
7797}
7798
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307799static const struct nla_policy
7800wlan_hdd_set_sta_roam_config_policy[
7801QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7802 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7803 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7804};
7805
7806/**
7807 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7808 * for station connection or roaming.
7809 * @wiphy: Pointer to wireless phy
7810 * @wdev: Pointer to wireless device
7811 * @data: Pointer to data
7812 * @data_len: Length of @data
7813 *
7814 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7815 * channels needs to be skipped in scanning or not.
7816 * If dfs_mode is disabled, driver will not scan DFS channels.
7817 * If skip_unsafe_channels is set, driver will skip unsafe channels
7818 * in Scanning.
7819 *
7820 * Return: 0 on success, negative errno on failure
7821 */
7822static int
7823__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7824 struct wireless_dev *wdev,
7825 const void *data, int data_len)
7826{
7827 struct net_device *dev = wdev->netdev;
7828 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7829 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7830 struct nlattr *tb[
7831 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7832 int ret;
7833 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7834 enum dfs_mode mode = DFS_MODE_NONE;
7835 bool skip_unsafe_channels = false;
7836 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307837 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307838
7839 ENTER_DEV(dev);
7840
7841 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7842 hdd_err("Command not allowed in FTM mode");
7843 return -EINVAL;
7844 }
7845
7846 ret = wlan_hdd_validate_context(hdd_ctx);
7847 if (0 != ret)
7848 return ret;
7849 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7850 data, data_len,
7851 wlan_hdd_set_sta_roam_config_policy)) {
7852 hdd_err("invalid attr");
7853 return -EINVAL;
7854 }
7855 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7856 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7857 if (!IS_DFS_MODE_VALID(mode)) {
7858 hdd_err("attr sta roam dfs mode policy is not valid");
7859 return -EINVAL;
7860 }
7861
7862 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7863
7864 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7865 skip_unsafe_channels = nla_get_u8(
7866 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307867 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307868 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307869 skip_unsafe_channels, adapter->sessionId,
7870 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307871
7872 if (!QDF_IS_STATUS_SUCCESS(status)) {
7873 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7874 return -EINVAL;
7875 }
7876 return 0;
7877}
7878
7879/**
7880 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7881 * connection and roaming for station.
7882 * @wiphy: wiphy structure pointer
7883 * @wdev: Wireless device structure pointer
7884 * @data: Pointer to the data received
7885 * @data_len: Length of @data
7886 *
7887 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7888 * channels needs to be skipped in scanning or not.
7889 * If dfs_mode is disabled, driver will not scan DFS channels.
7890 * If skip_unsafe_channels is set, driver will skip unsafe channels
7891 * in Scanning.
7892 * Return: 0 on success; errno on failure
7893 */
7894static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7895 struct wireless_dev *wdev,
7896 const void *data, int data_len)
7897{
7898 int ret;
7899
7900 cds_ssr_protect(__func__);
7901 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7902 cds_ssr_unprotect(__func__);
7903
7904 return ret;
7905}
7906
Agrawal Ashish467dde42016-09-08 18:44:22 +05307907#ifdef FEATURE_WLAN_CH_AVOID
7908/**
7909 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7910 * is on unsafe channel.
7911 * @wiphy: wiphy structure pointer
7912 * @wdev: Wireless device structure pointer
7913 * @data: Pointer to the data received
7914 * @data_len: Length of @data
7915 *
7916 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7917 * on any of unsafe channels.
7918 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7919 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7920 *
7921 * Return: 0 on success; errno on failure
7922 */
7923static int
7924__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7925 struct wireless_dev *wdev,
7926 const void *data, int data_len)
7927{
7928 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7929 int ret;
7930 uint16_t unsafe_channel_count;
7931 int unsafe_channel_index;
7932 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7933
7934 ENTER_DEV(wdev->netdev);
7935
7936 if (!qdf_ctx) {
7937 cds_err("qdf_ctx is NULL");
7938 return -EINVAL;
7939 }
7940
7941 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7942 hdd_err("Command not allowed in FTM mode");
7943 return -EINVAL;
7944 }
7945
7946 ret = wlan_hdd_validate_context(hdd_ctx);
7947 if (0 != ret)
7948 return ret;
7949 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7950 &(hdd_ctx->unsafe_channel_count),
7951 sizeof(hdd_ctx->unsafe_channel_list));
7952
7953 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7954 (uint16_t)NUM_CHANNELS);
7955 for (unsafe_channel_index = 0;
7956 unsafe_channel_index < unsafe_channel_count;
7957 unsafe_channel_index++) {
7958 hdd_info("Channel %d is not safe",
7959 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7960 }
7961 hdd_unsafe_channel_restart_sap(hdd_ctx);
7962 return 0;
7963}
7964
7965/**
7966 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7967 * is on unsafe channel.
7968 * @wiphy: wiphy structure pointer
7969 * @wdev: Wireless device structure pointer
7970 * @data: Pointer to the data received
7971 * @data_len: Length of @data
7972 *
7973 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7974 * on any of unsafe channels.
7975 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7976 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7977 *
7978 * Return: 0 on success; errno on failure
7979 */
7980static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7981 struct wireless_dev *wdev,
7982 const void *data, int data_len)
7983{
7984 int ret;
7985
7986 cds_ssr_protect(__func__);
7987 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7988 cds_ssr_unprotect(__func__);
7989
7990 return ret;
7991}
7992
7993#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307994/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307995 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7996 * SAP is on unsafe channel.
7997 * @wiphy: wiphy structure pointer
7998 * @wdev: Wireless device structure pointer
7999 * @data: Pointer to the data received
8000 * @data_len: Length of @data
8001 *
8002 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8003 * driver.
8004 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8005 * will initiate restart of sap.
8006 *
8007 * Return: 0 on success; errno on failure
8008 */
8009static int
8010__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8011 struct wireless_dev *wdev,
8012 const void *data, int data_len)
8013{
8014 struct net_device *ndev = wdev->netdev;
8015 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8016 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8017 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8018 uint8_t config_channel = 0;
8019 hdd_ap_ctx_t *ap_ctx;
8020 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308021 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308022
8023 ENTER();
8024
8025 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008026 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308027 return -EINVAL;
8028 }
8029
8030 ret = wlan_hdd_validate_context(hdd_ctx);
8031 if (0 != ret)
8032 return -EINVAL;
8033
8034 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8035 data, data_len,
8036 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008037 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308038 return -EINVAL;
8039 }
8040
8041 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8042 if (!test_bit(SOFTAP_BSS_STARTED,
8043 &hostapd_adapter->event_flags)) {
8044 hdd_err("SAP is not started yet. Restart sap will be invalid");
8045 return -EINVAL;
8046 }
8047
8048 config_channel =
8049 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8050
8051 if (!((IS_24G_CH(config_channel)) ||
8052 (IS_5G_CH(config_channel)))) {
8053 hdd_err("Channel %d is not valid to restart SAP",
8054 config_channel);
8055 return -ENOTSUPP;
8056 }
8057
8058 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8059 ap_ctx->sapConfig.channel = config_channel;
8060 ap_ctx->sapConfig.ch_params.ch_width =
8061 ap_ctx->sapConfig.ch_width_orig;
8062
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008063 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308064 ap_ctx->sapConfig.sec_ch,
8065 &ap_ctx->sapConfig.ch_params);
8066
8067 cds_restart_sap(hostapd_adapter);
8068 }
8069
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308070 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8071 uint32_t freq_len, i;
8072 uint32_t *freq;
8073 uint8_t chans[QDF_MAX_NUM_CHAN];
8074
8075 hdd_debug("setting mandatory freq/chan list");
8076
8077 freq_len = nla_len(
8078 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8079 sizeof(uint32_t);
8080
8081 if (freq_len > QDF_MAX_NUM_CHAN) {
8082 hdd_err("insufficient space to hold channels");
8083 return -ENOMEM;
8084 }
8085
8086 freq = nla_data(
8087 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8088
8089 hdd_debug("freq_len=%d", freq_len);
8090
8091 for (i = 0; i < freq_len; i++) {
8092 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8093 hdd_debug("freq[%d]=%d", i, freq[i]);
8094 }
8095
8096 status = cds_set_sap_mandatory_channels(chans, freq_len);
8097 if (QDF_IS_STATUS_ERROR(status))
8098 return -EINVAL;
8099 }
8100
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308101 return 0;
8102}
8103
8104/**
8105 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8106 * @wiphy: wiphy structure pointer
8107 * @wdev: Wireless device structure pointer
8108 * @data: Pointer to the data received
8109 * @data_len: Length of @data
8110 *
8111 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8112 * driver.
8113 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8114 * will initiate restart of sap.
8115 *
8116 * Return: 0 on success; errno on failure
8117 */
8118static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8119 struct wireless_dev *wdev,
8120 const void *data, int data_len)
8121{
8122 int ret;
8123
8124 cds_ssr_protect(__func__);
8125 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8126 wdev, data, data_len);
8127 cds_ssr_unprotect(__func__);
8128
8129 return ret;
8130}
8131
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308132#undef BPF_INVALID
8133#undef BPF_SET_RESET
8134#undef BPF_VERSION
8135#undef BPF_ID
8136#undef BPF_PACKET_SIZE
8137#undef BPF_CURRENT_OFFSET
8138#undef BPF_PROGRAM
8139#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308140
8141/**
8142 * define short names for the global vendor params
8143 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8144 */
8145#define PARAM_TOTAL_CMD_EVENT_WAKE \
8146 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8147#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8148 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8149#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8150 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8151#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8152 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8153#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8154 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8155#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8156 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8157#define PARAM_TOTAL_RX_DATA_WAKE \
8158 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8159#define PARAM_RX_UNICAST_CNT \
8160 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8161#define PARAM_RX_MULTICAST_CNT \
8162 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8163#define PARAM_RX_BROADCAST_CNT \
8164 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8165#define PARAM_ICMP_PKT \
8166 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8167#define PARAM_ICMP6_PKT \
8168 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8169#define PARAM_ICMP6_RA \
8170 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8171#define PARAM_ICMP6_NA \
8172 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8173#define PARAM_ICMP6_NS \
8174 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8175#define PARAM_ICMP4_RX_MULTICAST_CNT \
8176 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8177#define PARAM_ICMP6_RX_MULTICAST_CNT \
8178 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8179#define PARAM_OTHER_RX_MULTICAST_CNT \
8180 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308181#define PARAM_RSSI_BREACH_CNT \
8182 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8183#define PARAM_LOW_RSSI_CNT \
8184 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8185#define PARAM_GSCAN_CNT \
8186 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8187#define PARAM_PNO_COMPLETE_CNT \
8188 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8189#define PARAM_PNO_MATCH_CNT \
8190 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8191
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308192
8193
8194/**
8195 * hdd_send_wakelock_stats() - API to send wakelock stats
8196 * @ctx: context to be passed to callback
8197 * @data: data passed to callback
8198 *
8199 * This function is used to send wake lock stats to HAL layer
8200 *
8201 * Return: 0 on success, error number otherwise.
8202 */
8203static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8204 const struct sir_wake_lock_stats *data)
8205{
8206 struct sk_buff *skb;
8207 uint32_t nl_buf_len;
8208 uint32_t total_rx_data_wake, rx_multicast_cnt;
8209 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308210 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308211
8212 ENTER();
8213
8214 nl_buf_len = NLMSG_HDRLEN;
8215 nl_buf_len +=
8216 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8217 (NLMSG_HDRLEN + sizeof(uint32_t));
8218
8219 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8220
8221 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008222 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308223 return -ENOMEM;
8224 }
8225
Jeff Johnson64943bd2016-08-23 13:14:06 -07008226 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308227 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008228 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308229 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008230 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308231 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008232 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308233 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008234 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308235 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008236 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308237 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008238 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308239 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008240 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8241 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308242 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308243 hdd_info("wow_rssi_breach_wake_up_count %d",
8244 data->wow_rssi_breach_wake_up_count);
8245 hdd_info("wow_low_rssi_wake_up_count %d",
8246 data->wow_low_rssi_wake_up_count);
8247 hdd_info("wow_gscan_wake_up_count %d",
8248 data->wow_gscan_wake_up_count);
8249 hdd_info("wow_pno_complete_wake_up_count %d",
8250 data->wow_pno_complete_wake_up_count);
8251 hdd_info("wow_pno_match_wake_up_count %d",
8252 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308253
8254 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308255 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308256
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308257 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308258 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308259
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260 rx_multicast_cnt =
8261 data->wow_ipv4_mcast_wake_up_count +
8262 ipv6_rx_multicast_addr_cnt;
8263
8264 total_rx_data_wake =
8265 data->wow_ucast_wake_up_count +
8266 data->wow_bcast_wake_up_count +
8267 rx_multicast_cnt;
8268
8269 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8270 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8271 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8272 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8273 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8274 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8275 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8276 total_rx_data_wake) ||
8277 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8278 data->wow_ucast_wake_up_count) ||
8279 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8280 rx_multicast_cnt) ||
8281 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8282 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308283 nla_put_u32(skb, PARAM_ICMP_PKT,
8284 data->wow_icmpv4_count) ||
8285 nla_put_u32(skb, PARAM_ICMP6_PKT,
8286 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287 nla_put_u32(skb, PARAM_ICMP6_RA,
8288 data->wow_ipv6_mcast_ra_stats) ||
8289 nla_put_u32(skb, PARAM_ICMP6_NA,
8290 data->wow_ipv6_mcast_na_stats) ||
8291 nla_put_u32(skb, PARAM_ICMP6_NS,
8292 data->wow_ipv6_mcast_ns_stats) ||
8293 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8294 data->wow_ipv4_mcast_wake_up_count) ||
8295 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8296 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308297 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8298 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8299 data->wow_rssi_breach_wake_up_count) ||
8300 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8301 data->wow_low_rssi_wake_up_count) ||
8302 nla_put_u32(skb, PARAM_GSCAN_CNT,
8303 data->wow_gscan_wake_up_count) ||
8304 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8305 data->wow_pno_complete_wake_up_count) ||
8306 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8307 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008308 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308309 goto nla_put_failure;
8310 }
8311
8312 cfg80211_vendor_cmd_reply(skb);
8313
8314 EXIT();
8315 return 0;
8316
8317nla_put_failure:
8318 kfree_skb(skb);
8319 return -EINVAL;
8320}
8321
8322/**
8323 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8324 * @wiphy: wiphy pointer
8325 * @wdev: pointer to struct wireless_dev
8326 * @data: pointer to incoming NL vendor data
8327 * @data_len: length of @data
8328 *
8329 * This function parses the incoming NL vendor command data attributes and
8330 * invokes the SME Api and blocks on a completion variable.
8331 * WMA copies required data and invokes callback
8332 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8333 *
8334 * Return: 0 on success; error number otherwise.
8335 */
8336static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8337 struct wireless_dev *wdev,
8338 const void *data,
8339 int data_len)
8340{
8341 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8342 int status, ret;
8343 struct sir_wake_lock_stats wake_lock_stats;
8344 QDF_STATUS qdf_status;
8345
8346 ENTER();
8347
8348 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008349 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308350 return -EINVAL;
8351 }
8352
8353 status = wlan_hdd_validate_context(hdd_ctx);
8354 if (0 != status)
8355 return -EINVAL;
8356
8357 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8358 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008359 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308360 return -EINVAL;
8361 }
8362
8363 ret = hdd_send_wakelock_stats(hdd_ctx,
8364 &wake_lock_stats);
8365 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008366 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308367
8368 EXIT();
8369 return ret;
8370}
8371
8372/**
8373 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8374 * @wiphy: wiphy pointer
8375 * @wdev: pointer to struct wireless_dev
8376 * @data: pointer to incoming NL vendor data
8377 * @data_len: length of @data
8378 *
8379 * This function parses the incoming NL vendor command data attributes and
8380 * invokes the SME Api and blocks on a completion variable.
8381 * WMA copies required data and invokes callback
8382 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8383 *
8384 * Return: 0 on success; error number otherwise.
8385 */
8386static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8387 struct wireless_dev *wdev,
8388 const void *data, int data_len)
8389{
8390 int ret;
8391
8392 cds_ssr_protect(__func__);
8393 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8394 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008395 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308396
8397 return ret;
8398}
8399
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308400/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308401 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8402 * @wiphy: wiphy structure pointer
8403 * @wdev: Wireless device structure pointer
8404 * @data: Pointer to the data received
8405 * @data_len: Length of @data
8406 *
8407 * This function reads wmi max bus size and fill in the skb with
8408 * NL attributes and send up the NL event.
8409 * Return: 0 on success; errno on failure
8410 */
8411static int
8412__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8413 struct wireless_dev *wdev,
8414 const void *data, int data_len)
8415{
8416 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8417 int ret_val;
8418 struct sk_buff *skb;
8419 uint32_t nl_buf_len;
8420
8421 ENTER();
8422
8423 ret_val = wlan_hdd_validate_context(hdd_ctx);
8424 if (ret_val)
8425 return ret_val;
8426
8427 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8428 hdd_err("Command not allowed in FTM mode");
8429 return -EINVAL;
8430 }
8431
8432 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8433
8434 nl_buf_len = NLMSG_HDRLEN;
8435 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8436
8437 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8438 if (!skb) {
8439 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8440 return -ENOMEM;
8441 }
8442
8443 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8444 hdd_ctx->wmi_max_len)) {
8445 hdd_err("nla put failure");
8446 goto nla_put_failure;
8447 }
8448
8449 cfg80211_vendor_cmd_reply(skb);
8450
8451 EXIT();
8452
8453 return 0;
8454
8455nla_put_failure:
8456 kfree_skb(skb);
8457 return -EINVAL;
8458}
8459
8460/**
8461 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8462 * @wiphy: wiphy structure pointer
8463 * @wdev: Wireless device structure pointer
8464 * @data: Pointer to the data received
8465 * @data_len: Length of @data
8466 *
8467 * Return: 0 on success; errno on failure
8468 */
8469static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8470 struct wireless_dev *wdev,
8471 const void *data, int data_len)
8472{
8473 int ret;
8474
8475 cds_ssr_protect(__func__);
8476 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8477 cds_ssr_unprotect(__func__);
8478
8479 return ret;
8480}
8481
8482/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308483 *__wlan_hdd_cfg80211_setband() - set band
8484 * @wiphy: Pointer to wireless phy
8485 * @wdev: Pointer to wireless device
8486 * @data: Pointer to data
8487 * @data_len: Length of @data
8488 *
8489 * Return: 0 on success, negative errno on failure
8490 */
8491static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8492 struct wireless_dev *wdev,
8493 const void *data, int data_len)
8494{
8495 struct net_device *dev = wdev->netdev;
8496 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8497 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8498 int ret;
8499 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8500 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8501
8502 ENTER();
8503
8504 ret = wlan_hdd_validate_context(hdd_ctx);
8505 if (ret)
8506 return ret;
8507
8508 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8509 hdd_err(FL("Invalid ATTR"));
8510 return -EINVAL;
8511 }
8512
8513 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8514 hdd_err(FL("attr SETBAND_VALUE failed"));
8515 return -EINVAL;
8516 }
8517
8518 ret = hdd_set_band(dev,
8519 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8520
8521 EXIT();
8522 return ret;
8523}
8524
8525/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308526 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8527 * @adapter: hdd adapter
8528 * @channel: channel number
8529 *
8530 * return: QDF status based on success or failure
8531 */
8532static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8533 int channel, int chan_bw)
8534{
8535 if (QDF_STATUS_SUCCESS !=
8536 wlan_hdd_validate_operation_channel(adapter, channel))
8537 return QDF_STATUS_E_FAILURE;
8538 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8539 channel,
8540 PHY_SINGLE_CHANNEL_CENTERED))) {
8541 hdd_notice("channel %d is in nol", channel);
8542 return -EINVAL;
8543 }
8544
8545 if ((wlansap_is_channel_leaking_in_nol(
8546 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8547 channel, chan_bw))) {
8548 hdd_notice("channel %d is leaking in nol", channel);
8549 return -EINVAL;
8550 }
8551
8552 return 0;
8553
8554}
8555
Kapil Gupta8878ad92017-02-13 11:56:04 +05308556static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8557 tsap_Config_t *sap_config,
8558 struct hdd_vendor_chan_info *channel_list)
8559{
8560 sap_config->channel = channel_list->pri_ch;
8561
8562 sap_config->ch_params.center_freq_seg0 =
8563 channel_list->vht_seg0_center_ch;
8564 sap_config->ch_params.center_freq_seg1 =
8565 channel_list->vht_seg1_center_ch;
8566
8567 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8568 sap_config->ch_params.ch_width = channel_list->chan_width;
8569 if (sap_config->channel >= 36)
8570 sap_config->ch_width_orig =
8571 hdd_ctx->config->vhtChannelWidth;
8572 else
8573 sap_config->ch_width_orig =
8574 hdd_ctx->config->nChannelBondingMode24GHz ?
8575 eHT_CHANNEL_WIDTH_40MHZ :
8576 eHT_CHANNEL_WIDTH_20MHZ;
8577
8578 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8579 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8580 sap_config->acs_cfg.vht_seg0_center_ch =
8581 channel_list->vht_seg0_center_ch;
8582 sap_config->acs_cfg.vht_seg1_center_ch =
8583 channel_list->vht_seg1_center_ch;
8584 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8585}
8586
8587static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8588 uint8_t channel_cnt,
8589 struct hdd_vendor_chan_info *channel_list)
8590{
8591 tsap_Config_t *sap_config;
8592 hdd_ap_ctx_t *hdd_ap_ctx;
8593 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8594 QDF_STATUS status = QDF_STATUS_SUCCESS;
8595
8596 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8597 sap_config = &adapter->sessionCtx.ap.sapConfig;
8598
8599 if (QDF_TIMER_STATE_RUNNING ==
8600 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8601 ap.vendor_acs_timer)) {
8602 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8603 }
8604
8605 if (channel_list && channel_list->pri_ch == 0) {
8606 /* Check mode, set default channel */
8607 channel_list->pri_ch = 6;
8608 /*
8609 * sap_select_default_oper_chan(hdd_ctx->hHal,
8610 * sap_config->acs_cfg.hw_mode);
8611 */
8612 }
8613
8614 switch (reason) {
8615 /* SAP init case */
8616 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8617 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8618 /* Update Hostapd */
8619 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8620 break;
8621
8622 /* DFS detected on current channel */
8623 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8624 wlan_sap_update_next_channel(
8625 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8626 channel_list->pri_ch,
8627 channel_list->chan_width);
8628 status = sme_update_new_channel_event(
8629 WLAN_HDD_GET_HAL_CTX(adapter),
8630 adapter->sessionId);
8631 break;
8632
8633 /* LTE coex event on current channel */
8634 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8635 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8636 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8637 hdd_ap_ctx->sapConfig.ch_width_orig =
8638 channel_list->chan_width;
8639 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8640 break;
8641
8642 default:
8643 hdd_info("invalid reason for timer invoke");
8644 }
8645 qdf_mem_free(channel_list);
8646 EXIT();
8647 return status;
8648}
8649
8650/**
8651 * Define short name for vendor channel set config
8652 */
8653#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8654#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8655#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8656#define SET_CHAN_PRIMARY_CHANNEL \
8657 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8658#define SET_CHAN_SECONDARY_CHANNEL \
8659 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8660#define SET_CHAN_SEG0_CENTER_CHANNEL \
8661 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8662#define SET_CHAN_SEG1_CENTER_CHANNEL \
8663 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8664#define SET_CHAN_CHANNEL_WIDTH \
8665 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8666#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8667
8668/**
8669 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8670 * @channel_list: pointer to hdd_vendor_chan_info
8671 * @reason: channel change reason
8672 * @channel_cnt: channel count
8673 * @data: data
8674 * @data_len: data len
8675 *
8676 * Return: 0 on success, negative errno on failure
8677 */
8678static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8679 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8680 const void *data, int data_len)
8681{
8682 int rem, i = 0;
8683 struct nlattr *tb[SET_CHAN_MAX + 1];
8684 struct nlattr *tb2[SET_CHAN_MAX + 1];
8685 struct nlattr *curr_attr;
8686 struct hdd_vendor_chan_info *channel_list;
8687
8688 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8689 hdd_err("Invalid ATTR");
8690 return -EINVAL;
8691 }
8692
8693 if (tb[SET_CHAN_REASON])
8694 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8695
8696 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8697 *channel_cnt = nla_get_u8(tb[
8698 SET_CHAN_CHANNEL_COUNT]);
8699 hdd_info("channel count %d", *channel_cnt);
8700 }
8701
8702 if (!(*channel_cnt)) {
8703 hdd_err("channel count is %d", *channel_cnt);
8704 return -EINVAL;
8705 }
8706
8707 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8708 (*channel_cnt));
8709
8710 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8711 if (nla_parse(tb2,
8712 SET_CHAN_MAX,
8713 nla_data(curr_attr), nla_len(curr_attr),
8714 NULL)) {
8715 hdd_err("nla_parse failed");
8716 return -EINVAL;
8717 }
8718 /* Parse and Fetch allowed SSID list*/
8719 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8720 channel_list[i].pri_ch =
8721 nla_get_u8(
8722 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8723 }
8724 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8725 channel_list[i].ht_sec_ch =
8726 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8727 }
8728 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8729 channel_list[i].vht_seg0_center_ch =
8730 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8731 }
8732 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8733 channel_list[i].vht_seg1_center_ch =
8734 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8735 }
8736 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8737 channel_list[i].chan_width =
8738 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8739 }
8740 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8741 i, channel_list[i].pri_ch,
8742 channel_list[i].ht_sec_ch,
8743 channel_list[i].vht_seg0_center_ch,
8744 channel_list[i].vht_seg1_center_ch,
8745 channel_list[i].chan_width);
8746 i++;
8747 if (i > *channel_cnt)
8748 break;
8749 }
8750 *chan_list_ptr = channel_list;
8751
8752 return 0;
8753}
8754
8755/**
8756 * Undef short names for vendor set channel configuration
8757 */
8758#undef SET_CHAN_REASON
8759#undef SET_CHAN_CHANNEL_COUNT
8760#undef SET_CHAN_CHAN_LIST
8761#undef SET_CHAN_PRIMARY_CHANNEL
8762#undef SET_CHAN_SECONDARY_CHANNEL
8763#undef SET_CHAN_SEG0_CENTER_CHANNEL
8764#undef SET_CHAN_SEG1_CENTER_CHANNEL
8765#undef SET_CHAN_CHANNEL_WIDTH
8766#undef SET_CHAN_MAX
8767
8768/**
8769 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8770 * @wiphy: Pointer to wireless phy
8771 * @wdev: Pointer to wireless device
8772 * @data: Pointer to data
8773 * @data_len: Length of @data
8774 *
8775 * Return: 0 on success, negative errno on failure
8776 */
8777static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8778 struct wireless_dev *wdev,
8779 const void *data, int data_len)
8780{
8781 int ret_val;
8782 QDF_STATUS qdf_status;
8783 uint8_t channel_cnt = 0, reason = -1;
8784 struct hdd_vendor_chan_info *channel_list = NULL;
8785 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8786 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8787
8788 ENTER();
8789
8790 ret_val = wlan_hdd_validate_context(hdd_ctx);
8791 if (ret_val)
8792 return ret_val;
8793
8794 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8795 hdd_err("Command not allowed in FTM mode");
8796 return -EINVAL;
8797 }
8798
8799 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8800 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8801 else {
8802 hdd_err("already timeout happened for acs");
8803 return -EINVAL;
8804 }
8805
8806 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8807 &channel_cnt, data, data_len);
8808 if (ret_val)
8809 return ret_val;
8810
8811 /* Validate channel to be set */
8812 while (channel_cnt && channel_list) {
8813 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8814 channel_list->pri_ch,
8815 channel_list->chan_width);
8816 if (qdf_status == QDF_STATUS_SUCCESS)
8817 break;
8818 channel_cnt--;
8819 channel_list++;
8820 }
8821 if ((channel_cnt <= 0) || !channel_list) {
8822 hdd_err("no available channel/chanlist %p", channel_list);
8823 return -EINVAL;
8824 }
8825
8826 qdf_status = hdd_update_acs_channel(adapter, reason,
8827 channel_cnt, channel_list);
8828 return qdf_status_to_os_return(qdf_status);
8829}
8830
8831/**
8832 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8833 * @wiphy: Pointer to wireless phy
8834 * @wdev: Pointer to wireless device
8835 * @data: Pointer to data
8836 * @data_len: Length of @data
8837 *
8838 * Return: 0 on success, negative errno on failure
8839 */
8840static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8841 struct wireless_dev *wdev,
8842 const void *data, int data_len)
8843{
8844 int ret;
8845
8846 cds_ssr_protect(__func__);
8847 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8848 data_len);
8849 cds_ssr_protect(__func__);
8850
8851 return ret;
8852}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308853
8854/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308855 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8856 * @wiphy: wiphy structure pointer
8857 * @wdev: Wireless device structure pointer
8858 * @data: Pointer to the data received
8859 * @data_len: Length of @data
8860 *
8861 * Return: 0 on success; errno on failure
8862 */
8863static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8864 struct wireless_dev *wdev,
8865 const void *data, int data_len)
8866{
8867 int ret;
8868
8869 cds_ssr_protect(__func__);
8870 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8871 cds_ssr_unprotect(__func__);
8872
8873 return ret;
8874}
8875
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008876/**
8877 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8878 * @nl80211_value: Vendor command attribute value
8879 * @wmi_value: Pointer to return converted WMI return value
8880 *
8881 * Convert NL80211 vendor command value for SAR limit set to WMI value
8882 * Return: 0 on success, -1 on invalid value
8883 */
8884static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8885 u32 *wmi_value)
8886{
8887 int ret = 0;
8888
8889 switch (nl80211_value) {
8890 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8891 *wmi_value = WMI_SAR_FEATURE_OFF;
8892 break;
8893 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8894 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8895 break;
8896 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8897 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8898 break;
8899 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8900 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8901 break;
8902 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8903 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8904 break;
8905 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8906 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8907 break;
8908 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8909 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8910 break;
8911 default:
8912 ret = -1;
8913 }
8914 return ret;
8915}
8916
8917/**
8918 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8919 * @nl80211_value: Vendor command attribute value
8920 * @wmi_value: Pointer to return converted WMI return value
8921 *
8922 * Convert NL80211 vendor command value for SAR BAND to WMI value
8923 * Return: 0 on success, -1 on invalid value
8924 */
8925static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8926{
8927 int ret = 0;
8928
8929 switch (nl80211_value) {
8930 case NL80211_BAND_2GHZ:
8931 *wmi_value = WMI_SAR_2G_ID;
8932 break;
8933 case NL80211_BAND_5GHZ:
8934 *wmi_value = WMI_SAR_5G_ID;
8935 break;
8936 default:
8937 ret = -1;
8938 }
8939 return ret;
8940}
8941
8942/**
8943 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8944 * @nl80211_value: Vendor command attribute value
8945 * @wmi_value: Pointer to return converted WMI return value
8946 *
8947 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8948 * Return: 0 on success, -1 on invalid value
8949 */
8950static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8951 u32 *wmi_value)
8952{
8953 int ret = 0;
8954
8955 switch (nl80211_value) {
8956 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8957 *wmi_value = WMI_SAR_MOD_CCK;
8958 break;
8959 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8960 *wmi_value = WMI_SAR_MOD_OFDM;
8961 break;
8962 default:
8963 ret = -1;
8964 }
8965 return ret;
8966}
8967
8968
8969/**
8970 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8971 * @wiphy: Pointer to wireless phy
8972 * @wdev: Pointer to wireless device
8973 * @data: Pointer to data
8974 * @data_len: Length of @data
8975 *
8976 * This function is used to setup Specific Absorption Rate limit specs.
8977 *
8978 * Return: 0 on success, negative errno on failure
8979 */
8980static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8981 struct wireless_dev *wdev,
8982 const void *data, int data_len)
8983{
8984 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8985 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8986 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8987 *sar_spec_list;
8988 struct sar_limit_cmd_params sar_limit_cmd = {0};
8989 int ret = -EINVAL, i = 0, rem = 0;
8990
8991 ENTER();
8992
8993 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8994 hdd_err("Command not allowed in FTM mode");
8995 return -EPERM;
8996 }
8997
8998 if (wlan_hdd_validate_context(hdd_ctx))
8999 return -EINVAL;
9000
9001 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9002 data, data_len, NULL)) {
9003 hdd_err("Invalid SAR attributes");
9004 return -EINVAL;
9005 }
9006
9007 /* Vendor command manadates all SAR Specs in single call */
9008 sar_limit_cmd.commit_limits = 1;
9009 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9010 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9011 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9012 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9013 &sar_limit_cmd.sar_enable) < 0) {
9014 hdd_err("Invalid SAR Enable attr");
9015 goto fail;
9016 }
9017 }
9018 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9019
9020 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9021 sar_limit_cmd.num_limit_rows = nla_get_u32(
9022 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9023 hdd_info("attr sar num_limit_rows %d",
9024 sar_limit_cmd.num_limit_rows);
9025 }
9026 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9027 hdd_err("SAR Spec list exceed supported size");
9028 goto fail;
9029 }
9030 if (sar_limit_cmd.num_limit_rows == 0)
9031 goto send_sar_limits;
9032 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9033 struct sar_limit_cmd_row) *
9034 sar_limit_cmd.num_limit_rows);
9035 if (!sar_limit_cmd.sar_limit_row_list) {
9036 ret = -ENOMEM;
9037 goto fail;
9038 }
9039 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9040 hdd_err("Invalid SAR SPECs list");
9041 goto fail;
9042 }
9043
9044 nla_for_each_nested(sar_spec_list,
9045 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9046 if (i == sar_limit_cmd.num_limit_rows) {
9047 hdd_warn("SAR Cmd has excess SPECs in list");
9048 break;
9049 }
9050
9051 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9052 nla_data(sar_spec_list), nla_len(sar_spec_list),
9053 NULL)) {
9054 hdd_err("nla_parse failed for SAR Spec list");
9055 goto fail;
9056 }
9057 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9058 if (sar_spec[
9059 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9060 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9061 nla_get_u32(sar_spec[
9062 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9063 } else {
9064 hdd_err("SAR Spec does not have power limit value");
9065 goto fail;
9066 }
9067
9068 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9069 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9070 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9071 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9072 < 0) {
9073 hdd_err("Invalid SAR Band attr");
9074 goto fail;
9075 }
9076 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9077 WMI_SAR_BAND_ID_VALID_MASK;
9078 }
9079 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9080 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9081 nla_get_u32(sar_spec[
9082 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9083 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9084 WMI_SAR_CHAIN_ID_VALID_MASK;
9085 }
9086 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9087 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9088 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9089 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9090 < 0) {
9091 hdd_err("Invalid SAR Modulation attr");
9092 goto fail;
9093 }
9094 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9095 WMI_SAR_MOD_ID_VALID_MASK;
9096 }
9097 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9098 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9099 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9100 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9101 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9102 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9103 i++;
9104 }
9105
9106 if (i < sar_limit_cmd.num_limit_rows) {
9107 hdd_warn("SAR Cmd has less SPECs in list");
9108 sar_limit_cmd.num_limit_rows = i;
9109 }
9110
9111send_sar_limits:
9112 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9113 QDF_STATUS_SUCCESS)
9114 ret = 0;
9115fail:
9116 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9117 return ret;
9118}
9119
9120/**
9121 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9122 * @wiphy: Pointer to wireless phy
9123 * @wdev: Pointer to wireless device
9124 * @data: Pointer to data
9125 * @data_len: Length of @data
9126 *
9127 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9128 *
9129 * Return: 0 on success, negative errno on failure
9130 */
9131static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9132 struct wireless_dev *wdev,
9133 const void *data,
9134 int data_len)
9135{
9136 int ret;
9137
9138 cds_ssr_protect(__func__);
9139 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9140 data_len);
9141 cds_ssr_unprotect(__func__);
9142
9143 return ret;
9144}
9145
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309146static const struct
9147nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9148 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9149 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9150 .len = QDF_MAC_ADDR_SIZE},
9151};
9152
9153/**
9154 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9155 * @wiphy: Pointer to wireless phy
9156 * @wdev: Pointer to wireless device
9157 * @data: Pointer to data
9158 * @data_len: Length of @data
9159 *
9160 * This function is used to enable/disable roaming using vendor commands
9161 *
9162 * Return: 0 on success, negative errno on failure
9163 */
9164static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9165 struct wireless_dev *wdev,
9166 const void *data, int data_len)
9167{
9168 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9169 struct net_device *dev = wdev->netdev;
9170 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9171 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9172 uint32_t is_fast_roam_enabled;
9173 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309174 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309175
9176 ENTER_DEV(dev);
9177
9178 ret = wlan_hdd_validate_context(hdd_ctx);
9179 if (0 != ret)
9180 return ret;
9181
9182 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9183 hdd_err("Command not allowed in FTM mode");
9184 return -EINVAL;
9185 }
9186
9187 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9188 qca_wlan_vendor_attr);
9189 if (ret) {
9190 hdd_err("Invalid ATTR");
9191 return -EINVAL;
9192 }
9193
9194 /* Parse and fetch Enable flag */
9195 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9196 hdd_err("attr enable failed");
9197 return -EINVAL;
9198 }
9199
9200 is_fast_roam_enabled = nla_get_u32(
9201 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009202 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9203 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309204
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009205 if (!adapter->fast_roaming_allowed) {
9206 hdd_err("fast roaming not allowed on %s interface",
9207 adapter->dev->name);
9208 return -EINVAL;
9209 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309210 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309211 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009212 (is_fast_roam_enabled &&
9213 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309214 if (qdf_status != QDF_STATUS_SUCCESS)
9215 hdd_err("sme_config_fast_roaming failed with status=%d",
9216 qdf_status);
9217 ret = qdf_status_to_os_return(qdf_status);
9218
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309219 EXIT();
9220 return ret;
9221}
9222
9223/**
9224 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9225 * @wiphy: Pointer to wireless phy
9226 * @wdev: Pointer to wireless device
9227 * @data: Pointer to data
9228 * @data_len: Length of @data
9229 *
9230 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9231 *
9232 * Return: 0 on success, negative errno on failure
9233 */
9234static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9235 struct wireless_dev *wdev,
9236 const void *data, int data_len)
9237{
9238 int ret;
9239
9240 cds_ssr_protect(__func__);
9241 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9242 cds_ssr_unprotect(__func__);
9243
9244 return ret;
9245}
9246
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309247static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9248 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9249 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9250 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9251 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9252};
9253
9254/**
9255 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9256 * @wiphy: Pointer to wireless phy
9257 * @wdev: Pointer to wireless device
9258 * @data: Pointer to data
9259 * @data_len: Length of @data
9260 *
9261 * Return: 0 on success, negative errno on failure
9262 */
9263static int
9264__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9265 struct wireless_dev *wdev,
9266 const void *data,
9267 int data_len)
9268{
9269 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9270 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9271 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9272 struct nlattr *apth;
9273 int rem;
9274 int ret = 1;
9275 int print_idx = -1;
9276 int module_id = -1;
9277 int bit_mask = -1;
9278 int status;
9279
9280 ENTER();
9281
9282 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9283 hdd_err("Command not allowed in FTM mode");
9284 return -EINVAL;
9285 }
9286
9287 ret = wlan_hdd_validate_context(hdd_ctx);
9288 if (ret != 0)
9289 return -EINVAL;
9290
9291 print_idx = qdf_get_pidx();
9292 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9293 hdd_err("Invalid print controle object index");
9294 return -EINVAL;
9295 }
9296
9297 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9298 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9299 hdd_err("Invalid attr");
9300 return -EINVAL;
9301 }
9302
9303 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9304 hdd_err("attr trace level param failed");
9305 return -EINVAL;
9306 }
9307
9308 nla_for_each_nested(apth,
9309 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9310 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9311 nla_data(apth), nla_len(apth), NULL)) {
9312 hdd_err("Invalid attr");
9313 return -EINVAL;
9314 }
9315
9316 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9317 hdd_err("attr Module ID failed");
9318 return -EINVAL;
9319 }
9320 module_id = nla_get_u32
9321 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9322
9323 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9324 hdd_err("attr Verbose mask failed");
9325 return -EINVAL;
9326 }
9327 bit_mask = nla_get_u32
9328 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9329
9330 status = hdd_qdf_trace_enable(module_id, bit_mask);
9331
9332 if (status != 0)
9333 hdd_err("can not set verbose mask %d for the category %d",
9334 bit_mask, module_id);
9335 }
9336
9337 EXIT();
9338 return ret;
9339}
9340
9341/**
9342 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9343 * @wiphy: Pointer to wireless phy
9344 * @wdev: Pointer to wireless device
9345 * @data: Pointer to data
9346 * @data_len: Length of @data
9347 *
9348 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9349 *
9350 * Return: 0 on success, negative errno on failure
9351 */
9352
9353static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9354 struct wireless_dev *wdev,
9355 const void *data,
9356 int data_len)
9357{
9358 int ret;
9359
9360 cds_ssr_protect(__func__);
9361 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9362 cds_ssr_unprotect(__func__);
9363
9364 return ret;
9365}
9366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009367const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9368 {
9369 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9370 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9371 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309372 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009373 .doit = is_driver_dfs_capable
9374 },
9375
9376#ifdef WLAN_FEATURE_NAN
9377 {
9378 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9379 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9380 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9381 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9382 .doit = wlan_hdd_cfg80211_nan_request
9383 },
9384#endif
9385
9386#ifdef WLAN_FEATURE_STATS_EXT
9387 {
9388 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9389 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9390 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9391 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9392 .doit = wlan_hdd_cfg80211_stats_ext_request
9393 },
9394#endif
9395#ifdef FEATURE_WLAN_EXTSCAN
9396 {
9397 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9398 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9399 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9400 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9401 .doit = wlan_hdd_cfg80211_extscan_start
9402 },
9403 {
9404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9407 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9408 .doit = wlan_hdd_cfg80211_extscan_stop
9409 },
9410 {
9411 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9412 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9413 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9414 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9415 },
9416 {
9417 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9418 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9419 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9420 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9421 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9422 },
9423 {
9424 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9425 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9426 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9427 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9428 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9429 },
9430 {
9431 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9432 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9433 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9434 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9435 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9436 },
9437 {
9438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9441 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9442 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9443 },
9444 {
9445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9446 .info.subcmd =
9447 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9448 .flags =
9449 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9450 WIPHY_VENDOR_CMD_NEED_RUNNING,
9451 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9452 },
9453 {
9454 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9455 .info.subcmd =
9456 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9457 .flags =
9458 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9459 WIPHY_VENDOR_CMD_NEED_RUNNING,
9460 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9461 },
9462 {
9463 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9464 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9465 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9466 WIPHY_VENDOR_CMD_NEED_NETDEV |
9467 WIPHY_VENDOR_CMD_NEED_RUNNING,
9468 .doit = wlan_hdd_cfg80211_set_epno_list
9469 },
9470#endif /* FEATURE_WLAN_EXTSCAN */
9471
9472#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9473 {
9474 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9475 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9476 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9477 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9478 .doit = wlan_hdd_cfg80211_ll_stats_clear
9479 },
9480
9481 {
9482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9483 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9484 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9485 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9486 .doit = wlan_hdd_cfg80211_ll_stats_set
9487 },
9488
9489 {
9490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9491 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9492 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9493 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9494 .doit = wlan_hdd_cfg80211_ll_stats_get
9495 },
9496#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9497#ifdef FEATURE_WLAN_TDLS
9498 {
9499 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9500 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9501 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9502 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9503 .doit = wlan_hdd_cfg80211_exttdls_enable
9504 },
9505 {
9506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9507 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9508 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9509 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9510 .doit = wlan_hdd_cfg80211_exttdls_disable
9511 },
9512 {
9513 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9514 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9515 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9516 .doit = wlan_hdd_cfg80211_exttdls_get_status
9517 },
9518#endif
9519 {
9520 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9521 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9522 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9523 .doit = wlan_hdd_cfg80211_get_supported_features
9524 },
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9529 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9530 },
9531 {
9532 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9533 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9534 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309535 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009536 },
9537 {
9538 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9539 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9540 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9541 WIPHY_VENDOR_CMD_NEED_NETDEV,
9542 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9543 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009544 {
9545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9546 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9547 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9548 WIPHY_VENDOR_CMD_NEED_NETDEV,
9549 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9550 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009551 {
9552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9555 WIPHY_VENDOR_CMD_NEED_NETDEV |
9556 WIPHY_VENDOR_CMD_NEED_RUNNING,
9557 .doit = hdd_cfg80211_get_station_cmd
9558 },
9559 {
9560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9563 WIPHY_VENDOR_CMD_NEED_NETDEV |
9564 WIPHY_VENDOR_CMD_NEED_RUNNING,
9565 .doit = wlan_hdd_cfg80211_do_acs
9566 },
9567
9568 {
9569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9572 WIPHY_VENDOR_CMD_NEED_NETDEV,
9573 .doit = wlan_hdd_cfg80211_get_features
9574 },
9575#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9576 {
9577 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9578 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9579 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9580 WIPHY_VENDOR_CMD_NEED_NETDEV |
9581 WIPHY_VENDOR_CMD_NEED_RUNNING,
9582 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9583 },
9584#endif
9585#ifdef FEATURE_WLAN_EXTSCAN
9586 {
9587 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9588 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9589 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9590 WIPHY_VENDOR_CMD_NEED_NETDEV |
9591 WIPHY_VENDOR_CMD_NEED_RUNNING,
9592 .doit = wlan_hdd_cfg80211_set_passpoint_list
9593 },
9594 {
9595 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9596 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9597 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9598 WIPHY_VENDOR_CMD_NEED_NETDEV |
9599 WIPHY_VENDOR_CMD_NEED_RUNNING,
9600 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9601 },
9602 {
9603 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9604 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9605 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9606 WIPHY_VENDOR_CMD_NEED_NETDEV |
9607 WIPHY_VENDOR_CMD_NEED_RUNNING,
9608 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9609 },
9610 {
9611 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9612 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9613 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9614 WIPHY_VENDOR_CMD_NEED_NETDEV |
9615 WIPHY_VENDOR_CMD_NEED_RUNNING,
9616 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9617 },
9618#endif /* FEATURE_WLAN_EXTSCAN */
9619 {
9620 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9621 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9622 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9623 WIPHY_VENDOR_CMD_NEED_NETDEV,
9624 .doit = wlan_hdd_cfg80211_get_wifi_info
9625 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009626#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009627 {
9628 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9629 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9630 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9631 WIPHY_VENDOR_CMD_NEED_NETDEV |
9632 WIPHY_VENDOR_CMD_NEED_RUNNING,
9633 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9634 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009635#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009636 {
9637 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9638 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9639 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9640 WIPHY_VENDOR_CMD_NEED_NETDEV,
9641 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9642 },
9643 {
9644 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9645 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9646 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9647 WIPHY_VENDOR_CMD_NEED_NETDEV,
9648 .doit = wlan_hdd_cfg80211_wifi_logger_start
9649 },
9650 {
9651 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9652 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9653 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9654 WIPHY_VENDOR_CMD_NEED_NETDEV,
9655 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9656 },
9657 {
9658 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9659 .info.subcmd =
9660 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9661 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9662 WIPHY_VENDOR_CMD_NEED_NETDEV |
9663 WIPHY_VENDOR_CMD_NEED_RUNNING,
9664 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9665 },
9666 {
9667 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9668 .info.subcmd =
9669 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9671 WIPHY_VENDOR_CMD_NEED_NETDEV |
9672 WIPHY_VENDOR_CMD_NEED_RUNNING,
9673 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9674 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009675#ifdef WLAN_FEATURE_TSF
9676 {
9677 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9678 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9680 WIPHY_VENDOR_CMD_NEED_NETDEV |
9681 WIPHY_VENDOR_CMD_NEED_RUNNING,
9682 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9683 },
9684#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009685#ifdef FEATURE_WLAN_TDLS
9686 {
9687 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9688 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9689 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9690 WIPHY_VENDOR_CMD_NEED_NETDEV |
9691 WIPHY_VENDOR_CMD_NEED_RUNNING,
9692 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9693 },
9694#endif
9695#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9696 {
9697 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9698 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9699 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9700 WIPHY_VENDOR_CMD_NEED_NETDEV |
9701 WIPHY_VENDOR_CMD_NEED_RUNNING,
9702 .doit = wlan_hdd_cfg80211_offloaded_packets
9703 },
9704#endif
9705 {
9706 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9707 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9708 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9709 WIPHY_VENDOR_CMD_NEED_NETDEV |
9710 WIPHY_VENDOR_CMD_NEED_RUNNING,
9711 .doit = wlan_hdd_cfg80211_monitor_rssi
9712 },
9713 {
9714 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309715 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9716 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9717 WIPHY_VENDOR_CMD_NEED_NETDEV |
9718 WIPHY_VENDOR_CMD_NEED_RUNNING,
9719 .doit = wlan_hdd_cfg80211_set_ns_offload
9720 },
9721 {
9722 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009723 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9724 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9725 WIPHY_VENDOR_CMD_NEED_NETDEV |
9726 WIPHY_VENDOR_CMD_NEED_RUNNING,
9727 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9728 },
9729#ifdef WLAN_FEATURE_MEMDUMP
9730 {
9731 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9732 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9733 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9734 WIPHY_VENDOR_CMD_NEED_NETDEV |
9735 WIPHY_VENDOR_CMD_NEED_RUNNING,
9736 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9737 },
9738#endif /* WLAN_FEATURE_MEMDUMP */
9739 {
9740 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9741 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9742 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9743 WIPHY_VENDOR_CMD_NEED_NETDEV |
9744 WIPHY_VENDOR_CMD_NEED_RUNNING,
9745 .doit = wlan_hdd_cfg80211_vendor_scan
9746 },
9747
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309748 /* Vendor abort scan */
9749 {
9750 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9751 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9752 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9753 WIPHY_VENDOR_CMD_NEED_NETDEV |
9754 WIPHY_VENDOR_CMD_NEED_RUNNING,
9755 .doit = wlan_hdd_vendor_abort_scan
9756 },
9757
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 /* OCB commands */
9759 {
9760 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9761 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9762 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9763 WIPHY_VENDOR_CMD_NEED_NETDEV |
9764 WIPHY_VENDOR_CMD_NEED_RUNNING,
9765 .doit = wlan_hdd_cfg80211_ocb_set_config
9766 },
9767 {
9768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9769 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9770 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9771 WIPHY_VENDOR_CMD_NEED_NETDEV |
9772 WIPHY_VENDOR_CMD_NEED_RUNNING,
9773 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9774 },
9775 {
9776 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9777 .info.subcmd =
9778 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9779 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9780 WIPHY_VENDOR_CMD_NEED_NETDEV |
9781 WIPHY_VENDOR_CMD_NEED_RUNNING,
9782 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9783 },
9784 {
9785 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9786 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9787 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9788 WIPHY_VENDOR_CMD_NEED_NETDEV |
9789 WIPHY_VENDOR_CMD_NEED_RUNNING,
9790 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9791 },
9792 {
9793 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9794 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9795 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9796 WIPHY_VENDOR_CMD_NEED_NETDEV |
9797 WIPHY_VENDOR_CMD_NEED_RUNNING,
9798 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9799 },
9800 {
9801 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9802 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9803 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9804 WIPHY_VENDOR_CMD_NEED_NETDEV |
9805 WIPHY_VENDOR_CMD_NEED_RUNNING,
9806 .doit = wlan_hdd_cfg80211_dcc_get_stats
9807 },
9808 {
9809 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9810 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9811 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9812 WIPHY_VENDOR_CMD_NEED_NETDEV |
9813 WIPHY_VENDOR_CMD_NEED_RUNNING,
9814 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9815 },
9816 {
9817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9818 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9819 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9820 WIPHY_VENDOR_CMD_NEED_NETDEV |
9821 WIPHY_VENDOR_CMD_NEED_RUNNING,
9822 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9823 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309824 {
9825 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9826 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9827 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9828 WIPHY_VENDOR_CMD_NEED_NETDEV |
9829 WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_get_link_properties
9831 },
Peng Xu278d0122015-09-24 16:34:17 -07009832 {
Peng Xud2220962016-07-11 17:59:17 -07009833 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009834 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9835 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9836 WIPHY_VENDOR_CMD_NEED_NETDEV |
9837 WIPHY_VENDOR_CMD_NEED_RUNNING,
9838 .doit = wlan_hdd_cfg80211_set_ota_test
9839 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009840#ifdef FEATURE_LFR_SUBNET_DETECTION
9841 {
9842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9845 WIPHY_VENDOR_CMD_NEED_NETDEV |
9846 WIPHY_VENDOR_CMD_NEED_RUNNING,
9847 .doit = wlan_hdd_cfg80211_set_gateway_params
9848 },
9849#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009850 {
Peng Xud2220962016-07-11 17:59:17 -07009851 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009852 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9853 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9854 WIPHY_VENDOR_CMD_NEED_NETDEV |
9855 WIPHY_VENDOR_CMD_NEED_RUNNING,
9856 .doit = wlan_hdd_cfg80211_txpower_scale
9857 },
9858 {
9859 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9860 .info.subcmd =
9861 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9862 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9863 WIPHY_VENDOR_CMD_NEED_NETDEV |
9864 WIPHY_VENDOR_CMD_NEED_RUNNING,
9865 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9866 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309867 {
9868 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9869 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9870 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9871 WIPHY_VENDOR_CMD_NEED_NETDEV |
9872 WIPHY_VENDOR_CMD_NEED_RUNNING,
9873 .doit = wlan_hdd_cfg80211_bpf_offload
9874 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309875 {
9876 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309877 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9878 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9879 WIPHY_VENDOR_CMD_NEED_NETDEV |
9880 WIPHY_VENDOR_CMD_NEED_RUNNING,
9881 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9882 },
9883 {
9884 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309885 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9886 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9887 WIPHY_VENDOR_CMD_NEED_NETDEV |
9888 WIPHY_VENDOR_CMD_NEED_RUNNING,
9889 .doit = wlan_hdd_cfg80211_sta_roam_policy
9890 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309891#ifdef FEATURE_WLAN_CH_AVOID
9892 {
9893 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9894 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9895 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9896 WIPHY_VENDOR_CMD_NEED_NETDEV |
9897 WIPHY_VENDOR_CMD_NEED_RUNNING,
9898 .doit = wlan_hdd_cfg80211_avoid_freq
9899 },
9900#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309901 {
9902 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309903 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9904 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9905 WIPHY_VENDOR_CMD_NEED_NETDEV |
9906 WIPHY_VENDOR_CMD_NEED_RUNNING,
9907 .doit = wlan_hdd_cfg80211_sap_configuration_set
9908 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009909 {
Peng Xu4225c152016-07-14 21:18:14 -07009910 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009911 .info.subcmd =
9912 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9913 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9914 WIPHY_VENDOR_CMD_NEED_NETDEV |
9915 WIPHY_VENDOR_CMD_NEED_RUNNING,
9916 .doit = wlan_hdd_cfg80211_p2p_lo_start
9917 },
9918 {
9919 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9920 .info.subcmd =
9921 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9922 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9923 WIPHY_VENDOR_CMD_NEED_NETDEV |
9924 WIPHY_VENDOR_CMD_NEED_RUNNING,
9925 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9926 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9929 .info.subcmd =
9930 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9931 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9932 WIPHY_VENDOR_CMD_NEED_NETDEV |
9933 WIPHY_VENDOR_CMD_NEED_RUNNING,
9934 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9935 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009936#ifdef WLAN_FEATURE_NAN_DATAPATH
9937 {
9938 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9939 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9940 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9941 WIPHY_VENDOR_CMD_NEED_NETDEV |
9942 WIPHY_VENDOR_CMD_NEED_RUNNING,
9943 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9944 },
9945#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309946 {
9947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9948 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9949 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9950 WIPHY_VENDOR_CMD_NEED_NETDEV |
9951 WIPHY_VENDOR_CMD_NEED_RUNNING,
9952 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9953 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309954 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309955 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9956 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9958 WIPHY_VENDOR_CMD_NEED_NETDEV |
9959 WIPHY_VENDOR_CMD_NEED_RUNNING,
9960 .doit = wlan_hdd_cfg80211_get_bus_size
9961 },
9962 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309963 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9964 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
9965 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9966 WIPHY_VENDOR_CMD_NEED_NETDEV |
9967 WIPHY_VENDOR_CMD_NEED_RUNNING,
9968 .doit = wlan_hdd_cfg80211_update_vendor_channel
9969 },
9970 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309971 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9973 WIPHY_VENDOR_CMD_NEED_NETDEV |
9974 WIPHY_VENDOR_CMD_NEED_RUNNING,
9975 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309976 },
9977 {
9978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9979 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9981 WIPHY_VENDOR_CMD_NEED_NETDEV |
9982 WIPHY_VENDOR_CMD_NEED_RUNNING,
9983 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309984 },
9985#ifdef WLAN_FEATURE_DISA
9986 {
9987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9988 .info.subcmd =
9989 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
9990 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9991 WIPHY_VENDOR_CMD_NEED_NETDEV |
9992 WIPHY_VENDOR_CMD_NEED_RUNNING,
9993 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
9994 },
9995#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009996#ifdef FEATURE_WLAN_TDLS
9997 {
9998 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9999 .info.subcmd =
10000 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10002 WIPHY_VENDOR_CMD_NEED_NETDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010005 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010006#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010007 {
10008 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10009 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10013 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010014 {
10015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10018 WIPHY_VENDOR_CMD_NEED_NETDEV |
10019 WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_set_trace_level
10021 },
10022
Paul Zhang3a210c52016-12-08 10:18:12 +080010023#ifdef WLAN_UMAC_CONVERGENCE
10024 COMMON_VENDOR_COMMANDS
10025#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010026};
10027
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010028#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10029 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10030 defined(FEATURE_WLAN_SCAN_PNO)
10031/**
10032 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10033 * @wiphy: pointer to wiphy
10034 * @config: pointer to config
10035 *
10036 * Return: None
10037 */
10038static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10039 struct hdd_config *config)
10040{
10041 if (config->configPNOScanSupport) {
10042 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10043 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10044 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10045 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10046 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10047 if (config->max_sched_scan_plan_interval)
10048 wiphy->max_sched_scan_plan_interval =
10049 config->max_sched_scan_plan_interval;
10050 if (config->max_sched_scan_plan_iterations)
10051 wiphy->max_sched_scan_plan_iterations =
10052 config->max_sched_scan_plan_iterations;
10053 }
10054}
10055#else
10056static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10057 struct hdd_config *config)
10058{
10059}
10060#endif
10061
10062
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010063/**
10064 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10065 * @priv_size: Size of the hdd context.
10066 *
10067 * Allocate wiphy context and hdd context.
10068 *
10069 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010071hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010072{
10073 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010074 hdd_context_t *hdd_ctx;
10075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010076 ENTER();
10077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010078 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10079
10080 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010081 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010082 return NULL;
10083 }
10084
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010085 hdd_ctx = wiphy_priv(wiphy);
10086
10087 hdd_ctx->wiphy = wiphy;
10088
10089 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010090}
10091
10092/*
10093 * FUNCTION: wlan_hdd_cfg80211_update_band
10094 * This function is called from the supplicant through a
10095 * private ioctl to change the band value
10096 */
10097int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10098{
10099 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010100 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101
10102 ENTER();
10103
Dustin Browna30892e2016-10-12 17:28:36 -070010104 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010105
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010106 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010107 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010108
10109 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10110 struct ieee80211_supported_band *band = wiphy->bands[i];
10111
10112 channelEnabledState =
10113 cds_get_channel_state(band->channels[j].
10114 hw_value);
10115
Dustin Browna30892e2016-10-12 17:28:36 -070010116 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 /* 5G only */
10118#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10119 /* Enable Social channels for P2P */
10120 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10121 (band->channels[j].center_freq)
10122 && CHANNEL_STATE_ENABLE ==
10123 channelEnabledState)
10124 band->channels[j].flags &=
10125 ~IEEE80211_CHAN_DISABLED;
10126 else
10127#endif
10128 band->channels[j].flags |=
10129 IEEE80211_CHAN_DISABLED;
10130 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010131 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010132 eCSR_BAND_24 == eBand) {
10133 /* 2G only */
10134 band->channels[j].flags |=
10135 IEEE80211_CHAN_DISABLED;
10136 continue;
10137 }
10138
Amar Singhal6842e8f2016-02-23 16:30:32 -080010139 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140 band->channels[j].flags &=
10141 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010142 }
10143 }
10144 return 0;
10145}
10146
Peng Xuacfdda12017-02-06 16:15:38 -080010147#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148/*
10149 * FUNCTION: wlan_hdd_cfg80211_init
10150 * This function is called by hdd_wlan_startup()
10151 * during initialization.
10152 * This function is used to initialize and register wiphy structure.
10153 */
10154int wlan_hdd_cfg80211_init(struct device *dev,
10155 struct wiphy *wiphy, struct hdd_config *pCfg)
10156{
10157 int i, j;
10158 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10159
10160 ENTER();
10161
10162 /* Now bind the underlying wlan device with wiphy */
10163 set_wiphy_dev(wiphy, dev);
10164
10165 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10168 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010169 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170#else
10171 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010172 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010173#endif
10174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010175 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10176 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10177 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10178#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10179 | WIPHY_FLAG_4ADDR_STATION
10180#endif
10181 | WIPHY_FLAG_OFFCHAN_TX;
10182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10184 wiphy->wowlan = &wowlan_support_cfg80211_init;
10185#else
10186 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10187 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10188 wiphy->wowlan.pattern_min_len = 1;
10189 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10190#endif
10191
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010192 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193#ifdef FEATURE_WLAN_ESE
10194 || pCfg->isEseIniFeatureEnabled
10195#endif
10196 ) {
10197 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10198 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199#ifdef FEATURE_WLAN_TDLS
10200 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10201 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10202#endif
10203
10204 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10205
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010206#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10207 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10208#endif
10209
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010210 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010211
10212#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010213 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214#endif
10215
10216 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010217 * driver can still register regulatory callback and
10218 * it will get regulatory settings in wiphy->band[], but
10219 * driver need to determine what to do with both
10220 * regulatory settings
10221 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010222
10223 wiphy->reg_notifier = hdd_reg_notifier;
10224
10225#if defined QCA_WIFI_FTM
10226}
10227#endif
10228
10229 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10230
10231 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10232
10233 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10234
Arun Khandavallifae92942016-08-01 13:31:08 +053010235 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10236 | BIT(NL80211_IFTYPE_ADHOC)
10237 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10238 | BIT(NL80211_IFTYPE_P2P_GO)
10239 | BIT(NL80211_IFTYPE_AP)
10240 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010241
Arun Khandavallifae92942016-08-01 13:31:08 +053010242 if (pCfg->advertiseConcurrentOperation) {
10243 if (pCfg->enableMCC) {
10244 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010245
Arun Khandavallifae92942016-08-01 13:31:08 +053010246 for (i = 0;
10247 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10248 i++) {
10249 if (!pCfg->allowMCCGODiffBI)
10250 wlan_hdd_iface_combination[i].
10251 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010252 }
10253 }
10254 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010255 ARRAY_SIZE(wlan_hdd_iface_combination);
10256 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257 }
10258
10259 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010260 * on ini values
10261 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262 if (!pCfg->ShortGI20MhzEnable) {
10263 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10264 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010265 }
10266
10267 if (!pCfg->ShortGI40MhzEnable) {
10268 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10269 }
10270
10271 if (!pCfg->nChannelBondingMode5GHz) {
10272 wlan_hdd_band_5_ghz.ht_cap.cap &=
10273 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10274 }
10275
Abhishek Singhf512bf32016-05-04 16:47:46 +053010276 /*
10277 * In case of static linked driver at the time of driver unload,
10278 * module exit doesn't happens. Module cleanup helps in cleaning
10279 * of static memory.
10280 * If driver load happens statically, at the time of driver unload,
10281 * wiphy flags don't get reset because of static memory.
10282 * It's better not to store channel in static memory.
10283 */
Dustin Browna30892e2016-10-12 17:28:36 -070010284 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10285 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010286 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010287 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010288 hdd_err("Not enough memory to allocate channels");
10289 return -ENOMEM;
10290 }
Dustin Browna30892e2016-10-12 17:28:36 -070010291 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010292 &hdd_channels_2_4_ghz[0],
10293 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010294 if ((hdd_is_5g_supported(pHddCtx)) &&
10295 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10296 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10297 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10298 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010299 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10300 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010301 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010302 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010303 hdd_err("Not enough memory to allocate channels");
10304 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010305 bands[NL80211_BAND_2GHZ]->channels);
10306 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010307 return -ENOMEM;
10308 }
Dustin Browna30892e2016-10-12 17:28:36 -070010309 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010310 &hdd_channels_5_ghz[0],
10311 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 }
10313
Dustin Browna30892e2016-10-12 17:28:36 -070010314 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010316 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010317 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318
10319 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10320 struct ieee80211_supported_band *band = wiphy->bands[i];
10321
Dustin Browna30892e2016-10-12 17:28:36 -070010322 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 eCSR_BAND_5G == pCfg->nBandCapability) {
10324 /* 5G only */
10325#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10326 /* Enable social channels for P2P */
10327 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10328 (band->channels[j].center_freq))
10329 band->channels[j].flags &=
10330 ~IEEE80211_CHAN_DISABLED;
10331 else
10332#endif
10333 band->channels[j].flags |=
10334 IEEE80211_CHAN_DISABLED;
10335 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010336 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010337 eCSR_BAND_24 == pCfg->nBandCapability) {
10338 /* 2G only */
10339 band->channels[j].flags |=
10340 IEEE80211_CHAN_DISABLED;
10341 continue;
10342 }
10343 }
10344 }
10345 /*Initialise the supported cipher suite details */
10346 wiphy->cipher_suites = hdd_cipher_suites;
10347 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10348
10349 /*signal strength in mBm (100*dBm) */
10350 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10351 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10352
Anurag Chouhan6d760662016-02-20 16:05:43 +053010353 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 wiphy->n_vendor_commands =
10355 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10356 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10357
10358 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10359 wiphy->n_vendor_events =
10360 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10361 }
10362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 if (pCfg->enableDFSMasterCap) {
10364 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10365 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366
10367 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10368
10369#ifdef QCA_HT_2040_COEX
10370 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10371#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010372 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010373 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010374 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 EXIT();
10377 return 0;
10378}
10379
Abhishek Singhf512bf32016-05-04 16:47:46 +053010380/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010381 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10382 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010383 *
10384 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010385 * memory allocated in wlan_hdd_cfg80211_init also
10386 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010387 *
10388 * Return: void
10389 */
10390void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10391{
10392 int i;
10393
Dustin Browna30892e2016-10-12 17:28:36 -070010394 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010395 if (NULL != wiphy->bands[i] &&
10396 (NULL != wiphy->bands[i]->channels)) {
10397 qdf_mem_free(wiphy->bands[i]->channels);
10398 wiphy->bands[i]->channels = NULL;
10399 }
10400 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010401 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010402}
10403
Yingying Tang80e15f32016-09-27 18:23:01 +080010404/**
10405 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10406 * @hdd_ctx: HDD context
10407 *
10408 * this function will update capabilities for supported bands
10409 *
10410 * Return: void
10411 */
10412static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10413{
10414 uint32_t val32;
10415 uint16_t val16;
10416 tSirMacHTCapabilityInfo *ht_cap_info;
10417 QDF_STATUS status;
10418
10419 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10420 if (QDF_STATUS_SUCCESS != status) {
10421 hdd_err("could not get HT capability info");
10422 val32 = 0;
10423 }
10424 val16 = (uint16_t)val32;
10425 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10426
10427 if (ht_cap_info->txSTBC == true) {
10428 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10429 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10430 IEEE80211_HT_CAP_TX_STBC;
10431 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10432 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10433 IEEE80211_HT_CAP_TX_STBC;
10434 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010435
10436 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10437 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10438 vht_cap.vht_supported = 0;
10439 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10440 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10441 vht_cap.vht_supported = 0;
10442 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10443 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010444}
10445
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010446/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010447 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010448 * initialization. In wlan_hdd_cfg80211_init, only the
10449 * default values will be initialized. The final initialization
10450 * of all required members can be done here.
10451 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010452void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453{
Yingying Tang80e15f32016-09-27 18:23:01 +080010454 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10455
10456 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010457}
10458
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010459/**
10460 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10461 * @cfg: hdd cfg
10462 *
10463 * this function update 11n mode in hdd cfg
10464 *
10465 * Return: void
10466 */
10467void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10468{
10469 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10470 hdd_notice("support 11ac");
10471 } else {
10472 hdd_notice("not support 11ac");
10473 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10474 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10475 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10476 cfg->sap_p2p_11ac_override = 0;
10477 }
10478 }
10479}
10480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010481/* In this function we are registering wiphy. */
10482int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10483{
10484 ENTER();
10485 /* Register our wiphy dev with cfg80211 */
10486 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010487 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 return -EIO;
10489 }
10490
10491 EXIT();
10492 return 0;
10493}
10494
10495/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010496 * HDD function to update wiphy capability based on target offload status.
10497 *
10498 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10499 * capability even before downloading firmware to the target. In discrete
10500 * case, host will get know certain offload capability (say sched_scan
10501 * caps) only after downloading firmware to the target and target boots up.
10502 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10503 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010504 */
10505void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10506{
10507#ifdef FEATURE_WLAN_SCAN_PNO
10508 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10509 struct hdd_config *pCfg = pHddCtx->config;
10510
10511 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10512 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010513 * have PNO support.
10514 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010515 if (!pCfg->PnoOffload) {
10516 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10517 wiphy->max_sched_scan_ssids = 0;
10518 wiphy->max_match_sets = 0;
10519 wiphy->max_sched_scan_ie_len = 0;
10520 }
10521#endif
10522}
10523
10524/* This function registers for all frame which supplicant is interested in */
10525void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10526{
10527 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10528 /* Register for all P2P action, public action etc frames */
10529 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10530
10531 ENTER();
10532
Abhishek Singh7996eb72015-12-30 17:24:02 +053010533 /* Register frame indication call back */
10534 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10535
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010536 /* Register for p2p ack indication */
10537 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010539 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010540 * initialized. Once we will move to 2.6.37 kernel, in which we have
10541 * frame register ops, we will move this code as a part of that
10542 */
10543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010544 /* GAS Initial Request */
10545 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10546 (uint8_t *) GAS_INITIAL_REQ,
10547 GAS_INITIAL_REQ_SIZE);
10548
10549 /* GAS Initial Response */
10550 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10551 (uint8_t *) GAS_INITIAL_RSP,
10552 GAS_INITIAL_RSP_SIZE);
10553
10554 /* GAS Comeback Request */
10555 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10556 (uint8_t *) GAS_COMEBACK_REQ,
10557 GAS_COMEBACK_REQ_SIZE);
10558
10559 /* GAS Comeback Response */
10560 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10561 (uint8_t *) GAS_COMEBACK_RSP,
10562 GAS_COMEBACK_RSP_SIZE);
10563
10564 /* P2P Public Action */
10565 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10566 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10567 P2P_PUBLIC_ACTION_FRAME_SIZE);
10568
10569 /* P2P Action */
10570 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10571 (uint8_t *) P2P_ACTION_FRAME,
10572 P2P_ACTION_FRAME_SIZE);
10573
10574 /* WNM BSS Transition Request frame */
10575 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10576 (uint8_t *) WNM_BSS_ACTION_FRAME,
10577 WNM_BSS_ACTION_FRAME_SIZE);
10578
10579 /* WNM-Notification */
10580 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10581 (uint8_t *) WNM_NOTIFICATION_FRAME,
10582 WNM_NOTIFICATION_FRAME_SIZE);
10583}
10584
10585void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10586{
10587 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10588 /* Register for all P2P action, public action etc frames */
10589 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10590
10591 ENTER();
10592
10593 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010594 * initialized. Once we will move to 2.6.37 kernel, in which we have
10595 * frame register ops, we will move this code as a part of that
10596 */
10597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010598 /* GAS Initial Request */
10599
10600 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10601 (uint8_t *) GAS_INITIAL_REQ,
10602 GAS_INITIAL_REQ_SIZE);
10603
10604 /* GAS Initial Response */
10605 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10606 (uint8_t *) GAS_INITIAL_RSP,
10607 GAS_INITIAL_RSP_SIZE);
10608
10609 /* GAS Comeback Request */
10610 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10611 (uint8_t *) GAS_COMEBACK_REQ,
10612 GAS_COMEBACK_REQ_SIZE);
10613
10614 /* GAS Comeback Response */
10615 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10616 (uint8_t *) GAS_COMEBACK_RSP,
10617 GAS_COMEBACK_RSP_SIZE);
10618
10619 /* P2P Public Action */
10620 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10621 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10622 P2P_PUBLIC_ACTION_FRAME_SIZE);
10623
10624 /* P2P Action */
10625 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10626 (uint8_t *) P2P_ACTION_FRAME,
10627 P2P_ACTION_FRAME_SIZE);
10628
10629 /* WNM-Notification */
10630 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10631 (uint8_t *) WNM_NOTIFICATION_FRAME,
10632 WNM_NOTIFICATION_FRAME_SIZE);
10633}
10634
10635#ifdef FEATURE_WLAN_WAPI
10636void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10637 const uint8_t *mac_addr, const uint8_t *key,
10638 int key_Len)
10639{
10640 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10641 tCsrRoamSetKey setKey;
10642 bool isConnected = true;
10643 int status = 0;
10644 uint32_t roamId = 0xFF;
10645 uint8_t *pKeyPtr = NULL;
10646 int n = 0;
10647
Jeff Johnson46b40792016-06-29 14:03:14 -070010648 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 hdd_device_mode_to_string(pAdapter->device_mode),
10650 pAdapter->device_mode);
10651
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010652 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 setKey.keyId = key_index; /* Store Key ID */
10654 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10655 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10656 setKey.paeRole = 0; /* the PAE role */
10657 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010658 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010660 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661 }
10662 setKey.keyLength = key_Len;
10663 pKeyPtr = setKey.Key;
10664 memcpy(pKeyPtr, key, key_Len);
10665
Jeff Johnson46b40792016-06-29 14:03:14 -070010666 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010667 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010668 hdd_notice("WAPI KEY Data[%d]:%02x ",
10669 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010670
10671 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10672 if (isConnected) {
10673 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10674 pAdapter->sessionId, &setKey, &roamId);
10675 }
10676 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010677 hdd_err("sme_roam_set_key returned ERROR status= %d",
10678 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010679 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10680 }
10681}
10682#endif /* FEATURE_WLAN_WAPI */
10683
10684uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10685 uint8_t eid)
10686{
10687 int left = length;
10688 uint8_t *ptr = (uint8_t *)ies_ptr;
10689 uint8_t elem_id, elem_len;
10690
10691 while (left >= 2) {
10692 elem_id = ptr[0];
10693 elem_len = ptr[1];
10694 left -= 2;
10695 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010696 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 eid, elem_len, left);
10698 return NULL;
10699 }
10700 if (elem_id == eid) {
10701 return ptr;
10702 }
10703
10704 left -= elem_len;
10705 ptr += (elem_len + 2);
10706 }
10707 return NULL;
10708}
10709
10710/*
10711 * FUNCTION: wlan_hdd_validate_operation_channel
10712 * called by wlan_hdd_cfg80211_start_bss() and
10713 * wlan_hdd_set_channel()
10714 * This function validates whether given channel is part of valid
10715 * channel list.
10716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010717QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010718 int channel)
10719{
10720
10721 uint32_t num_ch = 0;
10722 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10723 u32 indx = 0;
10724 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10725 uint8_t fValidChannel = false, count = 0;
10726 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10727
10728 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10729
10730 if (hdd_pConfig_ini->sapAllowAllChannel) {
10731 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010732 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010733 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734 fValidChannel = true;
10735 break;
10736 }
10737 }
10738 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010739 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010740 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010741 }
10742 } else {
10743 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10744 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010745 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010746 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010747 }
10748 for (indx = 0; indx < num_ch; indx++) {
10749 if (channel == valid_ch[indx]) {
10750 break;
10751 }
10752 }
10753
10754 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010755 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010756 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757 }
10758 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010759 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760
10761}
10762
10763#ifdef DHCP_SERVER_OFFLOAD
10764static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10765{
10766 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10767 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10768 uint8_t numEntries = 0;
10769 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10770 uint8_t num;
10771 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010772 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010774 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010775 return;
10776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10778 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10779 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10780 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10781 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10782 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010783 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010784 goto end;
10785 }
10786 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010787 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 goto end;
10789 }
10790 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010791 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792 goto end;
10793 }
10794 for (num = 0; num < numEntries; num++) {
10795 temp = srv_ip[num];
10796 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10797 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010798 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010800 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 goto end;
10802 }
Jeff Johnson77848112016-06-29 14:52:06 -070010803 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010805 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 return;
10807}
10808#endif /* DHCP_SERVER_OFFLOAD */
10809
10810static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10811 struct net_device *dev,
10812 struct bss_parameters *params)
10813{
10814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10815 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10816 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010817 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818
10819 ENTER();
10820
Anurag Chouhan6d760662016-02-20 16:05:43 +053010821 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010822 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010823 return -EINVAL;
10824 }
10825
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010826 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10827 hdd_err("invalid session id: %d", pAdapter->sessionId);
10828 return -EINVAL;
10829 }
10830
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010831 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10833 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010834 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010835 hdd_device_mode_to_string(pAdapter->device_mode),
10836 pAdapter->device_mode, params->ap_isolate);
10837
10838 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10839 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010840 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010841 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842
Krunal Sonib4326f22016-03-10 13:05:51 -080010843 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10844 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 return -EOPNOTSUPP;
10846 }
10847
10848 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010849 * want to update this parameter
10850 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851 if (-1 != params->ap_isolate) {
10852 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10853 !!params->ap_isolate;
10854
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010855 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 pAdapter->sessionId,
10857 pAdapter->sessionCtx.
10858 ap.
10859 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010860 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 ret = -EINVAL;
10862 }
10863 }
10864
10865 EXIT();
10866 return ret;
10867}
10868
Krunal Soni8c37e322016-02-03 16:08:37 -080010869/**
10870 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10871 * @ndev: pointer to net device provided by supplicant
10872 * @type: type of the interface, upper layer wanted to change
10873 *
10874 * Upper layer provides the new interface mode that needs to be changed
10875 * for given net device
10876 *
10877 * Return: success or failure in terms of integer value
10878 */
10879static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 enum nl80211_iftype type)
10881{
Krunal Soni8c37e322016-02-03 16:08:37 -080010882 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10883 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10884 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010885 hdd_wext_state_t *wext;
10886 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010887 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010888
10889 ENTER();
10890
Krunal Soni8c37e322016-02-03 16:08:37 -080010891 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010892 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 return 0;
10894 }
10895
10896 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010897 hdd_stop_adapter(hdd_ctx, adapter, true);
10898 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899 wdev->iftype = type;
10900 /*Check for sub-string p2p to confirm its a p2p interface */
10901 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010902 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010903 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010904 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010905 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010906 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010908 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010910 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010911 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010912 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10913 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010914 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10915 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010917 adapter->scan_info.scanAddIE.length;
10918 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010919 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010920 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10921 wext->roamProfile.phyMode =
10922 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10923 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010924 EXIT();
10925 return status;
10926}
10927
10928static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10929 struct net_device *dev,
10930 struct bss_parameters *params)
10931{
10932 int ret;
10933
10934 cds_ssr_protect(__func__);
10935 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10936 cds_ssr_unprotect(__func__);
10937
10938 return ret;
10939}
10940
10941/* FUNCTION: wlan_hdd_change_country_code_cd
10942 * to wait for contry code completion
10943 */
10944void *wlan_hdd_change_country_code_cb(void *pAdapter)
10945{
10946 hdd_adapter_t *call_back_pAdapter = pAdapter;
10947 complete(&call_back_pAdapter->change_country_code);
10948 return NULL;
10949}
10950
Rajeev Kumar98edb772016-01-19 12:42:19 -080010951/**
10952 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10953 * @wiphy: Pointer to the wiphy structure
10954 * @ndev: Pointer to the net device
10955 * @type: Interface type
10956 * @flags: Flags for change interface
10957 * @params: Pointer to change interface parameters
10958 *
10959 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 */
10961static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10962 struct net_device *ndev,
10963 enum nl80211_iftype type,
10964 u32 *flags,
10965 struct vif_params *params)
10966{
10967 struct wireless_dev *wdev;
10968 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10969 hdd_context_t *pHddCtx;
10970 tCsrRoamProfile *pRoamProfile = NULL;
10971 eCsrRoamBssType LastBSSType;
10972 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010973 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 int status;
10975
10976 ENTER();
10977
Anurag Chouhan6d760662016-02-20 16:05:43 +053010978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010980 return -EINVAL;
10981 }
10982
10983 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10984 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010985 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010986 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010988 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
10990 pAdapter->sessionId, type));
10991
Jeff Johnson77848112016-06-29 14:52:06 -070010992 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 pAdapter->device_mode, type);
10994
Arun Khandavallifae92942016-08-01 13:31:08 +053010995 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
10996 if (status) {
10997 hdd_err("Failed to start modules");
10998 return -EINVAL;
10999 }
11000
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011001 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11003 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011004 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011005 return -EINVAL;
11006 }
11007
11008 pConfig = pHddCtx->config;
11009 wdev = ndev->ieee80211_ptr;
11010
11011 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011012 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013
11014 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
11015
Krunal Sonib4326f22016-03-10 13:05:51 -080011016 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11017 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11018 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11019 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 hdd_wext_state_t *pWextState =
11021 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11022
11023 pRoamProfile = &pWextState->roamProfile;
11024 LastBSSType = pRoamProfile->BSSType;
11025
11026 switch (type) {
11027 case NL80211_IFTYPE_STATION:
11028 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011029 case NL80211_IFTYPE_ADHOC:
11030 if (type == NL80211_IFTYPE_ADHOC) {
11031 wlan_hdd_tdls_exit(pAdapter);
11032 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011033 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011034 }
11035 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11036 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011037 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011038 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011039 if (hdd_start_adapter(pAdapter)) {
11040 hdd_err("Failed to start adapter :%d",
11041 pAdapter->device_mode);
11042 return -EINVAL;
11043 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 case NL80211_IFTYPE_AP:
11046 case NL80211_IFTYPE_P2P_GO:
11047 {
Jeff Johnson77848112016-06-29 14:52:06 -070011048 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011049 (type ==
11050 NL80211_IFTYPE_AP) ? "SoftAP" :
11051 "P2pGo");
11052
11053 /* Cancel any remain on channel for GO mode */
11054 if (NL80211_IFTYPE_P2P_GO == type) {
11055 wlan_hdd_cancel_existing_remain_on_channel
11056 (pAdapter);
11057 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011058
Arun Khandavallifae92942016-08-01 13:31:08 +053011059 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011060 /* De-init the adapter */
11061 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11062 memset(&pAdapter->sessionCtx, 0,
11063 sizeof(pAdapter->sessionCtx));
11064 pAdapter->device_mode =
11065 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011066 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11067 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011068
11069 /*
11070 * Fw will take care incase of concurrency
11071 */
11072
Krunal Sonib4326f22016-03-10 13:05:51 -080011073 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011075 /* To meet Android requirements create
11076 * a randomized MAC address of the
11077 * form 02:1A:11:Fx:xx:xx
11078 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 get_random_bytes(&ndev->dev_addr[3], 3);
11080 ndev->dev_addr[0] = 0x02;
11081 ndev->dev_addr[1] = 0x1A;
11082 ndev->dev_addr[2] = 0x11;
11083 ndev->dev_addr[3] |= 0xF0;
11084 memcpy(pAdapter->macAddressCurrent.
11085 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011086 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 pr_info("wlan: Generated HotSpot BSSID "
11088 MAC_ADDRESS_STR "\n",
11089 MAC_ADDR_ARRAY(ndev->dev_addr));
11090 }
11091
11092 hdd_set_ap_ops(pAdapter->dev);
11093
Arun Khandavallifae92942016-08-01 13:31:08 +053011094 if (hdd_start_adapter(pAdapter)) {
11095 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 return -EINVAL;
11097 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 /* Interface type changed update in wiphy structure */
11099 if (wdev) {
11100 wdev->iftype = type;
11101 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011102 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103 return -EINVAL;
11104 }
11105 goto done;
11106 }
11107
11108 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011109 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 type);
11111 return -EOPNOTSUPP;
11112 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011113 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11114 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 switch (type) {
11116 case NL80211_IFTYPE_STATION:
11117 case NL80211_IFTYPE_P2P_CLIENT:
11118 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011119 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11120 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011121 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011122 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011123 if (hdd_start_adapter(pAdapter)) {
11124 hdd_err("Failed to start adapter :%d",
11125 pAdapter->device_mode);
11126 return -EINVAL;
11127 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 goto done;
11129
11130 case NL80211_IFTYPE_AP:
11131 case NL80211_IFTYPE_P2P_GO:
11132 wdev->iftype = type;
11133 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011134 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011135 goto done;
11136
11137 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011138 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139 type);
11140 return -EOPNOTSUPP;
11141 }
11142 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011143 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 pAdapter->device_mode);
11145 return -EOPNOTSUPP;
11146 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147done:
11148 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011149 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011151 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152
11153 EXIT();
11154 return 0;
11155}
11156
Rajeev Kumar98edb772016-01-19 12:42:19 -080011157/**
11158 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11159 * @wiphy: Pointer to the wiphy structure
11160 * @ndev: Pointer to the net device
11161 * @type: Interface type
11162 * @flags: Flags for change interface
11163 * @params: Pointer to change interface parameters
11164 *
11165 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 */
11167static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11168 struct net_device *ndev,
11169 enum nl80211_iftype type,
11170 u32 *flags,
11171 struct vif_params *params)
11172{
11173 int ret;
11174
11175 cds_ssr_protect(__func__);
11176 ret =
11177 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11178 cds_ssr_unprotect(__func__);
11179
11180 return ret;
11181}
11182
11183#ifdef FEATURE_WLAN_TDLS
11184static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11185 int index, uint8_t match)
11186{
11187 int i;
11188 for (i = 0; i < index; i++) {
11189 if (arr[i] == match)
11190 return true;
11191 }
11192 return false;
11193}
11194#endif
11195
11196/**
11197 * __wlan_hdd_change_station() - change station
11198 * @wiphy: Pointer to the wiphy structure
11199 * @dev: Pointer to the net device.
11200 * @mac: bssid
11201 * @params: Pointer to station parameters
11202 *
11203 * Return: 0 for success, error number on failure.
11204 */
11205#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11206static int __wlan_hdd_change_station(struct wiphy *wiphy,
11207 struct net_device *dev,
11208 const uint8_t *mac,
11209 struct station_parameters *params)
11210#else
11211static int __wlan_hdd_change_station(struct wiphy *wiphy,
11212 struct net_device *dev,
11213 uint8_t *mac,
11214 struct station_parameters *params)
11215#endif
11216{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011217 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11219 hdd_context_t *pHddCtx;
11220 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011221 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222#ifdef FEATURE_WLAN_TDLS
11223 tCsrStaParams StaParams = { 0 };
11224 uint8_t isBufSta = 0;
11225 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011226 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227#endif
11228 int ret;
11229
11230 ENTER();
11231
Anurag Chouhan6d760662016-02-20 16:05:43 +053011232 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011233 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 return -EINVAL;
11235 }
11236
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011237 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 TRACE_CODE_HDD_CHANGE_STATION,
11239 pAdapter->sessionId, params->listen_interval));
11240
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011241 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11242 hdd_err("invalid session id: %d", pAdapter->sessionId);
11243 return -EINVAL;
11244 }
11245
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11247 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011248 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250
11251 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11252
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011253 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254
Krunal Sonib4326f22016-03-10 13:05:51 -080011255 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11256 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11258 status =
11259 hdd_softap_change_sta_state(pAdapter,
11260 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011261 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011263 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011264 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011265 return -EINVAL;
11266 }
11267 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011268 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11269 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270#ifdef FEATURE_WLAN_TDLS
11271 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011272
11273 if (cds_is_sub_20_mhz_enabled()) {
11274 hdd_err("TDLS not allowed with sub 20 MHz");
11275 return -EINVAL;
11276 }
11277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011278 StaParams.capability = params->capability;
11279 StaParams.uapsd_queues = params->uapsd_queues;
11280 StaParams.max_sp = params->max_sp;
11281
11282 /* Convert (first channel , number of channels) tuple to
11283 * the total list of channels. This goes with the assumption
11284 * that if the first channel is < 14, then the next channels
11285 * are an incremental of 1 else an incremental of 4 till the number
11286 * of channels.
11287 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011288 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289 if (0 != params->supported_channels_len) {
11290 int i = 0, j = 0, k = 0, no_of_channels = 0;
11291 int num_unique_channels;
11292 int next;
11293 for (i = 0;
11294 i < params->supported_channels_len
11295 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11296 int wifi_chan_index;
11297 if (!wlan_hdd_is_duplicate_channel
11298 (StaParams.supported_channels, j,
11299 params->supported_channels[i])) {
11300 StaParams.
11301 supported_channels[j] =
11302 params->
11303 supported_channels[i];
11304 } else {
11305 continue;
11306 }
11307 wifi_chan_index =
11308 ((StaParams.supported_channels[j] <=
11309 HDD_CHANNEL_14) ? 1 : 4);
11310 no_of_channels =
11311 params->supported_channels[i + 1];
11312
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011313 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d", i, j, k, j,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011314 StaParams.
11315 supported_channels[j],
11316 wifi_chan_index,
11317 no_of_channels);
11318 for (k = 1; k <= no_of_channels &&
11319 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11320 k++) {
11321 next =
11322 StaParams.
11323 supported_channels[j] +
11324 wifi_chan_index;
11325 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11326 StaParams.
11327 supported_channels[j
11328 +
11329 1]
11330 = next;
11331 } else {
11332 continue;
11333 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011334 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335 j + 1,
11336 StaParams.
11337 supported_channels[j +
11338 1]);
11339 j += 1;
11340 }
11341 }
11342 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011343 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011345 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 StaParams.
11347 supported_channels[i]);
11348 }
11349 if (MAX_CHANNEL < num_unique_channels)
11350 num_unique_channels = MAX_CHANNEL;
11351 StaParams.supported_channels_len =
11352 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011353 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 StaParams.supported_channels_len);
11355 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011356 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357 params->supported_oper_classes,
11358 params->supported_oper_classes_len);
11359 StaParams.supported_oper_classes_len =
11360 params->supported_oper_classes_len;
11361
11362 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011363 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011364 params->ext_capab,
11365 sizeof(StaParams.extn_capability));
11366
11367 if (NULL != params->ht_capa) {
11368 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011369 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 sizeof(tSirHTCap));
11371 }
11372
11373 StaParams.supported_rates_len =
11374 params->supported_rates_len;
11375
11376 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11377 * The supported_rates array , for all the structures propogating till Add Sta
11378 * to the firmware has to be modified , if the supplicant (ieee80211) is
11379 * modified to send more rates.
11380 */
11381
11382 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11383 */
11384 if (StaParams.supported_rates_len >
11385 SIR_MAC_MAX_SUPP_RATES)
11386 StaParams.supported_rates_len =
11387 SIR_MAC_MAX_SUPP_RATES;
11388
11389 if (0 != StaParams.supported_rates_len) {
11390 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011391 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392 params->supported_rates,
11393 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011394 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011395 StaParams.supported_rates_len);
11396 for (i = 0; i < StaParams.supported_rates_len;
11397 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011398 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 StaParams.supported_rates[i]);
11400 }
11401
11402 if (NULL != params->vht_capa) {
11403 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011404 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011405 params->vht_capa,
11406 sizeof(tSirVHTCap));
11407 }
11408
11409 if (0 != params->ext_capab_len) {
11410 /*Define A Macro : TODO Sunil */
11411 if ((1 << 4) & StaParams.extn_capability[3]) {
11412 isBufSta = 1;
11413 }
11414 /* TDLS Channel Switching Support */
11415 if ((1 << 6) & StaParams.extn_capability[3]) {
11416 isOffChannelSupported = 1;
11417 }
11418 }
11419
Nitesh Shah99934ac2016-09-05 15:54:08 +053011420 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011421 (params->ht_capa || params->vht_capa ||
11422 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011423 is_qos_wmm_sta = true;
11424
11425 hdd_notice("%s: TDLS Peer is QOS capable"
11426 " is_qos_wmm_sta= %d HTcapPresent = %d",
11427 __func__, is_qos_wmm_sta,
11428 StaParams.htcap_present);
11429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011431 &StaParams,
11432 isBufSta,
11433 isOffChannelSupported,
11434 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011435 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011436 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437 return -EINVAL;
11438 }
11439
11440 status =
11441 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11442 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011443 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011444 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011445 return -EINVAL;
11446 }
11447 }
11448#endif
11449 }
11450 EXIT();
11451 return ret;
11452}
11453
11454/**
11455 * wlan_hdd_change_station() - cfg80211 change station handler function
11456 * @wiphy: Pointer to the wiphy structure
11457 * @dev: Pointer to the net device.
11458 * @mac: bssid
11459 * @params: Pointer to station parameters
11460 *
11461 * This is the cfg80211 change station handler function which invokes
11462 * the internal function @__wlan_hdd_change_station with
11463 * SSR protection.
11464 *
11465 * Return: 0 for success, error number on failure.
11466 */
11467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11468static int wlan_hdd_change_station(struct wiphy *wiphy,
11469 struct net_device *dev,
11470 const u8 *mac,
11471 struct station_parameters *params)
11472#else
11473static int wlan_hdd_change_station(struct wiphy *wiphy,
11474 struct net_device *dev,
11475 u8 *mac,
11476 struct station_parameters *params)
11477#endif
11478{
11479 int ret;
11480
11481 cds_ssr_protect(__func__);
11482 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11483 cds_ssr_unprotect(__func__);
11484
11485 return ret;
11486}
11487
11488/*
11489 * FUNCTION: __wlan_hdd_cfg80211_add_key
11490 * This function is used to initialize the key information
11491 */
11492static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11493 struct net_device *ndev,
11494 u8 key_index, bool pairwise,
11495 const u8 *mac_addr,
11496 struct key_params *params)
11497{
11498 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11499 tCsrRoamSetKey setKey;
11500 int status;
11501 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011503 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011504 hdd_context_t *pHddCtx;
11505 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11506
11507 ENTER();
11508
Anurag Chouhan6d760662016-02-20 16:05:43 +053011509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011510 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 return -EINVAL;
11512 }
11513
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011514 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11515 hdd_err("invalid session id: %d", pAdapter->sessionId);
11516 return -EINVAL;
11517 }
11518
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011519 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11521 pAdapter->sessionId, params->key_len));
11522 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11523 status = wlan_hdd_validate_context(pHddCtx);
11524
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011525 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011527
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011528 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 hdd_device_mode_to_string(pAdapter->device_mode),
11530 pAdapter->device_mode);
11531
11532 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011533 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011534
11535 return -EINVAL;
11536 }
11537
11538 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011539 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540
11541 return -EINVAL;
11542 }
11543
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011544 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545
11546 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011547 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011548 setKey.keyId = key_index;
11549 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011550 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551
11552 switch (params->cipher) {
11553 case WLAN_CIPHER_SUITE_WEP40:
11554 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11555 break;
11556
11557 case WLAN_CIPHER_SUITE_WEP104:
11558 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11559 break;
11560
11561 case WLAN_CIPHER_SUITE_TKIP:
11562 {
11563 u8 *pKey = &setKey.Key[0];
11564 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11565
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011566 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011568 /* Supplicant sends the 32bytes key in this order
11569 *
11570 * |--------------|----------|----------|
11571 * | Tk1 |TX-MIC | RX Mic |
11572 * |--------------|----------|----------|
11573 * <---16bytes---><--8bytes--><--8bytes-->
11574 *
11575 * Sme expects the 32 bytes key to be in the below order
11576 *
11577 * |--------------|----------|----------|
11578 * | Tk1 |RX-MIC | TX Mic |
11579 * |--------------|----------|----------|
11580 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011581 */
11582 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011583 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584
11585 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011586 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587
11588 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011589 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590
11591 break;
11592 }
11593
11594 case WLAN_CIPHER_SUITE_CCMP:
11595 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11596 break;
11597
11598#ifdef FEATURE_WLAN_WAPI
11599 case WLAN_CIPHER_SUITE_SMS4:
11600 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011601 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011602 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11603 mac_addr, params->key,
11604 params->key_len);
11605 return 0;
11606 }
11607#endif
11608
11609#ifdef FEATURE_WLAN_ESE
11610 case WLAN_CIPHER_SUITE_KRK:
11611 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11612 break;
11613#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11614 case WLAN_CIPHER_SUITE_BTK:
11615 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11616 break;
11617#endif
11618#endif
11619
11620#ifdef WLAN_FEATURE_11W
11621 case WLAN_CIPHER_SUITE_AES_CMAC:
11622 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11623 break;
11624#endif
11625
11626 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011627 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 return -EOPNOTSUPP;
11629 }
11630
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011631 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632
11633 if (!pairwise) {
11634 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011635 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011637 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638 } else {
11639 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011642 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011644 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 /* if a key is already installed, block all subsequent ones */
11646 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011647 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011648 return 0;
11649 }
11650
11651 setKey.keyDirection = eSIR_TX_RX;
11652 /*Set the group key */
11653 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11654 pAdapter->sessionId, &setKey, &roamId);
11655
11656 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011657 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658 return -EINVAL;
11659 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011660 /* Save the keys here and call sme_roam_set_key for setting
11661 * the PTK after peer joins the IBSS network
11662 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011663 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 &setKey, sizeof(tCsrRoamSetKey));
11665
11666 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11667 return status;
11668 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011669 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11670 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11672 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011673 status = wlansap_set_key_sta(
11674 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011675 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011676 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 __LINE__, status);
11678 }
11679 }
11680
11681 /* Save the key in ap ctx for use on START_BASS and restart */
11682 if (pairwise ||
11683 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11684 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011685 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 sizeof(tCsrRoamSetKey));
11687 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011688 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011689 sizeof(tCsrRoamSetKey));
11690
Krunal Sonib4326f22016-03-10 13:05:51 -080011691 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11692 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 hdd_wext_state_t *pWextState =
11694 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11695 hdd_station_ctx_t *pHddStaCtx =
11696 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11697
11698 if (!pairwise) {
11699 /* set group key */
11700 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011701 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702 __func__, __LINE__);
11703 hdd_perform_roam_set_key_complete(pAdapter);
11704 }
11705 }
11706
11707 pWextState->roamProfile.Keys.KeyLength[key_index] =
11708 (u8) params->key_len;
11709
11710 pWextState->roamProfile.Keys.defaultIndex = key_index;
11711
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011712 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 KeyMaterial[key_index][0], params->key,
11714 params->key_len);
11715
11716 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11717
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011718 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11720 setKey.keyDirection);
11721
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011722 /* The supplicant may attempt to set the PTK once
11723 * pre-authentication is done. Save the key in the
11724 * UMAC and include it in the ADD BSS request
11725 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011726 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011727 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011728 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011729 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011730 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011731 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011732 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011733 return -EINVAL;
11734 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011735
11736 /* issue set key request to SME */
11737 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11738 pAdapter->sessionId, &setKey, &roamId);
11739
11740 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011741 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742 pHddStaCtx->roam_info.roamingState =
11743 HDD_ROAM_STATE_NONE;
11744 return -EINVAL;
11745 }
11746
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011747 /* in case of IBSS as there was no information
11748 * available about WEP keys during IBSS join, group
11749 * key intialized with NULL key, so re-initialize
11750 * group key with correct value
11751 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 if ((eCSR_BSS_TYPE_START_IBSS ==
11753 pWextState->roamProfile.BSSType)
11754 &&
11755 !((IW_AUTH_KEY_MGMT_802_1X ==
11756 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11757 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11758 pHddStaCtx->conn_info.authType)
11759 )
11760 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11761 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11762 )
11763 ) {
11764 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011765 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011767 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11769 setKey.keyDirection);
11770
11771 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11772 pAdapter->sessionId, &setKey,
11773 &roamId);
11774
11775 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011776 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011777 pHddStaCtx->roam_info.roamingState =
11778 HDD_ROAM_STATE_NONE;
11779 return -EINVAL;
11780 }
11781 }
11782 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011783 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 return 0;
11785}
11786
11787static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11788 struct net_device *ndev,
11789 u8 key_index, bool pairwise,
11790 const u8 *mac_addr,
11791 struct key_params *params)
11792{
11793 int ret;
11794 cds_ssr_protect(__func__);
11795 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11796 mac_addr, params);
11797 cds_ssr_unprotect(__func__);
11798
11799 return ret;
11800}
11801
11802/*
11803 * FUNCTION: __wlan_hdd_cfg80211_get_key
11804 * This function is used to get the key information
11805 */
11806static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11807 struct net_device *ndev,
11808 u8 key_index, bool pairwise,
11809 const u8 *mac_addr, void *cookie,
11810 void (*callback)(void *cookie,
11811 struct key_params *)
11812 )
11813{
11814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11815 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11816 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11817 struct key_params params;
11818
11819 ENTER();
11820
Anurag Chouhan6d760662016-02-20 16:05:43 +053011821 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011822 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 return -EINVAL;
11824 }
11825
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011826 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011827 hdd_device_mode_to_string(pAdapter->device_mode),
11828 pAdapter->device_mode);
11829
11830 memset(&params, 0, sizeof(params));
11831
11832 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011833 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 key_index);
11835 return -EINVAL;
11836 }
11837
11838 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11839 case eCSR_ENCRYPT_TYPE_NONE:
11840 params.cipher = IW_AUTH_CIPHER_NONE;
11841 break;
11842
11843 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11844 case eCSR_ENCRYPT_TYPE_WEP40:
11845 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11846 break;
11847
11848 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11849 case eCSR_ENCRYPT_TYPE_WEP104:
11850 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11851 break;
11852
11853 case eCSR_ENCRYPT_TYPE_TKIP:
11854 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11855 break;
11856
11857 case eCSR_ENCRYPT_TYPE_AES:
11858 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11859 break;
11860
11861 default:
11862 params.cipher = IW_AUTH_CIPHER_NONE;
11863 break;
11864 }
11865
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011866 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011867 TRACE_CODE_HDD_CFG80211_GET_KEY,
11868 pAdapter->sessionId, params.cipher));
11869
11870 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11871 params.seq_len = 0;
11872 params.seq = NULL;
11873 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11874 callback(cookie, &params);
11875
11876 EXIT();
11877 return 0;
11878}
11879
11880static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11881 struct net_device *ndev,
11882 u8 key_index, bool pairwise,
11883 const u8 *mac_addr, void *cookie,
11884 void (*callback)(void *cookie,
11885 struct key_params *)
11886 )
11887{
11888 int ret;
11889
11890 cds_ssr_protect(__func__);
11891 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11892 mac_addr, cookie, callback);
11893 cds_ssr_unprotect(__func__);
11894
11895 return ret;
11896}
11897
11898/**
11899 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11900 * @wiphy: wiphy interface context
11901 * @ndev: pointer to net device
11902 * @key_index: Key index used in 802.11 frames
11903 * @unicast: true if it is unicast key
11904 * @multicast: true if it is multicast key
11905 *
11906 * This function is required for cfg80211_ops API.
11907 * It is used to delete the key information
11908 * Underlying hardware implementation does not have API to delete the
11909 * encryption key. It is automatically deleted when the peer is
11910 * removed. Hence this function currently does nothing.
11911 * Future implementation may interprete delete key operation to
11912 * replacing the key with a random junk value, effectively making it
11913 * useless.
11914 *
11915 * Return: status code, always 0.
11916 */
11917
11918static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11919 struct net_device *ndev,
11920 u8 key_index,
11921 bool pairwise, const u8 *mac_addr)
11922{
11923 EXIT();
11924 return 0;
11925}
11926
11927/**
11928 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11929 * @wiphy: Pointer to wiphy structure.
11930 * @dev: Pointer to net_device structure.
11931 * @key_index: key index
11932 * @pairwise: pairwise
11933 * @mac_addr: mac address
11934 *
11935 * This is the cfg80211 delete key handler function which invokes
11936 * the internal function @__wlan_hdd_cfg80211_del_key with
11937 * SSR protection.
11938 *
11939 * Return: 0 for success, error number on failure.
11940 */
11941static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11942 struct net_device *dev,
11943 u8 key_index,
11944 bool pairwise, const u8 *mac_addr)
11945{
11946 int ret;
11947
11948 cds_ssr_protect(__func__);
11949 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11950 pairwise, mac_addr);
11951 cds_ssr_unprotect(__func__);
11952
11953 return ret;
11954}
11955
11956/*
11957 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11958 * This function is used to set the default tx key index
11959 */
11960static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11961 struct net_device *ndev,
11962 u8 key_index,
11963 bool unicast, bool multicast)
11964{
11965 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11966 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11967 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11968 hdd_context_t *pHddCtx;
11969 int status;
11970
11971 ENTER();
11972
Anurag Chouhan6d760662016-02-20 16:05:43 +053011973 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011974 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011975 return -EINVAL;
11976 }
11977
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011978 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11979 hdd_err("invalid session id: %d", pAdapter->sessionId);
11980 return -EINVAL;
11981 }
11982
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011983 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
11985 pAdapter->sessionId, key_index));
11986
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011987 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011988 hdd_device_mode_to_string(pAdapter->device_mode),
11989 pAdapter->device_mode, key_index);
11990
11991 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011992 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993 return -EINVAL;
11994 }
11995
11996 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11997 status = wlan_hdd_validate_context(pHddCtx);
11998
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011999 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012001
Krunal Sonib4326f22016-03-10 13:05:51 -080012002 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12003 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012004 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12005 pHddStaCtx->conn_info.ucEncryptionType) &&
12006 (eCSR_ENCRYPT_TYPE_AES !=
12007 pHddStaCtx->conn_info.ucEncryptionType)) {
12008 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012009 * then update the default key index
12010 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012011
12012 tCsrRoamSetKey setKey;
12013 uint32_t roamId = 0xFF;
12014 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12015
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012016 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012017
12018 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012019 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012020 setKey.keyId = key_index;
12021 setKey.keyLength = Keys->KeyLength[key_index];
12022
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012023 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012024 &Keys->KeyMaterial[key_index][0],
12025 Keys->KeyLength[key_index]);
12026
12027 setKey.keyDirection = eSIR_TX_RX;
12028
Anurag Chouhanc5548422016-02-24 18:33:27 +053012029 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 &pHddStaCtx->conn_info.bssId);
12031
12032 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12033 pWextState->roamProfile.EncryptionType.
12034 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012035 /* In the case of dynamic wep
12036 * supplicant hardcodes DWEP type to
12037 * eCSR_ENCRYPT_TYPE_WEP104 even
12038 * though ap is configured for WEP-40
12039 * encryption. In this canse the key
12040 * length is 5 but the encryption type
12041 * is 104 hence checking the key
12042 * lenght(5) and encryption type(104)
12043 * and switching encryption type to 40
12044 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 pWextState->roamProfile.EncryptionType.
12046 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12047 pWextState->roamProfile.mcEncryptionType.
12048 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12049 }
12050
12051 setKey.encType =
12052 pWextState->roamProfile.EncryptionType.
12053 encryptionType[0];
12054
12055 /* Issue set key request */
12056 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12057 pAdapter->sessionId, &setKey,
12058 &roamId);
12059
12060 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012061 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 status);
12063 return -EINVAL;
12064 }
12065 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012066 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012067 /* In SoftAp mode setting key direction for default mode */
12068 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12069 pWextState->roamProfile.EncryptionType.encryptionType[0])
12070 && (eCSR_ENCRYPT_TYPE_AES !=
12071 pWextState->roamProfile.EncryptionType.
12072 encryptionType[0])) {
12073 /* Saving key direction for default key index to TX default */
12074 hdd_ap_ctx_t *pAPCtx =
12075 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12076 pAPCtx->wepKey[key_index].keyDirection =
12077 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012078 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012079 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012080 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 }
12082 }
12083
12084 EXIT();
12085 return status;
12086}
12087
12088static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12089 struct net_device *ndev,
12090 u8 key_index,
12091 bool unicast, bool multicast)
12092{
12093 int ret;
12094 cds_ssr_protect(__func__);
12095 ret =
12096 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12097 multicast);
12098 cds_ssr_unprotect(__func__);
12099
12100 return ret;
12101}
12102
Abhishek Singhc9941602016-08-09 16:06:22 +053012103/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012104 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12105 * interface that BSS might have been lost.
12106 * @pAdapter: adaptor
12107 * @bssid: bssid which might have been lost
12108 *
12109 * Return: bss which is unlinked from kernel cache
12110 */
12111struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12112 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113{
12114 struct net_device *dev = pAdapter->dev;
12115 struct wireless_dev *wdev = dev->ieee80211_ptr;
12116 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 struct cfg80211_bss *bss = NULL;
12118
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012119 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012120 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012122 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012124 hdd_info("cfg80211_unlink_bss called for BSSID "
12125 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 cfg80211_unlink_bss(wiphy, bss);
12127 }
12128 return bss;
12129}
12130
Abhishek Singhc9941602016-08-09 16:06:22 +053012131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132/**
12133 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12134 * @pAdapter: Pointer to adapter
12135 * @bss_desc: Pointer to bss descriptor
12136 *
12137 * This function is used to inform the BSS details to nl80211 interface.
12138 *
12139 * Return: struct cfg80211_bss pointer
12140 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012141struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12142 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143{
12144 /*
12145 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12146 * already exists in bss data base of cfg80211 for that particular BSS
12147 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12148 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12149 * As of now there is no possibility to get the mgmt(probe response)
12150 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12151 * and passing to cfg80211_inform_bss_frame.
12152 */
12153 struct net_device *dev = pAdapter->dev;
12154 struct wireless_dev *wdev = dev->ieee80211_ptr;
12155 struct wiphy *wiphy = wdev->wiphy;
12156 int chan_no = bss_desc->channelId;
12157#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12158 qcom_ie_age *qie_age = NULL;
12159 int ie_length =
12160 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12161#else
12162 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12163#endif
12164 const char *ie =
12165 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12166 unsigned int freq;
12167 struct ieee80211_channel *chan;
12168 struct ieee80211_mgmt *mgmt = NULL;
12169 struct cfg80211_bss *bss_status = NULL;
12170 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12171 int rssi = 0;
12172 hdd_context_t *pHddCtx;
12173 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012175 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012176
12177 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12178 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012179 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012182 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012183 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012184 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012185 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012186 return NULL;
12187 }
12188
12189 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012192 * Instead it wants a monotonic increasing value
12193 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012194 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012195 mgmt->u.probe_resp.timestamp =
12196 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012197
12198 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12199 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12200
12201#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12202 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12203 /* Assuming this is the last IE, copy at the end */
12204 ie_length -= sizeof(qcom_ie_age);
12205 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12206 qie_age->element_id = QCOM_VENDOR_IE_ID;
12207 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12208 qie_age->oui_1 = QCOM_OUI1;
12209 qie_age->oui_2 = QCOM_OUI2;
12210 qie_age->oui_3 = QCOM_OUI3;
12211 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012212 /*
12213 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12214 * all bss related timestamp is in units of ms. Due to this when scan
12215 * results are sent to lowi the scan age is high.To address this,
12216 * send age in units of 1/10 ms.
12217 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012218 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012219 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012221 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12222 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012223 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12224 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012225#endif
12226
12227 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12228 if (bss_desc->fProbeRsp) {
12229 mgmt->frame_control |=
12230 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12231 } else {
12232 mgmt->frame_control |=
12233 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12234 }
12235
12236 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012237 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 freq =
12239 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012240 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012241 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012242 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012243 freq =
12244 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012245 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012247 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012248 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 return NULL;
12250 }
12251
12252 chan = __ieee80211_get_channel(wiphy, freq);
12253 /* When the band is changed on the fly using the GUI, three things are done
12254 * 1. scan abort
12255 * 2. flush scan results from cache
12256 * 3. update the band with the new band user specified (refer to the
12257 * hdd_set_band_helper function) as part of the scan abort, message will be
12258 * queued to PE and we proceed with flushing and changinh the band.
12259 * PE will stop the scanning further and report back the results what ever
12260 * it had till now by calling the call back function.
12261 * if the time between update band and scandone call back is sufficient
12262 * enough the band change reflects in SME, SME validates the channels
12263 * and discards the channels correponding to previous band and calls back
12264 * with zero bss results. but if the time between band update and scan done
12265 * callback is very small then band change will not reflect in SME and SME
12266 * reports to HDD all the channels correponding to previous band.this is due
12267 * to race condition.but those channels are invalid to the new band and so
12268 * this function __ieee80211_get_channel will return NULL.Each time we
12269 * report scan result with this pointer null warning kernel trace is printed.
12270 * if the scan results contain large number of APs continuosly kernel
12271 * warning trace is printed and it will lead to apps watch dog bark.
12272 * So drop the bss and continue to next bss.
12273 */
12274 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012275 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12276 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012277 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 return NULL;
12279 }
12280
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012281 /* Based on .ini configuration, raw rssi can be reported for bss.
12282 * Raw rssi is typically used for estimating power.
12283 */
12284
12285 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12286 bss_desc->rssi;
12287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012289 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012291 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012292 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012293 (int)(rssi / 100),
12294 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295
12296 bss_status =
12297 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
12298 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012299 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012300 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301 return bss_status;
12302}
12303
12304/**
12305 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12306 * @pAdapter: Pointer to adapter
12307 * @pRoamInfo: Pointer to roam info
12308 *
12309 * This function is used to update the BSS data base of CFG8011
12310 *
12311 * Return: struct cfg80211_bss pointer
12312 */
12313struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12314 tCsrRoamInfo *pRoamInfo)
12315{
12316 tCsrRoamConnectedProfile roamProfile;
12317 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12318 struct cfg80211_bss *bss = NULL;
12319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12321 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12322
12323 if (NULL != roamProfile.pBssDesc) {
12324 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12325 roamProfile.pBssDesc);
12326
12327 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012328 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012330 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012332 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 return bss;
12335}
12336/**
12337 * wlan_hdd_cfg80211_update_bss() - update bss
12338 * @wiphy: Pointer to wiphy
12339 * @pAdapter: Pointer to adapter
12340 * @scan_time: scan request timestamp
12341 *
12342 * Return: zero if success, non-zero otherwise
12343 */
12344int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12345 hdd_adapter_t *pAdapter,
12346 uint32_t scan_time)
12347{
12348 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12349 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012350 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012351 tScanResultHandle pResult;
12352 struct cfg80211_bss *bss_status = NULL;
12353 hdd_context_t *pHddCtx;
12354 int ret;
12355
12356 ENTER();
12357
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012358 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12359 hdd_err("invalid session id: %d", pAdapter->sessionId);
12360 return -EINVAL;
12361 }
12362
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012363 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012364 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12365 NO_SESSION, pAdapter->sessionId));
12366
12367 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12368 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012369 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012370 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371
12372 /* start getting scan results and populate cgf80211 BSS database */
12373 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12374
12375 /* no scan results */
12376 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012377 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012378 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 }
12380
12381 pScanResult = sme_scan_result_get_first(hHal, pResult);
12382
12383 while (pScanResult) {
12384 /*
12385 * - cfg80211_inform_bss() is not updating ie field of bss
12386 * entry if entry already exists in bss data base of cfg80211
12387 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12388 * to update thebss entry instead of cfg80211_inform_bss,
12389 * But this call expects mgmt packet as input. As of now
12390 * there is no possibility to get the mgmt(probe response)
12391 * frame from PE, converting bss_desc to
12392 * ieee80211_mgmt(probe response) and passing to c
12393 * fg80211_inform_bss_frame.
12394 * - Update BSS only if beacon timestamp is later than
12395 * scan request timestamp.
12396 */
12397 if ((scan_time == 0) ||
12398 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012399 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 bss_status =
12401 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12402 &pScanResult->BssDescriptor);
12403
12404 if (NULL == bss_status) {
12405 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12406 } else {
12407 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012409 bss_status);
12410 }
12411 } else {
12412 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12413 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12414 }
12415 pScanResult = sme_scan_result_get_next(hHal, pResult);
12416 }
12417
12418 sme_scan_result_purge(hHal, pResult);
12419 /*
12420 * For SAP mode, scan is invoked by hostapd during SAP start
12421 * if hostapd is restarted, we need to flush previous scan
12422 * result so that it will reflect environment change
12423 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012424 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12426 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12427#endif
12428 )
12429 sme_scan_flush_result(hHal);
12430
12431 EXIT();
12432 return 0;
12433}
12434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435/**
12436 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12437 * @pAdapter: Pointer to adapter
12438 * @pRoamInfo: Pointer to roam info
12439 * @index: Index
12440 * @preauth: Preauth flag
12441 *
12442 * This function is used to notify the supplicant of a new PMKSA candidate.
12443 *
12444 * Return: 0 for success, non-zero for failure
12445 */
12446int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12447 tCsrRoamInfo *pRoamInfo,
12448 int index, bool preauth)
12449{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012450 struct net_device *dev = pAdapter->dev;
12451 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12452
12453 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012454 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455
12456 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012457 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 return -EINVAL;
12459 }
12460
12461 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012462 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12464 cfg80211_pmksa_candidate_notify(dev, index,
12465 pRoamInfo->bssid.bytes,
12466 preauth, GFP_KERNEL);
12467 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012468 return 0;
12469}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012470
12471#ifdef FEATURE_WLAN_LFR_METRICS
12472/**
12473 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12474 * @pAdapter: Pointer to adapter
12475 * @pRoamInfo: Pointer to roam info
12476 *
12477 * 802.11r/LFR metrics reporting function to report preauth initiation
12478 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012479 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 */
12481#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012482QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012483 tCsrRoamInfo *pRoamInfo)
12484{
12485 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12486 union iwreq_data wrqu;
12487
12488 ENTER();
12489
12490 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012491 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012492 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012493 }
12494
12495 /* create the event */
12496 memset(&wrqu, 0, sizeof(wrqu));
12497 memset(metrics_notification, 0, sizeof(metrics_notification));
12498
12499 wrqu.data.pointer = metrics_notification;
12500 wrqu.data.length = scnprintf(metrics_notification,
12501 sizeof(metrics_notification),
12502 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12503 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12504
12505 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12506 metrics_notification);
12507
12508 EXIT();
12509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012510 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511}
12512
12513/**
12514 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12515 * @pAdapter: Pointer to adapter
12516 * @pRoamInfo: Pointer to roam info
12517 * @preauth_status: Preauth status
12518 *
12519 * 802.11r/LFR metrics reporting function to report handover initiation
12520 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012521 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012523QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12525 tCsrRoamInfo *pRoamInfo,
12526 bool preauth_status)
12527{
12528 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12529 union iwreq_data wrqu;
12530
12531 ENTER();
12532
12533 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012534 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012535 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536 }
12537
12538 /* create the event */
12539 memset(&wrqu, 0, sizeof(wrqu));
12540 memset(metrics_notification, 0, sizeof(metrics_notification));
12541
12542 scnprintf(metrics_notification, sizeof(metrics_notification),
12543 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12544 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12545
12546 if (1 == preauth_status)
12547 strlcat(metrics_notification, " true",
12548 sizeof(metrics_notification));
12549 else
12550 strlcat(metrics_notification, " false",
12551 sizeof(metrics_notification));
12552
12553 wrqu.data.pointer = metrics_notification;
12554 wrqu.data.length = strlen(metrics_notification);
12555
12556 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12557 metrics_notification);
12558
12559 EXIT();
12560
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012561 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562}
12563
12564/**
12565 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12566 * @pAdapter: Pointer to adapter
12567 * @pRoamInfo: Pointer to roam info
12568 *
12569 * 802.11r/LFR metrics reporting function to report handover initiation
12570 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012571 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012573QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 tCsrRoamInfo *pRoamInfo)
12575{
12576 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12577 union iwreq_data wrqu;
12578
12579 ENTER();
12580
12581 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012582 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012583 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584 }
12585
12586 /* create the event */
12587 memset(&wrqu, 0, sizeof(wrqu));
12588 memset(metrics_notification, 0, sizeof(metrics_notification));
12589
12590 wrqu.data.pointer = metrics_notification;
12591 wrqu.data.length = scnprintf(metrics_notification,
12592 sizeof(metrics_notification),
12593 "QCOM: LFR_PREAUTH_HANDOVER "
12594 MAC_ADDRESS_STR,
12595 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12596
12597 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12598 metrics_notification);
12599
12600 EXIT();
12601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012602 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012603}
12604#endif
12605
12606/**
12607 * hdd_select_cbmode() - select channel bonding mode
12608 * @pAdapter: Pointer to adapter
12609 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012610 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 *
12612 * Return: none
12613 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012614void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12615 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012616{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012617 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012618 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012619 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012620
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012621 /*
12622 * CDS api expects secondary channel for calculating
12623 * the channel params
12624 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012625 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012626 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12627 if (operationChannel >= 1 && operationChannel <= 5)
12628 sec_ch = operationChannel + 4;
12629 else if (operationChannel >= 6 && operationChannel <= 13)
12630 sec_ch = operationChannel - 4;
12631 }
12632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012634 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012635
12636 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012637 eHddDot11Mode hdd_dot11_mode;
12638 uint8_t iniDot11Mode =
12639 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12640
12641 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12642 switch (iniDot11Mode) {
12643 case eHDD_DOT11_MODE_AUTO:
12644 case eHDD_DOT11_MODE_11ac:
12645 case eHDD_DOT11_MODE_11ac_ONLY:
12646 if (sme_is_feature_supported_by_fw(DOT11AC))
12647 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12648 else
12649 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12650 break;
12651 case eHDD_DOT11_MODE_11n:
12652 case eHDD_DOT11_MODE_11n_ONLY:
12653 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12654 break;
12655 default:
12656 hdd_dot11_mode = iniDot11Mode;
12657 break;
12658 }
12659 ch_info->channel_width = ch_params->ch_width;
12660 ch_info->phy_mode =
12661 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012662 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012663 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012664 hdd_info("ch_info width %d, phymode %d channel %d",
12665 ch_info->channel_width, ch_info->phy_mode,
12666 ch_info->channel);
12667 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012668}
12669
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012670/**
12671 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12672 * @adapter: STA adapter
12673 * @roam_profile: STA roam profile
12674 *
12675 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12676 *
12677 * Return: false if sta-sap conc is not allowed, else return true
12678 */
12679static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12680 tCsrRoamProfile *roam_profile)
12681{
12682 hdd_context_t *hdd_ctx;
12683 hdd_adapter_t *ap_adapter;
12684 hdd_ap_ctx_t *hdd_ap_ctx;
12685 hdd_hostapd_state_t *hostapd_state;
12686 uint8_t channel = 0;
12687 QDF_STATUS status;
12688
12689 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12690 if (!hdd_ctx) {
12691 hdd_err("HDD context is NULL");
12692 return true;
12693 }
12694
12695 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12696 /* probably no sap running, no handling required */
12697 if (ap_adapter == NULL)
12698 return true;
12699
12700 /*
12701 * sap is not in started state, so it is fine to go ahead with sta.
12702 * if sap is currently doing CAC then don't allow sta to go further.
12703 */
12704 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12705 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12706 return true;
12707
12708 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12709 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12710 return false;
12711 }
12712
12713 /*
12714 * log and return error, if we allow STA to go through, we don't
12715 * know what is going to happen better stop sta connection
12716 */
12717 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12718 if (NULL == hdd_ap_ctx) {
12719 hdd_err("AP context not found");
12720 return false;
12721 }
12722
12723 /* sap is on non-dfs channel, nothing to handle */
12724 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12725 hdd_info("sap is on non-dfs channel, sta is allowed");
12726 return true;
12727 }
12728 /*
12729 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012730 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012731 */
12732 status = cds_get_channel_from_scan_result(adapter,
12733 roam_profile, &channel);
12734
Nitesh Shah59774522016-09-16 15:14:21 +053012735 /*
12736 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12737 * channels for roaming case.
12738 */
12739 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12740 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12741 return true;
12742 }
12743
12744 /*
12745 * If channel is 0 or DFS then better to call pcl and find out the
12746 * best channel. If channel is non-dfs 5 GHz then better move SAP
12747 * to STA's channel to make scc, so we have room for 3port MCC
12748 * scenario.
12749 */
12750 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012751 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12752 true);
12753
12754 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12755 qdf_event_reset(&hostapd_state->qdf_event);
12756 status = wlansap_set_channel_change_with_csa(
12757 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12758 hdd_ap_ctx->sapConfig.ch_width_orig);
12759
12760 if (QDF_STATUS_SUCCESS != status) {
12761 hdd_err("Set channel with CSA IE failed, can't allow STA");
12762 return false;
12763 }
12764
12765 /*
12766 * wait here for SAP to finish the channel switch. When channel
12767 * switch happens, SAP sends few beacons with CSA_IE. After
12768 * successfully Transmission of those beacons, it will move its
12769 * state from started to disconnected and move to new channel.
12770 * once it moves to new channel, sap again moves its state
12771 * machine from disconnected to started and set this event.
12772 * wait for 10 secs to finish this.
12773 */
12774 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12775 if (!QDF_IS_STATUS_SUCCESS(status)) {
12776 hdd_err("wait for qdf_event failed, STA not allowed!!");
12777 return false;
12778 }
12779
12780 return true;
12781}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782
Krunal Soni31949422016-07-29 17:17:53 -070012783/**
12784 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012786 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012787 * @ssid_len: Length of ssid
12788 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012789 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012790 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012791 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012792 *
12793 * This function is used to start the association process
12794 *
12795 * Return: 0 for success, non-zero for failure
12796 */
Krunal Soni31949422016-07-29 17:17:53 -070012797static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012798 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012799 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012800 u8 operatingChannel,
12801 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802{
12803 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012804 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012805 hdd_wext_state_t *pWextState;
12806 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012807 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012808 uint32_t roamId;
12809 tCsrRoamProfile *pRoamProfile;
12810 eCsrAuthType RSNAuthType;
12811 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012812 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012813
12814 ENTER();
12815
12816 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12817 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012818 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012819
12820 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012821 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012822 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823
12824 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012825 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012826 status = -EINVAL;
12827 goto ret_status;
12828 }
12829
12830 if (true == cds_is_connection_in_progress()) {
12831 hdd_err("Connection refused: conn in progress");
12832 status = -EINVAL;
12833 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 }
12835
12836 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012837 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12838 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839
12840 if (pRoamProfile) {
12841 hdd_station_ctx_t *pHddStaCtx;
12842 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12843
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012844 /* Restart the opportunistic timer
12845 *
12846 * If hw_mode_change_in_progress is true, then wait
12847 * till firmware sends the callback for hw_mode change.
12848 *
12849 * Else set connect_in_progress as true and proceed.
12850 */
12851 cds_restart_opportunistic_timer(false);
12852 if (cds_is_hw_mode_change_in_progress()) {
12853 status = qdf_wait_for_connection_update();
12854 if (!QDF_IS_STATUS_SUCCESS(status)) {
12855 hdd_err("qdf wait for event failed!!");
12856 status = -EINVAL;
12857 goto ret_status;
12858 }
12859 }
12860 cds_set_connection_in_progress(true);
12861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012862 if (HDD_WMM_USER_MODE_NO_QOS ==
12863 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12864 /*QoS not enabled in cfg file */
12865 pRoamProfile->uapsd_mask = 0;
12866 } else {
12867 /*QoS enabled, update uapsd mask from cfg file */
12868 pRoamProfile->uapsd_mask =
12869 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12870 }
12871
12872 pRoamProfile->SSIDs.numOfSSIDs = 1;
12873 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012874 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012875 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012876 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877 ssid, ssid_len);
12878
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012879 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012880 /* cleanup bssid hint */
12881 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12882 QDF_MAC_ADDR_SIZE);
12883 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12884 QDF_MAC_ADDR_SIZE);
12885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012886 if (bssid) {
12887 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012888 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012889 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012890 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012891 /*
12892 * Save BSSID in seperate variable as
12893 * pRoamProfile's BSSID is getting zeroed out in the
12894 * association process. In case of join failure
12895 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012896 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012897 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012898 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012899 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012901 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12902 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012903 /*
12904 * Save BSSID in a separate variable as
12905 * pRoamProfile's BSSID is getting zeroed out in the
12906 * association process. In case of join failure
12907 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012909 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012910 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012911 hdd_info("bssid_hint is given by upper layer %pM",
12912 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012913 }
12914
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012915 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916 pRoamProfile->SSIDs.SSIDList->SSID.length,
12917 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12918 operatingChannel);
12919
12920 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12921 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012922 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12924 }
12925#ifdef FEATURE_WLAN_WAPI
12926 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012927 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012928 switch (pAdapter->wapi_info.wapiAuthMode) {
12929 case WAPI_AUTH_MODE_PSK:
12930 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012931 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012932 pAdapter->wapi_info.wapiAuthMode);
12933 pRoamProfile->AuthType.authType[0] =
12934 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12935 break;
12936 }
12937 case WAPI_AUTH_MODE_CERT:
12938 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012939 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012940 pAdapter->wapi_info.wapiAuthMode);
12941 pRoamProfile->AuthType.authType[0] =
12942 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12943 break;
12944 }
12945 } /* End of switch */
12946 if (pAdapter->wapi_info.wapiAuthMode ==
12947 WAPI_AUTH_MODE_PSK
12948 || pAdapter->wapi_info.wapiAuthMode ==
12949 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012950 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012951 pRoamProfile->AuthType.numEntries = 1;
12952 pRoamProfile->EncryptionType.numEntries = 1;
12953 pRoamProfile->EncryptionType.encryptionType[0] =
12954 eCSR_ENCRYPT_TYPE_WPI;
12955 pRoamProfile->mcEncryptionType.numEntries = 1;
12956 pRoamProfile->mcEncryptionType.
12957 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12958 }
12959 }
Krunal Soni31949422016-07-29 17:17:53 -070012960#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961#ifdef WLAN_FEATURE_GTK_OFFLOAD
12962 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080012963 if ((QDF_STA_MODE == pAdapter->device_mode) ||
12964 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
12966 sizeof(tSirGtkOffloadParams));
12967 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12968 GTK_OFFLOAD_DISABLE;
12969 }
12970#endif
12971 pRoamProfile->csrPersona = pAdapter->device_mode;
12972
12973 if (operatingChannel) {
12974 pRoamProfile->ChannelInfo.ChannelList =
12975 &operatingChannel;
12976 pRoamProfile->ChannelInfo.numOfChannels = 1;
12977 } else {
12978 pRoamProfile->ChannelInfo.ChannelList = NULL;
12979 pRoamProfile->ChannelInfo.numOfChannels = 0;
12980 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012981 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 && operatingChannel) {
12983 /*
12984 * Need to post the IBSS power save parameters
12985 * to WMA. WMA will configure this parameters
12986 * to firmware if power save is enabled by the
12987 * firmware.
12988 */
12989 status = hdd_set_ibss_power_save_params(pAdapter);
12990
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012991 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012992 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012993 status = -EINVAL;
12994 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012996 pRoamProfile->ch_params.ch_width =
12997 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053012998 /*
12999 * In IBSS mode while operating in 2.4 GHz,
13000 * the device supports only 20 MHz.
13001 */
13002 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13003 pRoamProfile->ch_params.ch_width =
13004 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013005 hdd_select_cbmode(pAdapter, operatingChannel,
13006 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013007 }
Abhishek Singh99bce862016-06-20 15:10:51 +053013008 /*
13009 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13010 * or pmf=2 is an explicit configuration in the supplicant
13011 * configuration, drop the connection request.
13012 */
13013 if (pWextState->roamProfile.MFPEnabled &&
13014 !(pWextState->roamProfile.MFPRequired ||
13015 pWextState->roamProfile.MFPCapable)) {
13016 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13017 pWextState->roamProfile.MFPEnabled,
13018 pWextState->roamProfile.MFPRequired,
13019 pWextState->roamProfile.MFPCapable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013020
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013021 status = -EINVAL;
13022 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023 }
13024
Krunal Soni31949422016-07-29 17:17:53 -070013025 /*
13026 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013028 * enhancements, the supplicant is not issuing the scan command
13029 * now. So the unicast frames which are sent from the host are
13030 * not having the additional IEs. If it is P2P CLIENT and there
13031 * is no additional IE present in roamProfile, then use the
13032 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013033 */
13034
Krunal Sonib4326f22016-03-10 13:05:51 -080013035 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013036 (!pRoamProfile->pAddIEScan)) {
13037 pRoamProfile->pAddIEScan =
13038 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13039 pRoamProfile->nAddIEScanLength =
13040 pAdapter->scan_info.scanAddIE.length;
13041 }
13042 /*
13043 * When policy manager is enabled from ini file, we shouldn't
13044 * check for other concurrency rules.
13045 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013046 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013047 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013048 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013049 pAdapter, pRoamProfile, &roamId)) {
13050 status = 0;
13051 goto conn_failure;
13052 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 }
13054
Krunal Soni3091bcc2016-06-23 12:28:21 -070013055 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013056 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13057 pRoamProfile))) {
13058 hdd_err("sap-sta conc will fail, can't allow sta");
13059 hdd_conn_set_connection_state(pAdapter,
13060 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013061 status = -ENOMEM;
13062 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013063 }
13064
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013065 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066 if (!sme_config) {
13067 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013068 hdd_conn_set_connection_state(pAdapter,
13069 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013070 status = -ENOMEM;
13071 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013072 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073 sme_get_config_param(pHddCtx->hHal, sme_config);
13074 /* These values are not sessionized. So, any change in these SME
13075 * configs on an older or parallel interface will affect the
13076 * cb mode. So, restoring the default INI params before starting
13077 * interfaces such as sta, cli etc.,
13078 */
13079 sme_config->csrConfig.channelBondingMode5GHz =
13080 pHddCtx->config->nChannelBondingMode5GHz;
13081 sme_config->csrConfig.channelBondingMode24GHz =
13082 pHddCtx->config->nChannelBondingMode24GHz;
13083 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013084 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013085 /*
13086 * Change conn_state to connecting before sme_roam_connect(),
13087 * because sme_roam_connect() has a direct path to call
13088 * hdd_sme_roam_callback(), which will change the conn_state
13089 * If direct path, conn_state will be accordingly changed to
13090 * NotConnected or Associated by either
13091 * hdd_association_completion_handler() or
13092 * hdd_dis_connect_handler() in sme_RoamCallback()if
13093 * sme_RomConnect is to be queued,
13094 * Connecting state will remain until it is completed.
13095 *
13096 * If connection state is not changed, connection state will
13097 * remain in eConnectionState_NotConnected state.
13098 * In hdd_association_completion_handler, "hddDisconInProgress"
13099 * is set to true if conn state is
13100 * eConnectionState_NotConnected.
13101 * If "hddDisconInProgress" is set to true then cfg80211 layer
13102 * is not informed of connect result indication which
13103 * is an issue.
13104 */
13105 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013106 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013107 hdd_conn_set_connection_state(pAdapter,
13108 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109
Komal Seelama89be8d2016-09-29 11:09:26 +053013110 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13111 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013112 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 pAdapter->sessionId, pRoamProfile,
13114 &roamId);
13115
Rajeev Kumard31e1542017-01-13 14:37:42 -080013116 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013117 (QDF_STA_MODE == pAdapter->device_mode ||
13118 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013119 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013120 "qdf_status %d. -> NotConnected",
13121 pAdapter->sessionId, qdf_status);
13122 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 /* change back to NotAssociated */
13124 hdd_conn_set_connection_state(pAdapter,
13125 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013126 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13127 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013128 }
13129
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013130 /* Reset connect_in_progress */
13131 cds_set_connection_in_progress(false);
13132
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013133 pRoamProfile->ChannelInfo.ChannelList = NULL;
13134 pRoamProfile->ChannelInfo.numOfChannels = 0;
13135
Nitesh Shah044fd672016-10-13 18:53:25 +053013136 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080013137 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013138 cds_get_channel_from_scan_result(pAdapter,
13139 pRoamProfile, &channel);
13140 if (channel)
13141 cds_checkn_update_hw_mode_single_mac_mode
13142 (channel);
13143 }
13144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013145 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013146 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013147 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013149 goto ret_status;
13150
13151conn_failure:
13152 /* Reset connect_in_progress */
13153 cds_set_connection_in_progress(false);
13154
13155ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013156 EXIT();
13157 return status;
13158}
13159
13160/**
13161 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13162 * @pAdapter: Pointer to adapter
13163 * @auth_type: Auth type
13164 *
13165 * This function is used to set the authentication type (OPEN/SHARED).
13166 *
13167 * Return: 0 for success, non-zero for failure
13168 */
13169static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13170 enum nl80211_auth_type auth_type)
13171{
13172 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13173 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 /*set authentication type */
13176 switch (auth_type) {
13177 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013178 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013179 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13180 break;
13181
13182 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013184 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013185 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13186 break;
13187
13188 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013189 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013190 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13191 break;
13192#ifdef FEATURE_WLAN_ESE
13193 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013194 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13196 break;
13197#endif
13198
13199 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013200 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13202 return -EINVAL;
13203 }
13204
13205 pWextState->roamProfile.AuthType.authType[0] =
13206 pHddStaCtx->conn_info.authType;
13207 return 0;
13208}
13209
13210/**
13211 * wlan_hdd_set_akm_suite() - set key management type
13212 * @pAdapter: Pointer to adapter
13213 * @key_mgmt: Key management type
13214 *
13215 * This function is used to set the key mgmt type(PSK/8021x).
13216 *
13217 * Return: 0 for success, non-zero for failure
13218 */
13219static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13220{
13221 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13224#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13225 /*set key mgmt type */
13226 switch (key_mgmt) {
13227 case WLAN_AKM_SUITE_PSK:
13228 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013230 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13232 break;
13233
13234 case WLAN_AKM_SUITE_8021X_SHA256:
13235 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013236 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013237 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13239 break;
13240#ifdef FEATURE_WLAN_ESE
13241#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13242#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13243 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013244 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13246 break;
13247#endif
13248#ifndef WLAN_AKM_SUITE_OSEN
13249#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13250#endif
13251 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013252 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013253 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13254 break;
13255
13256 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013257 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 return -EINVAL;
13259
13260 }
13261 return 0;
13262}
13263
13264/**
13265 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13266 * @pAdapter: Pointer to adapter
13267 * @cipher: Cipher type
13268 * @ucast: Unicast flag
13269 *
13270 * This function is used to set the encryption type
13271 * (NONE/WEP40/WEP104/TKIP/CCMP).
13272 *
13273 * Return: 0 for success, non-zero for failure
13274 */
13275static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13276 u32 cipher, bool ucast)
13277{
13278 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13279 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13280 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013283 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13285 } else {
13286
13287 /*set encryption method */
13288 switch (cipher) {
13289 case IW_AUTH_CIPHER_NONE:
13290 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13291 break;
13292
13293 case WLAN_CIPHER_SUITE_WEP40:
13294 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13295 break;
13296
13297 case WLAN_CIPHER_SUITE_WEP104:
13298 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13299 break;
13300
13301 case WLAN_CIPHER_SUITE_TKIP:
13302 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13303 break;
13304
13305 case WLAN_CIPHER_SUITE_CCMP:
13306 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13307 break;
13308#ifdef FEATURE_WLAN_WAPI
13309 case WLAN_CIPHER_SUITE_SMS4:
13310 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13311 break;
13312#endif
13313
13314#ifdef FEATURE_WLAN_ESE
13315 case WLAN_CIPHER_SUITE_KRK:
13316 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13317 break;
13318#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13319 case WLAN_CIPHER_SUITE_BTK:
13320 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13321 break;
13322#endif
13323#endif
13324 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013325 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326 return -EOPNOTSUPP;
13327 }
13328 }
13329
13330 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013331 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13333 pWextState->roamProfile.EncryptionType.numEntries = 1;
13334 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13335 encryptionType;
13336 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013337 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13339 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13340 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13341 encryptionType;
13342 }
13343
13344 return 0;
13345}
13346
13347/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013348 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13349 * @wext_state: Pointer to wext state
13350 * @gen_ie: Pointer to IE data
13351 * @len: length of IE data
13352 *
13353 * Return: 0 for success, non-zero for failure
13354 */
13355static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13356 const uint8_t *gen_ie, uint16_t len)
13357{
13358 uint16_t cur_add_ie_len =
13359 wext_state->assocAddIE.length;
13360
13361 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13362 (wext_state->assocAddIE.length + len)) {
13363 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13364 QDF_ASSERT(0);
13365 return -ENOMEM;
13366 }
13367 memcpy(wext_state->assocAddIE.addIEdata +
13368 cur_add_ie_len, gen_ie, len);
13369 wext_state->assocAddIE.length += len;
13370
13371 wext_state->roamProfile.pAddIEAssoc =
13372 wext_state->assocAddIE.addIEdata;
13373 wext_state->roamProfile.nAddIEAssocLength =
13374 wext_state->assocAddIE.length;
13375 return 0;
13376}
13377
13378/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379 * wlan_hdd_cfg80211_set_ie() - set IEs
13380 * @pAdapter: Pointer to adapter
13381 * @ie: Pointer ot ie
13382 * @ie: IE length
13383 *
13384 * Return: 0 for success, non-zero for failure
13385 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013386static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013387 size_t ie_len)
13388{
13389 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13390 const uint8_t *genie = ie;
13391 uint16_t remLen = ie_len;
13392#ifdef FEATURE_WLAN_WAPI
13393 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13394 u16 *tmp;
13395 uint16_t akmsuiteCount;
13396 int *akmlist;
13397#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013398 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013399
13400 /* clear previous assocAddIE */
13401 pWextState->assocAddIE.length = 0;
13402 pWextState->roamProfile.bWPSAssociation = false;
13403 pWextState->roamProfile.bOSENAssociation = false;
13404
13405 while (remLen >= 2) {
13406 uint16_t eLen = 0;
13407 uint8_t elementId;
13408 elementId = *genie++;
13409 eLen = *genie++;
13410 remLen -= 2;
13411
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013412 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413
13414 switch (elementId) {
13415 case DOT11F_EID_WPA:
13416 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 -070013417 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 return -EINVAL;
13419 } else if (0 ==
13420 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13421 uint16_t curAddIELen =
13422 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013423 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424
13425 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13426 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013427 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013428 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 return -ENOMEM;
13430 }
13431 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13432 memcpy(pWextState->assocAddIE.addIEdata +
13433 curAddIELen, genie - 2, eLen + 2);
13434 pWextState->assocAddIE.length += eLen + 2;
13435
13436 pWextState->roamProfile.bWPSAssociation = true;
13437 pWextState->roamProfile.pAddIEAssoc =
13438 pWextState->assocAddIE.addIEdata;
13439 pWextState->roamProfile.nAddIEAssocLength =
13440 pWextState->assocAddIE.length;
13441 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013442 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013443 memset(pWextState->WPARSNIE, 0,
13444 MAX_WPA_RSN_IE_LEN);
13445 memcpy(pWextState->WPARSNIE, genie - 2,
13446 (eLen + 2));
13447 pWextState->roamProfile.pWPAReqIE =
13448 pWextState->WPARSNIE;
13449 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13450 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13451 P2P_OUI_TYPE_SIZE))) {
13452 uint16_t curAddIELen =
13453 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013454 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455
13456 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13457 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013458 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013459 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013460 return -ENOMEM;
13461 }
13462 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13463 memcpy(pWextState->assocAddIE.addIEdata +
13464 curAddIELen, genie - 2, eLen + 2);
13465 pWextState->assocAddIE.length += eLen + 2;
13466
13467 pWextState->roamProfile.pAddIEAssoc =
13468 pWextState->assocAddIE.addIEdata;
13469 pWextState->roamProfile.nAddIEAssocLength =
13470 pWextState->assocAddIE.length;
13471 }
13472#ifdef WLAN_FEATURE_WFD
13473 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13474 WFD_OUI_TYPE_SIZE)) &&
13475 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013476 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013477 pAdapter->device_mode)) {
13478 uint16_t curAddIELen =
13479 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013480 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481
13482 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13483 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013484 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013485 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013486 return -ENOMEM;
13487 }
13488 /* WFD IE is saved to Additional IE ; it should
13489 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013490 * WFD IE
13491 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 memcpy(pWextState->assocAddIE.addIEdata +
13493 curAddIELen, genie - 2, eLen + 2);
13494 pWextState->assocAddIE.length += eLen + 2;
13495
13496 pWextState->roamProfile.pAddIEAssoc =
13497 pWextState->assocAddIE.addIEdata;
13498 pWextState->roamProfile.nAddIEAssocLength =
13499 pWextState->assocAddIE.length;
13500 }
13501#endif
13502 /* Appending HS 2.0 Indication Element in Assiciation Request */
13503 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13504 HS20_OUI_TYPE_SIZE))) {
13505 uint16_t curAddIELen =
13506 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013507 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013508
13509 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13510 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013511 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013512 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513 return -ENOMEM;
13514 }
13515 memcpy(pWextState->assocAddIE.addIEdata +
13516 curAddIELen, genie - 2, eLen + 2);
13517 pWextState->assocAddIE.length += eLen + 2;
13518
13519 pWextState->roamProfile.pAddIEAssoc =
13520 pWextState->assocAddIE.addIEdata;
13521 pWextState->roamProfile.nAddIEAssocLength =
13522 pWextState->assocAddIE.length;
13523 }
13524 /* Appending OSEN Information Element in Assiciation Request */
13525 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13526 OSEN_OUI_TYPE_SIZE))) {
13527 uint16_t curAddIELen =
13528 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013529 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013530
13531 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13532 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013533 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013534 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013535 return -ENOMEM;
13536 }
13537 memcpy(pWextState->assocAddIE.addIEdata +
13538 curAddIELen, genie - 2, eLen + 2);
13539 pWextState->assocAddIE.length += eLen + 2;
13540
13541 pWextState->roamProfile.bOSENAssociation = true;
13542 pWextState->roamProfile.pAddIEAssoc =
13543 pWextState->assocAddIE.addIEdata;
13544 pWextState->roamProfile.nAddIEAssocLength =
13545 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013546 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13547 MBO_OUI_TYPE_SIZE))){
13548 hdd_info("Set MBO IE(len %d)", eLen + 2);
13549 status = wlan_hdd_add_assoc_ie(pWextState,
13550 genie - 2, eLen + 2);
13551 if (status)
13552 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013553 } else {
13554 uint16_t add_ie_len =
13555 pWextState->assocAddIE.length;
13556
13557 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13558
13559 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13560 (pWextState->assocAddIE.length + eLen)) {
13561 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013562 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013563 return -ENOMEM;
13564 }
13565
13566 memcpy(pWextState->assocAddIE.addIEdata +
13567 add_ie_len, genie - 2, eLen + 2);
13568 pWextState->assocAddIE.length += eLen + 2;
13569
13570 pWextState->roamProfile.pAddIEAssoc =
13571 pWextState->assocAddIE.addIEdata;
13572 pWextState->roamProfile.nAddIEAssocLength =
13573 pWextState->assocAddIE.length;
13574 }
13575 break;
13576 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013577 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013578 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13579 memcpy(pWextState->WPARSNIE, genie - 2,
13580 (eLen + 2));
13581 pWextState->roamProfile.pRSNReqIE =
13582 pWextState->WPARSNIE;
13583 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13584 break;
13585 /*
13586 * Appending Extended Capabilities with Interworking bit set
13587 * in Assoc Req.
13588 *
13589 * In assoc req this EXT Cap will only be taken into account if
13590 * interworkingService bit is set to 1. Currently
13591 * driver is only interested in interworkingService capability
13592 * from supplicant. If in future any other EXT Cap info is
13593 * required from supplicat, it needs to be handled while
13594 * sending Assoc Req in LIM.
13595 */
13596 case DOT11F_EID_EXTCAP:
13597 {
13598 uint16_t curAddIELen =
13599 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013600 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601
13602 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13603 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013604 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013605 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 return -ENOMEM;
13607 }
13608 memcpy(pWextState->assocAddIE.addIEdata +
13609 curAddIELen, genie - 2, eLen + 2);
13610 pWextState->assocAddIE.length += eLen + 2;
13611
13612 pWextState->roamProfile.pAddIEAssoc =
13613 pWextState->assocAddIE.addIEdata;
13614 pWextState->roamProfile.nAddIEAssocLength =
13615 pWextState->assocAddIE.length;
13616 break;
13617 }
13618#ifdef FEATURE_WLAN_WAPI
13619 case WLAN_EID_WAPI:
13620 /* Setting WAPI Mode to ON=1 */
13621 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013622 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 tmp = (u16 *) ie;
13624 tmp = tmp + 2; /* Skip element Id and Len, Version */
13625 akmsuiteCount = WPA_GET_LE16(tmp);
13626 tmp = tmp + 1;
13627 akmlist = (int *)(tmp);
13628 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13629 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13630 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013631 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013632 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013633 return -EINVAL;
13634 }
13635
13636 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013637 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 pAdapter->wapi_info.wapiAuthMode =
13639 WAPI_AUTH_MODE_PSK;
13640 }
13641 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013642 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 pAdapter->wapi_info.wapiAuthMode =
13644 WAPI_AUTH_MODE_CERT;
13645 }
13646 break;
13647#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013648 case DOT11F_EID_SUPPOPERATINGCLASSES:
13649 {
13650 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13651 status = wlan_hdd_add_assoc_ie(pWextState,
13652 genie - 2, eLen + 2);
13653 if (status)
13654 return status;
13655 break;
13656 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013657 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013658 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013659 /* when Unknown IE is received we break
13660 * and continue to the next IE in the buffer
13661 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013662 break;
13663 }
13664 genie += eLen;
13665 remLen -= eLen;
13666 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013667 return 0;
13668}
13669
13670/**
13671 * hdd_is_wpaie_present() - check for WPA ie
13672 * @ie: Pointer to ie
13673 * @ie_len: Ie length
13674 *
13675 * Parse the received IE to find the WPA IE
13676 *
13677 * Return: true if wpa ie is found else false
13678 */
13679static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13680{
13681 uint8_t eLen = 0;
13682 uint16_t remLen = ie_len;
13683 uint8_t elementId = 0;
13684
13685 while (remLen >= 2) {
13686 elementId = *ie++;
13687 eLen = *ie++;
13688 remLen -= 2;
13689 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013690 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691 return false;
13692 }
13693 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13694 /* OUI - 0x00 0X50 0XF2
13695 * WPA Information Element - 0x01
13696 * WPA version - 0x01
13697 */
13698 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13699 return true;
13700 }
13701 ie += eLen;
13702 remLen -= eLen;
13703 }
13704 return false;
13705}
13706
13707/**
13708 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13709 * @pAdapter: Pointer to adapter
13710 * @req: Pointer to security parameters
13711 *
13712 * Return: 0 for success, non-zero for failure
13713 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013714static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13715 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716{
13717 int status = 0;
13718 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13719 ENTER();
13720
13721 /*set wpa version */
13722 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13723
13724 if (req->crypto.wpa_versions) {
13725 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13726 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13727 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13728 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13729 }
13730 }
13731
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013732 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013733
13734 /*set authentication type */
13735 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13736
13737 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013738 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013739 return status;
13740 }
13741
13742 /*set key mgmt type */
13743 if (req->crypto.n_akm_suites) {
13744 status =
13745 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13746 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013747 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748 return status;
13749 }
13750 }
13751
13752 /*set pairwise cipher type */
13753 if (req->crypto.n_ciphers_pairwise) {
13754 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13755 req->crypto.
13756 ciphers_pairwise[0],
13757 true);
13758 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013759 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760 return status;
13761 }
13762 } else {
13763 /*Reset previous cipher suite to none */
13764 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13765 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013766 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013767 return status;
13768 }
13769 }
13770
13771 /*set group cipher type */
13772 status =
13773 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13774 false);
13775
13776 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013777 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013778 return status;
13779 }
13780#ifdef WLAN_FEATURE_11W
13781 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13782#endif
13783
13784 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13785 if (req->ie_len) {
13786 status =
13787 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13788 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013789 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013790 return status;
13791 }
13792 }
13793
13794 /*incase of WEP set default key information */
13795 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013796 u8 key_len = req->key_len;
13797 u8 key_idx = req->key_idx;
13798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13800 || (WLAN_CIPHER_SUITE_WEP104 ==
13801 req->crypto.ciphers_pairwise[0])
13802 ) {
13803 if (IW_AUTH_KEY_MGMT_802_1X
13804 ==
13805 (pWextState->
13806 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013807 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013809 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013810
Jeff Johnson68755312017-02-10 11:46:55 -080013811 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13812 && (CSR_MAX_NUM_KEY > key_idx)) {
13813 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13814 key_idx, key_len);
13815 qdf_mem_copy(&pWextState->roamProfile.
13816 Keys.
13817 KeyMaterial[key_idx][0],
13818 req->key, key_len);
13819 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013820 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013821 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013823 }
13824 }
13825 }
13826
13827 return status;
13828}
13829
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013830int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831{
13832 unsigned long rc;
13833 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013834 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835
13836 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13837
Jeff Johnson9edf9572016-10-03 15:24:49 -070013838 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013839 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13840 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13841 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013842 hdd_conn_set_connection_state(pAdapter,
13843 eConnectionState_Disconnecting);
13844 /* Issue disconnect to CSR */
13845 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013846
13847 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13848 pAdapter->sessionId,
13849 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13850 /*
13851 * Wait here instead of returning directly, this will block the
13852 * next connect command and allow processing of the scan for
13853 * ssid and the previous connect command in CSR. Else we might
13854 * hit some race conditions leading to SME and HDD out of sync.
13855 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013856 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013857 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13858 } else if (0 != status) {
13859 hdd_err("csrRoamDisconnect failure, returned %d",
13860 (int)status);
13861 pHddStaCtx->staDebugState = status;
13862 result = -EINVAL;
13863 goto disconnected;
13864 }
13865
13866 rc = wait_for_completion_timeout(
13867 &pAdapter->disconnect_comp_var,
13868 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013869 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013870 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13871 pAdapter->sessionId, pHddStaCtx->staDebugState);
13872 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013873 }
13874 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013875 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013876 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013877 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013879 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013881 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013882 }
13883 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013884disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013885 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13886 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013887}
13888
13889/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013890 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13891 * @adapter: Pointer to the HDD adapter
13892 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013893 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013894 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013895 * This function will start reassociation if prev_bssid is set and bssid/
13896 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013897 *
Naveen Rawat07332902016-07-27 09:13:17 -070013898 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013899 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013900#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13901 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013902static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13903 struct cfg80211_connect_params *req,
13904 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013905{
Naveen Rawat07332902016-07-27 09:13:17 -070013906 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013907 const uint8_t *bssid = NULL;
13908 uint16_t channel = 0;
13909
13910 if (req->bssid)
13911 bssid = req->bssid;
13912 else if (req->bssid_hint)
13913 bssid = req->bssid_hint;
13914
13915 if (req->channel)
13916 channel = req->channel->hw_value;
13917 else if (req->channel_hint)
13918 channel = req->channel_hint->hw_value;
13919
13920 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013921 reassoc = true;
13922 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013923 channel, MAC_ADDR_ARRAY(bssid));
13924 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013925 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013926 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013927 }
Naveen Rawat07332902016-07-27 09:13:17 -070013928 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013929}
13930#else
Naveen Rawat07332902016-07-27 09:13:17 -070013931static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13932 struct cfg80211_connect_params *req,
13933 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013934{
Naveen Rawat07332902016-07-27 09:13:17 -070013935 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013936}
13937#endif
13938
13939/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013940 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13941 * @wiphy: Pointer to wiphy
13942 * @dev: Pointer to network device
13943 * @req: Pointer to cfg80211 connect request
13944 *
13945 * This function is used to start the association process
13946 *
13947 * Return: 0 for success, non-zero for failure
13948 */
13949static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13950 struct net_device *ndev,
13951 struct cfg80211_connect_params *req)
13952{
13953 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013954 u16 channel;
13955#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13956 const u8 *bssid_hint = req->bssid_hint;
13957#else
13958 const u8 *bssid_hint = NULL;
13959#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13961 hdd_context_t *pHddCtx;
13962
13963 ENTER();
13964
Anurag Chouhan6d760662016-02-20 16:05:43 +053013965 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013966 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 return -EINVAL;
13968 }
13969
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013970 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13971 hdd_err("invalid session id: %d", pAdapter->sessionId);
13972 return -EINVAL;
13973 }
13974
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013975 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976 TRACE_CODE_HDD_CFG80211_CONNECT,
13977 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013978 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 hdd_device_mode_to_string(pAdapter->device_mode),
13980 pAdapter->device_mode);
13981
Krunal Sonib4326f22016-03-10 13:05:51 -080013982 if (pAdapter->device_mode != QDF_STA_MODE &&
13983 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013984 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 hdd_device_mode_to_string(pAdapter->device_mode),
13986 pAdapter->device_mode);
13987 return -EINVAL;
13988 }
13989
13990 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13991 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013992 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013993 return -EINVAL;
13994 }
13995
13996 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013997 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013999
Naveen Rawat07332902016-07-27 09:13:17 -070014000 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014001 return status;
14002
Agrawal Ashishf156e942016-08-04 14:54:47 +053014003 /* Try disconnecting if already in connected state */
14004 status = wlan_hdd_try_disconnect(pAdapter);
14005 if (0 > status) {
14006 hdd_err("Failed to disconnect the existing connection");
14007 return -EALREADY;
14008 }
14009
14010 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014012 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014013 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014014 pAdapter->device_mode),
14015 req->channel->hw_value, HW_MODE_20_MHZ)) {
14016 hdd_err("This concurrency combination is not allowed");
14017 return -ECONNREFUSED;
14018 }
14019 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014020 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014021 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014022 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14023 hdd_err("This concurrency combination is not allowed");
14024 return -ECONNREFUSED;
14025 }
14026 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 /*initialise security parameters */
14029 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14030
14031 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014032 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 return status;
14034 }
14035
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014036 if (req->channel)
14037 channel = req->channel->hw_value;
14038 else
14039 channel = 0;
14040 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14041 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014042 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014043 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014044 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014045 return status;
14046 }
14047 EXIT();
14048 return status;
14049}
14050
14051/**
14052 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14053 * @wiphy: Pointer to wiphy
14054 * @dev: Pointer to network device
14055 * @req: Pointer to cfg80211 connect request
14056 *
14057 * Return: 0 for success, non-zero for failure
14058 */
14059static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14060 struct net_device *ndev,
14061 struct cfg80211_connect_params *req)
14062{
14063 int ret;
14064 cds_ssr_protect(__func__);
14065 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14066 cds_ssr_unprotect(__func__);
14067
14068 return ret;
14069}
14070
14071/**
14072 * wlan_hdd_disconnect() - hdd disconnect api
14073 * @pAdapter: Pointer to adapter
14074 * @reason: Disconnect reason code
14075 *
14076 * This function is used to issue a disconnect request to SME
14077 *
14078 * Return: 0 for success, non-zero for failure
14079 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014080static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081{
14082 int status, result = 0;
14083 unsigned long rc;
14084 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14085 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14086
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014087 ENTER();
14088
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014089 status = wlan_hdd_validate_context(pHddCtx);
14090
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014091 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014092 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093
14094 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014095 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014096 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
14097 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014098 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14100 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14101
14102 /*issue disconnect */
14103
14104 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14105 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053014106 /*
14107 * Wait here instead of returning directly, this will block the next
14108 * connect command and allow processing of the scan for ssid and
14109 * the previous connect command in CSR. Else we might hit some
14110 * race conditions leading to SME and HDD out of sync.
14111 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014112 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014113 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014115 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014116 (int)status);
14117 pHddStaCtx->staDebugState = status;
14118 result = -EINVAL;
14119 goto disconnected;
14120 }
14121 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14122 msecs_to_jiffies
14123 (WLAN_WAIT_TIME_DISCONNECT));
14124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014125 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014126 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 result = -ETIMEDOUT;
14128 }
14129disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14131#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14132 /* Sending disconnect event to userspace for kernel version < 3.11
14133 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14134 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014135 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014136 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14137 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138#endif
14139
14140 return result;
14141}
14142
14143/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014144 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14145 * @reason: ieee80211 reason code.
14146 *
14147 * This utility function helps log string conversion of reason code.
14148 *
14149 * Return: string conversion of reason code, if match found;
14150 * "Unknown" otherwise.
14151 */
14152static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14153{
14154 switch (reason) {
14155 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14156 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14157 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14158 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14159 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14160 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14161 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14162 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14163 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14164 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14165 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14166 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14167 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14168 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14169 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14170 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14171 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14172 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14173 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14174 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14175 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14176 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14177 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14178 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14179 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14180 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14181 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14182 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14183 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14184 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14185 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14186 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14187 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14188 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14189 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14190 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14191 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14192 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14193 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14194 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14195 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14196 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14197 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14198 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14199 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14200 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14201 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14202 default:
14203 return "Unknown";
14204 }
14205}
14206
14207/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14209 * @wiphy: Pointer to wiphy
14210 * @dev: Pointer to network device
14211 * @reason: Disconnect reason code
14212 *
14213 * This function is used to issue a disconnect request to SME
14214 *
14215 * Return: 0 for success, non-zero for failure
14216 */
14217static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14218 struct net_device *dev, u16 reason)
14219{
14220 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14221 int status;
14222 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14223 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14224#ifdef FEATURE_WLAN_TDLS
14225 uint8_t staIdx;
14226#endif
14227
14228 ENTER();
14229
Anurag Chouhan6d760662016-02-20 16:05:43 +053014230 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014231 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 return -EINVAL;
14233 }
14234
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014235 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14236 hdd_err("invalid session id: %d", pAdapter->sessionId);
14237 return -EINVAL;
14238 }
14239
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014240 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14242 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014243 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 hdd_device_mode_to_string(pAdapter->device_mode),
14245 pAdapter->device_mode, reason);
14246
14247 status = wlan_hdd_validate_context(pHddCtx);
14248
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080014249 if (hdd_is_roaming_in_progress()) {
14250 hdd_err("Roaming In Progress. Ignore!!!");
14251 return -EAGAIN;
14252 }
14253
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014254 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014255 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014256
14257 /* Issue disconnect request to SME, if station is in connected state */
14258 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14259 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14260 eCsrRoamDisconnectReason reasonCode =
14261 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14262 hdd_scaninfo_t *pScanInfo;
14263
14264 switch (reason) {
14265 case WLAN_REASON_MIC_FAILURE:
14266 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14267 break;
14268
14269 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14270 case WLAN_REASON_DISASSOC_AP_BUSY:
14271 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14272 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14273 break;
14274
14275 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14276 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14277 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14278 break;
14279
14280 case WLAN_REASON_DEAUTH_LEAVING:
14281 reasonCode =
14282 pHddCtx->config->
14283 gEnableDeauthToDisassocMap ?
14284 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14285 eCSR_DISCONNECT_REASON_DEAUTH;
14286 break;
14287 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14288 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14289 break;
14290 default:
14291 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14292 break;
14293 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014294 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014295 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296 pScanInfo = &pAdapter->scan_info;
14297 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014298 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014300 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 eCSR_SCAN_ABORT_DEFAULT);
14302 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014303 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304#ifdef FEATURE_WLAN_TDLS
14305 /* First clean up the tdls peers if any */
14306 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14307 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14308 pAdapter->sessionId)
14309 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14310 uint8_t *mac;
14311 mac =
14312 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014313 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14314 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014315 pHddCtx->tdlsConnInfo[staIdx].staId,
14316 pAdapter->sessionId,
14317 MAC_ADDR_ARRAY(mac));
14318 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14319 (pAdapter),
14320 pAdapter->sessionId, mac);
14321 }
14322 }
14323#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014324 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014326 hdd_info("Disconnect request from user space with reason: %s",
14327 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14329 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014330 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331 return -EINVAL;
14332 }
14333 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014334 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 pHddStaCtx->conn_info.connState);
14336 }
14337
14338 return status;
14339}
14340
14341/**
14342 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14343 * @wiphy: Pointer to wiphy
14344 * @dev: Pointer to network device
14345 * @reason: Disconnect reason code
14346 *
14347 * Return: 0 for success, non-zero for failure
14348 */
14349static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14350 struct net_device *dev, u16 reason)
14351{
14352 int ret;
14353 cds_ssr_protect(__func__);
14354 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14355 cds_ssr_unprotect(__func__);
14356
14357 return ret;
14358}
14359
14360/**
14361 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14362 * @pAdapter: Pointer to adapter
14363 * @param: Pointer to IBSS parameters
14364 *
14365 * This function is used to initialize the security settings in IBSS mode
14366 *
14367 * Return: 0 for success, non-zero for failure
14368 */
14369static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14370 struct cfg80211_ibss_params
14371 *params)
14372{
14373 int status = 0;
14374 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14375 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14376 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14377
14378 ENTER();
14379
14380 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014381 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 pHddStaCtx->ibss_enc_key_installed = 0;
14383
14384 if (params->ie_len && (NULL != params->ie)) {
14385 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14386 params->ie_len, WLAN_EID_RSN)) {
14387 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14388 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14389 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14390 tDot11fIEWPA dot11WPAIE;
14391 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14392 u8 *ie;
14393
14394 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14395 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14396 params->ie_len,
14397 DOT11F_EID_WPA);
14398 if (NULL != ie) {
14399 pWextState->wpaVersion =
14400 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014401 /* Unpack the WPA IE
14402 * Skip past the EID byte and length byte
14403 * and four byte WiFi OUI
14404 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014405 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14406 &ie[2 + 4],
14407 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014408 /* Extract the multicast cipher, the
14409 * encType for unicast cipher for
14410 * wpa-none is none
14411 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014412 encryptionType =
14413 hdd_translate_wpa_to_csr_encryption_type
14414 (dot11WPAIE.multicast_cipher);
14415 }
14416 }
14417
14418 status =
14419 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14420 params->ie_len);
14421
14422 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014423 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014424 return status;
14425 }
14426 }
14427
14428 pWextState->roamProfile.AuthType.authType[0] =
14429 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14430
14431 if (params->privacy) {
14432 /* Security enabled IBSS, At this time there is no information
14433 * available about the security paramters, so initialise the
14434 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14435 * The correct security parameters will be updated later in
14436 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14437 * set inorder enable privacy bit in beacons
14438 */
14439
14440 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14441 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014442 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014443 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14444 pWextState->roamProfile.EncryptionType.numEntries = 1;
14445 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14446 encryptionType;
14447 return status;
14448}
14449
14450/**
14451 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14452 * @wiphy: Pointer to wiphy
14453 * @dev: Pointer to network device
14454 * @param: Pointer to IBSS join parameters
14455 *
14456 * This function is used to create/join an IBSS network
14457 *
14458 * Return: 0 for success, non-zero for failure
14459 */
14460static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14461 struct net_device *dev,
14462 struct cfg80211_ibss_params *params)
14463{
14464 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14465 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14466 tCsrRoamProfile *pRoamProfile;
14467 int status;
14468 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14469 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014470 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014472
14473 ENTER();
14474
Anurag Chouhan6d760662016-02-20 16:05:43 +053014475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014476 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014477 return -EINVAL;
14478 }
14479
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014480 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14481 hdd_err("invalid session id: %d", pAdapter->sessionId);
14482 return -EINVAL;
14483 }
14484
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014485 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14487 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014488 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014489 hdd_device_mode_to_string(pAdapter->device_mode),
14490 pAdapter->device_mode);
14491
14492 status = wlan_hdd_validate_context(pHddCtx);
14493
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014494 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014495 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496
14497 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014498 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14500 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14501 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14502 int indx;
14503
14504 /* Get channel number */
14505 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014506 params->
14507 chandef.
14508 chan->
14509 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510
14511 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14512 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014513 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 return -EOPNOTSUPP;
14515 }
14516
14517 for (indx = 0; indx < numChans; indx++) {
14518 if (channelNum == validChan[indx]) {
14519 break;
14520 }
14521 }
14522 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014523 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 return -EINVAL;
14525 }
14526 }
14527
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014528 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014529 HW_MODE_20_MHZ)) {
14530 hdd_err("This concurrency combination is not allowed");
14531 return -ECONNREFUSED;
14532 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014533
Krunal Soni3091bcc2016-06-23 12:28:21 -070014534 status = qdf_reset_connection_update();
14535 if (!QDF_IS_STATUS_SUCCESS(status))
14536 hdd_err("ERR: clear event failed");
14537
14538 status = cds_current_connections_update(pAdapter->sessionId,
14539 channelNum,
14540 SIR_UPDATE_REASON_JOIN_IBSS);
14541 if (QDF_STATUS_E_FAILURE == status) {
14542 hdd_err("ERROR: connections update failed!!");
14543 return -EINVAL;
14544 }
14545
14546 if (QDF_STATUS_SUCCESS == status) {
14547 status = qdf_wait_for_connection_update();
14548 if (!QDF_IS_STATUS_SUCCESS(status)) {
14549 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014550 return -EINVAL;
14551 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 }
14553
14554 /*Try disconnecting if already in connected state */
14555 status = wlan_hdd_try_disconnect(pAdapter);
14556 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014557 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558 return -EALREADY;
14559 }
14560
14561 pRoamProfile = &pWextState->roamProfile;
14562
14563 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014564 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 return -EINVAL;
14566 }
14567
14568 /* enable selected protection checks in IBSS mode */
14569 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14570
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014571 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14573 pHddCtx->config->
14574 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014575 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014576 }
14577
14578 /* BSSID is provided by upper layers hence no need to AUTO generate */
14579 if (NULL != params->bssid) {
14580 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014581 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014582 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014583 return -EIO;
14584 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014585 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014586 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14587 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014588 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014589 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590 return -EIO;
14591 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014592 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014593 }
14594 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14595 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14596 pRoamProfile->beaconInterval = params->beacon_interval;
14597 else {
14598 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014599 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014600 params->beacon_interval, pRoamProfile->beaconInterval);
14601 }
14602
14603 /* Set Channel */
14604 if (channelNum) {
14605 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014606 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014607 pRoamProfile->ChannelInfo.numOfChannels = 1;
14608 pHddStaCtx->conn_info.operationChannel = channelNum;
14609 pRoamProfile->ChannelInfo.ChannelList =
14610 &pHddStaCtx->conn_info.operationChannel;
14611 }
14612
14613 /* Initialize security parameters */
14614 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14615 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014616 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014617 return status;
14618 }
14619
14620 /* Issue connect start */
14621 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14622 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014623 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014625 operationChannel,
14626 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014627
14628 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014629 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014630 return status;
14631 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014632 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014633 return 0;
14634}
14635
14636/**
14637 * wlan_hdd_cfg80211_join_ibss() - join ibss
14638 * @wiphy: Pointer to wiphy
14639 * @dev: Pointer to network device
14640 * @param: Pointer to IBSS join parameters
14641 *
14642 * This function is used to create/join an IBSS network
14643 *
14644 * Return: 0 for success, non-zero for failure
14645 */
14646static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14647 struct net_device *dev,
14648 struct cfg80211_ibss_params *params)
14649{
14650 int ret = 0;
14651
14652 cds_ssr_protect(__func__);
14653 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14654 cds_ssr_unprotect(__func__);
14655
14656 return ret;
14657}
14658
14659/**
14660 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14661 * @wiphy: Pointer to wiphy
14662 * @dev: Pointer to network device
14663 *
14664 * This function is used to leave an IBSS network
14665 *
14666 * Return: 0 for success, non-zero for failure
14667 */
14668static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14669 struct net_device *dev)
14670{
14671 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14672 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14673 tCsrRoamProfile *pRoamProfile;
14674 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14675 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014676 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014677 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014678 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014679
14680 ENTER();
14681
Anurag Chouhan6d760662016-02-20 16:05:43 +053014682 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014683 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014684 return -EINVAL;
14685 }
14686
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014687 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14688 hdd_err("invalid session id: %d", pAdapter->sessionId);
14689 return -EINVAL;
14690 }
14691
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014692 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14694 pAdapter->sessionId,
14695 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14696 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014697 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014699
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014700 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014701 hdd_device_mode_to_string(pAdapter->device_mode),
14702 pAdapter->device_mode);
14703 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014704 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 return -EIO;
14706 }
14707
14708 pRoamProfile = &pWextState->roamProfile;
14709
14710 /* Issue disconnect only if interface type is set to IBSS */
14711 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014712 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 return -EINVAL;
14714 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014715 /* Clearing add IE of beacon */
14716 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14717 sizeof(tSirMacAddr));
14718 updateIE.smeSessionId = pAdapter->sessionId;
14719 updateIE.ieBufferlength = 0;
14720 updateIE.pAdditionIEBuffer = NULL;
14721 updateIE.append = true;
14722 updateIE.notify = true;
14723 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14724 &updateIE,
14725 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014726 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014727 }
14728
14729 /* Reset WNI_CFG_PROBE_RSP Flags */
14730 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731
14732 /* Issue Disconnect request */
14733 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14734 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14735 pAdapter->sessionId,
14736 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014737 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014738 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 hal_status);
14740 return -EAGAIN;
14741 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014742
14743 /* wait for mc thread to cleanup and then return to upper stack
14744 * so by the time upper layer calls the change interface, we are
14745 * all set to proceed further
14746 */
14747 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14748 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14749 if (!rc) {
14750 hdd_err("Failed to disconnect, timed out");
14751 return -ETIMEDOUT;
14752 }
14753
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014754 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014755 return 0;
14756}
14757
14758/**
14759 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14760 * @wiphy: Pointer to wiphy
14761 * @dev: Pointer to network device
14762 *
14763 * This function is used to leave an IBSS network
14764 *
14765 * Return: 0 for success, non-zero for failure
14766 */
14767static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14768 struct net_device *dev)
14769{
14770 int ret = 0;
14771
14772 cds_ssr_protect(__func__);
14773 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14774 cds_ssr_unprotect(__func__);
14775
14776 return ret;
14777}
14778
14779/**
14780 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14781 * @wiphy: Pointer to wiphy
14782 * @changed: Parameters changed
14783 *
14784 * This function is used to set the phy parameters. RTS Threshold/FRAG
14785 * Threshold/Retry Count etc.
14786 *
14787 * Return: 0 for success, non-zero for failure
14788 */
14789static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14790 u32 changed)
14791{
14792 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14793 tHalHandle hHal = pHddCtx->hHal;
14794 int status;
14795
14796 ENTER();
14797
Anurag Chouhan6d760662016-02-20 16:05:43 +053014798 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014799 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014800 return -EINVAL;
14801 }
14802
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014803 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14805 NO_SESSION, wiphy->rts_threshold));
14806 status = wlan_hdd_validate_context(pHddCtx);
14807
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014808 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810
14811 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14812 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14813 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14814
14815 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14816 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014817 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 rts_threshold);
14819 return -EINVAL;
14820 }
14821
14822 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14823 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014824 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 rts_threshold);
14826 return -EIO;
14827 }
14828
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014829 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 }
14831
14832 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14833 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14834 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14835 wiphy->frag_threshold;
14836
14837 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14838 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014839 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840 frag_threshold);
14841 return -EINVAL;
14842 }
14843
14844 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14845 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014846 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 frag_threshold);
14848 return -EIO;
14849 }
14850
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014851 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852 }
14853
14854 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14855 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14856 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14857 wiphy->retry_short : wiphy->retry_long;
14858
14859 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14860 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014861 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014862 return -EINVAL;
14863 }
14864
14865 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14866 if (0 != sme_cfg_set_int(hHal,
14867 WNI_CFG_LONG_RETRY_LIMIT,
14868 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014869 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014870 retry_value);
14871 return -EIO;
14872 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014873 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014874 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14875 if (0 != sme_cfg_set_int(hHal,
14876 WNI_CFG_SHORT_RETRY_LIMIT,
14877 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014878 hdd_err("sme_cfg_set_int failed for short 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 short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 }
14884 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014885 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014886 return 0;
14887}
14888
14889/**
14890 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14891 * @wiphy: Pointer to wiphy
14892 * @changed: Parameters changed
14893 *
14894 * Return: 0 for success, non-zero for failure
14895 */
14896static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14897{
14898 int ret;
14899
14900 cds_ssr_protect(__func__);
14901 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14902 cds_ssr_unprotect(__func__);
14903
14904 return ret;
14905}
14906
14907/**
14908 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14909 * key
14910 * @wiphy: Pointer to wiphy
14911 * @dev: Pointer to network device
14912 * @key_index: Key index
14913 *
14914 * Return: 0
14915 */
14916static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14917 struct net_device *netdev,
14918 u8 key_index)
14919{
14920 ENTER();
14921 return 0;
14922}
14923
14924/**
14925 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14926 * wlan_hdd_set_default_mgmt_key
14927 * @wiphy: pointer to wiphy
14928 * @netdev: pointer to net_device structure
14929 * @key_index: key index
14930 *
14931 * Return: 0 on success, error number on failure
14932 */
14933static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14934 struct net_device *netdev,
14935 u8 key_index)
14936{
14937 int ret;
14938
14939 cds_ssr_protect(__func__);
14940 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14941 cds_ssr_unprotect(__func__);
14942
14943 return ret;
14944}
14945
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014946/**
14947 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14948 * @wiphy: Pointer to wiphy
14949 * @dev: Pointer to network device
14950 * @params: Pointer to tx queue parameters
14951 *
14952 * Return: 0
14953 */
14954static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14955 struct net_device *dev,
14956 struct ieee80211_txq_params *params)
14957{
14958 ENTER();
14959 return 0;
14960}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014961
14962/**
14963 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
14964 * @wiphy: pointer to wiphy
14965 * @netdev: pointer to net_device structure
14966 * @params: pointer to ieee80211_txq_params
14967 *
14968 * Return: 0 on success, error number on failure
14969 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14971 struct net_device *dev,
14972 struct ieee80211_txq_params *params)
14973{
14974 int ret;
14975
14976 cds_ssr_protect(__func__);
14977 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14978 cds_ssr_unprotect(__func__);
14979
14980 return ret;
14981}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014982
14983/**
14984 * __wlan_hdd_cfg80211_del_station() - delete station v2
14985 * @wiphy: Pointer to wiphy
14986 * @param: Pointer to delete station parameter
14987 *
14988 * Return: 0 for success, non-zero for failure
14989 */
14990static
14991int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14992 struct net_device *dev,
14993 struct tagCsrDelStaParams *pDelStaParams)
14994{
14995 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14996 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014997 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014998 hdd_hostapd_state_t *hapd_state;
14999 int status;
15000 uint8_t staId;
15001 uint8_t *mac;
15002
15003 ENTER();
15004
Anurag Chouhan6d760662016-02-20 16:05:43 +053015005 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015006 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015007 return -EINVAL;
15008 }
15009
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015010 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15011 hdd_err("invalid session id: %d", pAdapter->sessionId);
15012 return -EINVAL;
15013 }
15014
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015015 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015016 TRACE_CODE_HDD_CFG80211_DEL_STA,
15017 pAdapter->sessionId, pAdapter->device_mode));
15018
15019 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15020 status = wlan_hdd_validate_context(pHddCtx);
15021
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015022 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015023 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024
15025 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15026
Krunal Sonib4326f22016-03-10 13:05:51 -080015027 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15028 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015029
15030 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15031 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015032 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015033 return 0;
15034 }
15035
Anurag Chouhanc5548422016-02-24 18:33:27 +053015036 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015037 uint16_t i;
15038 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15039 if ((pAdapter->aStaInfo[i].isUsed) &&
15040 (!pAdapter->aStaInfo[i].
15041 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015042 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 mac,
15044 pAdapter->aStaInfo[i].
15045 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015046 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015047 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15048 hdd_ipa_wlan_evt(pAdapter,
15049 pAdapter->
15050 aStaInfo[i].
15051 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015052 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 mac);
15054 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015055 hdd_notice("Delete STA with MAC::"
15056 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015057 MAC_ADDR_ARRAY(mac));
15058
15059 if (pHddCtx->dev_dfs_cac_status ==
15060 DFS_CAC_IN_PROGRESS)
15061 goto fn_end;
15062
Wei Song2f76f642016-11-18 16:32:53 +080015063 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015065 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015066 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067 hdd_softap_sta_deauth(pAdapter,
15068 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015069 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 pAdapter->aStaInfo[i].
15071 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015072 qdf_status =
15073 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015074 &hapd_state->
15075 qdf_sta_disassoc_event,
15076 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015077 if (!QDF_IS_STATUS_SUCCESS(
15078 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015079 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015080 }
15081 }
15082 }
15083 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015084 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015086 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015088 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015089 hdd_notice("Skip DEL STA as this is not used::"
15090 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015091 MAC_ADDR_ARRAY(mac));
15092 return -ENOENT;
15093 }
15094
15095 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15096 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015097 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015098 }
15099
15100 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15101 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015102 hdd_notice("Skip DEL STA as deauth is in progress::"
15103 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 MAC_ADDR_ARRAY(mac));
15105 return -ENOENT;
15106 }
15107
15108 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15109
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015110 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015111 MAC_ADDR_ARRAY(mac));
15112
15113 /* Case: SAP in ACS selected DFS ch and client connected
15114 * Now Radar detected. Then if random channel is another
15115 * DFS ch then new CAC is initiated and no TX allowed.
15116 * So do not send any mgmt frames as it will timeout
15117 * during CAC.
15118 */
15119
15120 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15121 goto fn_end;
15122
Wei Song2f76f642016-11-18 16:32:53 +080015123 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015124 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15125 (pAdapter), pAdapter->sessionId,
15126 (uint8_t *)&pDelStaParams->peerMacAddr,
15127 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015128 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015130 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015131 pAdapter->aStaInfo[staId].isDeauthInProgress =
15132 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015133 hdd_notice("STA removal failed for ::"
15134 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015135 MAC_ADDR_ARRAY(mac));
15136 return -ENOENT;
15137 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015138 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015139 &hapd_state->
15140 qdf_sta_disassoc_event,
15141 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015142 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015143 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015144 }
15145 }
15146 }
15147
15148fn_end:
15149 EXIT();
15150 return 0;
15151}
15152
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015153#if defined(USE_CFG80211_DEL_STA_V2)
15154/**
15155 * wlan_hdd_del_station() - delete station wrapper
15156 * @adapter: pointer to the hdd adapter
15157 *
15158 * Return: None
15159 */
15160void wlan_hdd_del_station(hdd_adapter_t *adapter)
15161{
15162 struct station_del_parameters del_sta;
15163 del_sta.mac = NULL;
15164 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15165 del_sta.reason_code = eCsrForcedDeauthSta;
15166
15167 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15168 &del_sta);
15169}
15170#else
15171void wlan_hdd_del_station(hdd_adapter_t *adapter)
15172{
15173 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15174}
15175#endif
15176
15177#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178/**
15179 * wlan_hdd_cfg80211_del_station() - delete station v2
15180 * @wiphy: Pointer to wiphy
15181 * @param: Pointer to delete station parameter
15182 *
15183 * Return: 0 for success, non-zero for failure
15184 */
15185int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15186 struct net_device *dev,
15187 struct station_del_parameters *param)
15188#else
15189/**
15190 * wlan_hdd_cfg80211_del_station() - delete station
15191 * @wiphy: Pointer to wiphy
15192 * @mac: Pointer to station mac address
15193 *
15194 * Return: 0 for success, non-zero for failure
15195 */
15196#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15197int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15198 struct net_device *dev,
15199 const uint8_t *mac)
15200#else
15201int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15202 struct net_device *dev,
15203 uint8_t *mac)
15204#endif
15205#endif
15206{
15207 int ret;
15208 struct tagCsrDelStaParams delStaParams;
15209
15210 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015211#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015212 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015213 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015214 return -EINVAL;
15215 }
15216 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15217 param->subtype, &delStaParams);
15218#else
15219 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15220 (SIR_MAC_MGMT_DEAUTH >> 4),
15221 &delStaParams);
15222#endif
15223 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15224 cds_ssr_unprotect(__func__);
15225
15226 return ret;
15227}
15228
15229/**
15230 * __wlan_hdd_cfg80211_add_station() - add station
15231 * @wiphy: Pointer to wiphy
15232 * @mac: Pointer to station mac address
15233 * @pmksa: Pointer to add station parameter
15234 *
15235 * Return: 0 for success, non-zero for failure
15236 */
15237static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15238 struct net_device *dev,
15239 const uint8_t *mac,
15240 struct station_parameters *params)
15241{
15242 int status = -EPERM;
15243#ifdef FEATURE_WLAN_TDLS
15244 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15245 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15246 u32 mask, set;
15247
15248 ENTER();
15249
Anurag Chouhan6d760662016-02-20 16:05:43 +053015250 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015251 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015252 return -EINVAL;
15253 }
15254
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015255 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15256 hdd_err("invalid session id: %d", pAdapter->sessionId);
15257 return -EINVAL;
15258 }
15259
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015260 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015261 TRACE_CODE_HDD_CFG80211_ADD_STA,
15262 pAdapter->sessionId, params->listen_interval));
15263
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015264 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015266
15267 mask = params->sta_flags_mask;
15268
15269 set = params->sta_flags_set;
15270
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015271 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015272 MAC_ADDR_ARRAY(mac));
15273
15274 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15275 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15276 status =
15277 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15278 }
15279 }
15280#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015281 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 return status;
15283}
15284
15285/**
15286 * wlan_hdd_cfg80211_add_station() - add station
15287 * @wiphy: Pointer to wiphy
15288 * @mac: Pointer to station mac address
15289 * @pmksa: Pointer to add station parameter
15290 *
15291 * Return: 0 for success, non-zero for failure
15292 */
15293#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15294static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15295 struct net_device *dev,
15296 const uint8_t *mac,
15297 struct station_parameters *params)
15298#else
15299static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15300 struct net_device *dev, uint8_t *mac,
15301 struct station_parameters *params)
15302#endif
15303{
15304 int ret;
15305
15306 cds_ssr_protect(__func__);
15307 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15308 cds_ssr_unprotect(__func__);
15309
15310 return ret;
15311}
15312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015313/**
15314 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15315 * @wiphy: Pointer to wiphy
15316 * @dev: Pointer to network device
15317 * @pmksa: Pointer to set pmksa parameter
15318 *
15319 * Return: 0 for success, non-zero for failure
15320 */
15321static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15322 struct net_device *dev,
15323 struct cfg80211_pmksa *pmksa)
15324{
15325 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15326 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15327 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015328 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 int status;
15330 tPmkidCacheInfo pmk_id;
15331
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015332 ENTER();
15333
Anurag Chouhan6d760662016-02-20 16:05:43 +053015334 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015335 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015336 return -EINVAL;
15337 }
15338
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015339 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15340 hdd_err("invalid session id: %d", pAdapter->sessionId);
15341 return -EINVAL;
15342 }
15343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015344 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015345 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 return -EINVAL;
15347 }
15348
15349 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015350 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015351 pmksa->bssid, pmksa->pmkid);
15352 return -EINVAL;
15353 }
15354
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015355 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356 MAC_ADDR_ARRAY(pmksa->bssid));
15357
15358 status = wlan_hdd_validate_context(pHddCtx);
15359
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015360 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015362
15363 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15364
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015365 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15366 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015367
15368 /* Add to the PMKSA ID Cache in CSR */
15369 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15370 &pmk_id, 1, false);
15371
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015372 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015373 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15374 pAdapter->sessionId, result));
15375
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015376 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015377 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015378}
15379
15380/**
15381 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15382 * @wiphy: Pointer to wiphy
15383 * @dev: Pointer to network device
15384 * @pmksa: Pointer to set pmksa parameter
15385 *
15386 * Return: 0 for success, non-zero for failure
15387 */
15388static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15389 struct net_device *dev,
15390 struct cfg80211_pmksa *pmksa)
15391{
15392 int ret;
15393
15394 cds_ssr_protect(__func__);
15395 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15396 cds_ssr_unprotect(__func__);
15397
15398 return ret;
15399}
15400
15401/**
15402 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15403 * @wiphy: Pointer to wiphy
15404 * @dev: Pointer to network device
15405 * @pmksa: Pointer to pmksa parameter
15406 *
15407 * Return: 0 for success, non-zero for failure
15408 */
15409static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15410 struct net_device *dev,
15411 struct cfg80211_pmksa *pmksa)
15412{
15413 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15414 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15415 tHalHandle halHandle;
15416 int status = 0;
15417
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015418 ENTER();
15419
Anurag Chouhan6d760662016-02-20 16:05:43 +053015420 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015421 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015422 return -EINVAL;
15423 }
15424
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015425 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15426 hdd_err("invalid session id: %d", pAdapter->sessionId);
15427 return -EINVAL;
15428 }
15429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015430 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015431 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 return -EINVAL;
15433 }
15434
15435 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015436 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015437 return -EINVAL;
15438 }
15439
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015440 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015441 MAC_ADDR_ARRAY(pmksa->bssid));
15442
15443 status = wlan_hdd_validate_context(pHddCtx);
15444
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015445 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015446 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015447
15448 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15449
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015450 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015451 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15452 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015453 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015454 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015455 sme_roam_del_pmkid_from_cache(halHandle,
15456 pAdapter->sessionId, pmksa->bssid,
15457 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015458 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015459 MAC_ADDR_ARRAY(pmksa->bssid));
15460 status = -EINVAL;
15461 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015462 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015463 return status;
15464}
15465
15466/**
15467 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15468 * @wiphy: Pointer to wiphy
15469 * @dev: Pointer to network device
15470 * @pmksa: Pointer to pmksa parameter
15471 *
15472 * Return: 0 for success, non-zero for failure
15473 */
15474static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15475 struct net_device *dev,
15476 struct cfg80211_pmksa *pmksa)
15477{
15478 int ret;
15479
15480 cds_ssr_protect(__func__);
15481 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15482 cds_ssr_unprotect(__func__);
15483
15484 return ret;
15485
15486}
15487
15488/**
15489 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15490 * @wiphy: Pointer to wiphy
15491 * @dev: Pointer to network device
15492 *
15493 * Return: 0 for success, non-zero for failure
15494 */
15495static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15496 struct net_device *dev)
15497{
15498 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15499 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15500 tHalHandle halHandle;
15501 int status = 0;
15502
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015503 ENTER();
15504
Anurag Chouhan6d760662016-02-20 16:05:43 +053015505 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015506 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015507 return -EINVAL;
15508 }
15509
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015510 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15511 hdd_err("invalid session id: %d", pAdapter->sessionId);
15512 return -EINVAL;
15513 }
15514
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015515 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015516
15517 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15518 status = wlan_hdd_validate_context(pHddCtx);
15519
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015520 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015521 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015522
15523 /* Retrieve halHandle */
15524 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15525
15526 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015527 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015528 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15529 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015530 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531 status = -EINVAL;
15532 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015533 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015534 return status;
15535}
15536
15537/**
15538 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15539 * @wiphy: Pointer to wiphy
15540 * @dev: Pointer to network device
15541 *
15542 * Return: 0 for success, non-zero for failure
15543 */
15544static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15545 struct net_device *dev)
15546{
15547 int ret;
15548
15549 cds_ssr_protect(__func__);
15550 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15551 cds_ssr_unprotect(__func__);
15552
15553 return ret;
15554}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015555
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015556#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557/**
15558 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15559 * @wiphy: Pointer to wiphy
15560 * @dev: Pointer to network device
15561 * @ftie: Pointer to fast transition ie parameter
15562 *
15563 * Return: 0 for success, non-zero for failure
15564 */
15565static int
15566__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15567 struct net_device *dev,
15568 struct cfg80211_update_ft_ies_params *ftie)
15569{
15570 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15571 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15572 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15573 int status;
15574
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015575 ENTER();
15576
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 status = wlan_hdd_validate_context(hdd_ctx);
15578 if (status)
15579 return status;
15580
Anurag Chouhan6d760662016-02-20 16:05:43 +053015581 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015582 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015583 return -EINVAL;
15584 }
15585
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015586 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15587 hdd_err("invalid session id: %d", pAdapter->sessionId);
15588 return -EINVAL;
15589 }
15590
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015591 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15593 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15594 /* Added for debug on reception of Re-assoc Req. */
15595 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015596 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015598 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015599 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015600 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015602
15603 /* Pass the received FT IEs to SME */
15604 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15605 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015606 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015607 return 0;
15608}
15609
15610/**
15611 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15612 * @wiphy: Pointer to wiphy
15613 * @dev: Pointer to network device
15614 * @ftie: Pointer to fast transition ie parameter
15615 *
15616 * Return: 0 for success, non-zero for failure
15617 */
15618static int
15619wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15620 struct net_device *dev,
15621 struct cfg80211_update_ft_ies_params *ftie)
15622{
15623 int ret;
15624
15625 cds_ssr_protect(__func__);
15626 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15627 cds_ssr_unprotect(__func__);
15628
15629 return ret;
15630}
15631#endif
15632
15633#ifdef WLAN_FEATURE_GTK_OFFLOAD
15634/**
15635 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
15636 * @callbackContext: Callback context
15637 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
15638 *
15639 * Callback rountine called upon receiving response for get offload info
15640 *
15641 * Return: none
15642 */
15643void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
15644 tpSirGtkOffloadGetInfoRspParams
15645 pGtkOffloadGetInfoRsp)
15646{
15647 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
15648 uint8_t tempReplayCounter[8];
15649 hdd_station_ctx_t *pHddStaCtx;
15650
15651 ENTER();
15652
15653 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015654 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015655 return;
15656 }
15657
15658 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015659 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660 return;
15661 }
15662
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015663 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015664 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015665 return;
15666 }
15667
15668 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15669 /* Update replay counter */
15670 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
15671 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15672
15673 {
15674 /* changing from little to big endian since supplicant
15675 * works on big endian format
15676 */
15677 int i;
15678 uint8_t *p =
15679 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15680
15681 for (i = 0; i < 8; i++) {
15682 tempReplayCounter[7 - i] = (uint8_t) p[i];
15683 }
15684 }
15685
15686 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015687 cfg80211_gtk_rekey_notify(pAdapter->dev,
15688 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015689 tempReplayCounter, GFP_KERNEL);
15690}
15691
15692/**
15693 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15694 * @wiphy: Pointer to wiphy
15695 * @dev: Pointer to network device
15696 * @data: Pointer to rekey data
15697 *
15698 * This function is used to offload GTK rekeying job to the firmware.
15699 *
15700 * Return: 0 for success, non-zero for failure
15701 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015702static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15704 struct net_device *dev,
15705 struct cfg80211_gtk_rekey_data *data)
15706{
15707 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15708 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15709 hdd_station_ctx_t *pHddStaCtx;
15710 tHalHandle hHal;
15711 int result;
15712 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015713 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015714
15715 ENTER();
15716
Anurag Chouhan6d760662016-02-20 16:05:43 +053015717 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015718 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719 return -EINVAL;
15720 }
15721
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015722 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15723 hdd_err("invalid session id: %d", pAdapter->sessionId);
15724 return -EINVAL;
15725 }
15726
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015727 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15729 pAdapter->sessionId, pAdapter->device_mode));
15730
15731 result = wlan_hdd_validate_context(pHddCtx);
15732
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015733 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735
15736 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15737 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15738 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015739 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015740 return -EAGAIN;
15741 }
15742
15743 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
15744 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
15745 NL80211_KCK_LEN);
15746 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
15747 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053015748 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015749 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015750 {
15751 /* changing from big to little endian since driver
15752 * works on little endian format
15753 */
15754 uint8_t *p =
15755 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
15756 ullKeyReplayCounter;
15757 int i;
15758
15759 for (i = 0; i < 8; i++) {
15760 p[7 - i] = data->replay_ctr[i];
15761 }
15762 }
15763
15764 if (true == pHddCtx->hdd_wlan_suspended) {
15765 /* if wlan is suspended, enable GTK offload directly from here */
15766 memcpy(&hddGtkOffloadReqParams,
15767 &pHddStaCtx->gtkOffloadReqParams,
15768 sizeof(tSirGtkOffloadParams));
15769 status =
15770 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
15771 pAdapter->sessionId);
15772
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015773 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015774 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775 status);
15776 return -EINVAL;
15777 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015778 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015779 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015780 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015782 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015783 return result;
15784}
15785
15786/**
15787 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15788 * @wiphy: Pointer to wiphy
15789 * @dev: Pointer to network device
15790 * @data: Pointer to rekey data
15791 *
15792 * This function is used to offload GTK rekeying job to the firmware.
15793 *
15794 * Return: 0 for success, non-zero for failure
15795 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015796static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015797int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15798 struct net_device *dev,
15799 struct cfg80211_gtk_rekey_data *data)
15800{
15801 int ret;
15802
15803 cds_ssr_protect(__func__);
15804 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15805 cds_ssr_unprotect(__func__);
15806
15807 return ret;
15808}
15809#endif /*WLAN_FEATURE_GTK_OFFLOAD */
15810
15811/**
15812 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15813 * @wiphy: Pointer to wiphy
15814 * @dev: Pointer to network device
15815 * @param: Pointer to access control parameter
15816 *
15817 * Return: 0 for success, non-zero for failure
15818 */
15819static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15820 struct net_device *dev,
15821 const struct cfg80211_acl_data *params)
15822{
15823 int i;
15824 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15825 hdd_hostapd_state_t *pHostapdState;
15826 tsap_Config_t *pConfig;
15827 v_CONTEXT_t p_cds_context = NULL;
15828 hdd_context_t *pHddCtx;
15829 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015830 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015831
15832 ENTER();
15833
Anurag Chouhan6d760662016-02-20 16:05:43 +053015834 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015835 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836 return -EINVAL;
15837 }
15838
15839 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015840 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015841 return -EINVAL;
15842 }
15843
15844 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15845 status = wlan_hdd_validate_context(pHddCtx);
15846
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015847 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015848 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849
15850 p_cds_context = pHddCtx->pcds_context;
15851 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15852
15853 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015854 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015855 return -EINVAL;
15856 }
15857
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015858 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015859 params->n_acl_entries);
15860
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015861 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015862 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15863 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015864 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015865 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15866
15867 /* default value */
15868 pConfig->num_accept_mac = 0;
15869 pConfig->num_deny_mac = 0;
15870
15871 /**
15872 * access control policy
15873 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15874 * listed in hostapd.deny file.
15875 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15876 * listed in hostapd.accept file.
15877 */
15878 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15879 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15880 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15881 params->acl_policy) {
15882 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15883 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015884 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015885 params->acl_policy);
15886 return -ENOTSUPP;
15887 }
15888
15889 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15890 pConfig->num_accept_mac = params->n_acl_entries;
15891 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015892 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15893 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894 MAC_ADDR_ARRAY(
15895 params->mac_addrs[i].addr));
15896
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015897 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015898 params->mac_addrs[i].addr,
15899 sizeof(qcmacaddr));
15900 }
15901 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15902 pConfig->num_deny_mac = params->n_acl_entries;
15903 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015904 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15905 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015906 MAC_ADDR_ARRAY(
15907 params->mac_addrs[i].addr));
15908
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015909 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910 params->mac_addrs[i].addr,
15911 sizeof(qcmacaddr));
15912 }
15913 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015914 qdf_status = wlansap_set_mac_acl(
15915 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015916 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015917 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015918 return -EINVAL;
15919 }
15920 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015921 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922 hdd_device_mode_to_string(pAdapter->device_mode),
15923 pAdapter->device_mode);
15924 return -EINVAL;
15925 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015926 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927 return 0;
15928}
15929
15930/**
15931 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15932 * __wlan_hdd_cfg80211_set_mac_acl
15933 * @wiphy: pointer to wiphy structure
15934 * @dev: pointer to net_device
15935 * @params: pointer to cfg80211_acl_data
15936 *
15937 * Return; 0 on success, error number otherwise
15938 */
15939static int
15940wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15941 struct net_device *dev,
15942 const struct cfg80211_acl_data *params)
15943{
15944 int ret;
15945
15946 cds_ssr_protect(__func__);
15947 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15948 cds_ssr_unprotect(__func__);
15949
15950 return ret;
15951}
15952
15953#ifdef WLAN_NL80211_TESTMODE
15954#ifdef FEATURE_WLAN_LPHB
15955/**
15956 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15957 * @pHddCtx: Pointer to hdd context
15958 * @lphbInd: Pointer to low power heart beat indication parameter
15959 *
15960 * Return: none
15961 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015962static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15963 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015964{
15965 struct sk_buff *skb;
15966
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015967 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015968
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015969 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015970 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015971
15972 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015973 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015974 return;
15975 }
15976
15977 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15978 wiphy, sizeof(tSirLPHBInd),
15979 GFP_ATOMIC);
15980 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015981 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 return;
15983 }
15984
15985 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015986 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015987 goto nla_put_failure;
15988 }
15989 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015990 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015991 goto nla_put_failure;
15992 }
15993 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015994 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015995 goto nla_put_failure;
15996 }
15997 cfg80211_testmode_event(skb, GFP_ATOMIC);
15998 return;
15999
16000nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016001 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016002 kfree_skb(skb);
16003
16004 return;
16005}
16006#endif /* FEATURE_WLAN_LPHB */
16007
16008/**
16009 * __wlan_hdd_cfg80211_testmode() - test mode
16010 * @wiphy: Pointer to wiphy
16011 * @data: Data pointer
16012 * @len: Data length
16013 *
16014 * Return: 0 for success, non-zero for failure
16015 */
16016static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16017 void *data, int len)
16018{
16019 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16020 int err;
16021 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16022
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016023 ENTER();
16024
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016025 err = wlan_hdd_validate_context(pHddCtx);
16026 if (err)
16027 return err;
16028
16029 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16030 len, wlan_hdd_tm_policy);
16031 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016032 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 return err;
16034 }
16035
16036 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016037 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016038 return -EINVAL;
16039 }
16040
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016041 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016042 TRACE_CODE_HDD_CFG80211_TESTMODE,
16043 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016044 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16045#ifdef FEATURE_WLAN_LPHB
16046 /* Low Power Heartbeat configuration request */
16047 case WLAN_HDD_TM_CMD_WLAN_HB:
16048 {
16049 int buf_len;
16050 void *buf;
16051 tSirLPHBReq *hb_params = NULL;
16052 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016053 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016054
16055 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016056 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 return -EINVAL;
16058 }
16059
16060 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16061 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16062
16063 hb_params_temp = (tSirLPHBReq *) buf;
16064 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16065 && (hb_params_temp->params.lphbTcpParamReq.
16066 timePeriodSec == 0))
16067 return -EINVAL;
16068
16069 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016070 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016071 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016072 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016073 return -ENOMEM;
16074 }
16075
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016076 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016077 smeStatus =
16078 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16079 hb_params,
16080 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016081 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016082 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016083 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016084 }
16085 return 0;
16086 }
16087#endif /* FEATURE_WLAN_LPHB */
16088
16089#if defined(QCA_WIFI_FTM)
16090 case WLAN_HDD_TM_CMD_WLAN_FTM:
16091 {
16092 int buf_len;
16093 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016094 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016095 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016096 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016097 return -EINVAL;
16098 }
16099
16100 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16101 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16102
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016103 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016104
16105 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16106
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016107 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016108 err = -EBUSY;
16109 break;
16110 }
16111#endif
16112
16113 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016114 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16116 return -EOPNOTSUPP;
16117 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016118 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119 return err;
16120}
16121
16122/**
16123 * wlan_hdd_cfg80211_testmode() - test mode
16124 * @wiphy: Pointer to wiphy
16125 * @dev: Pointer to network device
16126 * @data: Data pointer
16127 * @len: Data length
16128 *
16129 * Return: 0 for success, non-zero for failure
16130 */
16131static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16132#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16133 struct wireless_dev *wdev,
16134#endif
16135 void *data, int len)
16136{
16137 int ret;
16138
16139 cds_ssr_protect(__func__);
16140 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16141 cds_ssr_unprotect(__func__);
16142
16143 return ret;
16144}
16145
16146#if defined(QCA_WIFI_FTM)
16147/**
16148 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16149 * @buf: Pointer to buffer
16150 * @buf_len: Buffer length
16151 *
16152 * Return: none
16153 */
16154void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16155{
16156 struct sk_buff *skb;
16157 hdd_context_t *hdd_ctx;
16158
16159 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016160 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161 return;
16162 }
16163
Anurag Chouhan6d760662016-02-20 16:05:43 +053016164 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016165 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016166 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167 return;
16168 }
16169
16170 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16171 buf_len, GFP_KERNEL);
16172 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016173 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174 return;
16175 }
16176
16177 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16178 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16179 goto nla_put_failure;
16180
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016181 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016182
16183 cfg80211_testmode_event(skb, GFP_KERNEL);
16184 return;
16185
16186nla_put_failure:
16187 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016188 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016189}
16190#endif
16191#endif /* CONFIG_NL80211_TESTMODE */
16192
16193#ifdef QCA_HT_2040_COEX
16194/**
16195 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16196 * @wiphy: Pointer to wiphy
16197 * @dev: Pointer to network device
16198 * @chandef: Pointer to channel definition parameter
16199 *
16200 * Return: 0 for success, non-zero for failure
16201 */
16202static int
16203__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16204 struct net_device *dev,
16205 struct cfg80211_chan_def *chandef)
16206{
16207 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16208 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016209 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016211 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016212
Anurag Chouhan6d760662016-02-20 16:05:43 +053016213 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016214 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016215 return -EINVAL;
16216 }
16217
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016218 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16219 hdd_err("invalid session id: %d", pAdapter->sessionId);
16220 return -EINVAL;
16221 }
16222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16224 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016225 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016228 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016229 sme_get_config_param(pHddCtx->hHal, &sme_config);
16230 switch (chandef->width) {
16231 case NL80211_CHAN_WIDTH_20:
16232 if (sme_config.csrConfig.channelBondingMode24GHz !=
16233 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16234 sme_config.csrConfig.channelBondingMode24GHz =
16235 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16236 sme_update_config(pHddCtx->hHal, &sme_config);
16237 cbModeChange = true;
16238 }
16239 break;
16240
16241 case NL80211_CHAN_WIDTH_40:
16242 if (sme_config.csrConfig.channelBondingMode24GHz ==
16243 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16244 if (NL80211_CHAN_HT40MINUS ==
16245 cfg80211_get_chandef_type(chandef))
16246 sme_config.csrConfig.channelBondingMode24GHz =
16247 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16248 else
16249 sme_config.csrConfig.channelBondingMode24GHz =
16250 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16251 sme_update_config(pHddCtx->hHal, &sme_config);
16252 cbModeChange = true;
16253 }
16254 break;
16255
16256 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016257 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016258 return -EINVAL;
16259 }
16260
16261 if (!cbModeChange)
16262 return 0;
16263
Krunal Sonib4326f22016-03-10 13:05:51 -080016264 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016265 return 0;
16266
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016267 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268 sme_config.csrConfig.channelBondingMode24GHz);
16269
16270 /* Change SAP ht2040 mode */
16271 status = hdd_set_sap_ht2040_mode(pAdapter,
16272 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016273 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016274 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275 return -EINVAL;
16276 }
16277
16278 return 0;
16279}
16280
16281/**
16282 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16283 * @wiphy: Pointer to wiphy
16284 * @dev: Pointer to network device
16285 * @chandef: Pointer to channel definition parameter
16286 *
16287 * Return: 0 for success, non-zero for failure
16288 */
16289static int
16290wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16291 struct net_device *dev,
16292 struct cfg80211_chan_def *chandef)
16293{
16294 int ret;
16295
16296 cds_ssr_protect(__func__);
16297 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16298 cds_ssr_unprotect(__func__);
16299
16300 return ret;
16301}
16302#endif
16303
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016304#ifdef CHANNEL_SWITCH_SUPPORTED
16305/**
16306 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16307 * channel in SAP/GO
16308 * @wiphy: wiphy pointer
16309 * @dev: dev pointer.
16310 * @csa_params: Change channel params
16311 *
16312 * This function is called to switch channel in SAP/GO
16313 *
16314 * Return: 0 if success else return non zero
16315 */
16316static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16317 struct net_device *dev,
16318 struct cfg80211_csa_settings *csa_params)
16319{
16320 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16321 hdd_context_t *hdd_ctx;
16322 uint8_t channel;
16323 uint16_t freq;
16324 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016325 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016326
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016327 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016328 csa_params->chandef.chan->center_freq);
16329
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016330 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16331 hdd_err("invalid session id: %d", adapter->sessionId);
16332 return -EINVAL;
16333 }
16334
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016335 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16336 ret = wlan_hdd_validate_context(hdd_ctx);
16337
16338 if (0 != ret)
16339 return ret;
16340
Krunal Sonib4326f22016-03-10 13:05:51 -080016341 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16342 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016343 return -ENOTSUPP;
16344
16345 freq = csa_params->chandef.chan->center_freq;
16346 channel = cds_freq_to_chan(freq);
16347
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016348 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16349
16350 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016351 return ret;
16352}
16353
16354/**
16355 * wlan_hdd_cfg80211_channel_switch()- function to switch
16356 * channel in SAP/GO
16357 * @wiphy: wiphy pointer
16358 * @dev: dev pointer.
16359 * @csa_params: Change channel params
16360 *
16361 * This function is called to switch channel in SAP/GO
16362 *
16363 * Return: 0 if success else return non zero
16364 */
16365static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16366 struct net_device *dev,
16367 struct cfg80211_csa_settings *csa_params)
16368{
16369 int ret;
16370
16371 cds_ssr_protect(__func__);
16372 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16373 cds_ssr_unprotect(__func__);
16374 return ret;
16375}
16376#endif
16377
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016378/**
16379 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16380 * translation from NL to policy manager type
16381 * @type: Generic connection mode type defined in NL
16382 *
16383 *
16384 * This function provides the type translation
16385 *
16386 * Return: cds_con_mode enum
16387 */
16388enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16389 enum nl80211_iftype type)
16390{
16391 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16392 switch (type) {
16393 case NL80211_IFTYPE_STATION:
16394 mode = CDS_STA_MODE;
16395 break;
16396 case NL80211_IFTYPE_P2P_CLIENT:
16397 mode = CDS_P2P_CLIENT_MODE;
16398 break;
16399 case NL80211_IFTYPE_P2P_GO:
16400 mode = CDS_P2P_GO_MODE;
16401 break;
16402 case NL80211_IFTYPE_AP:
16403 mode = CDS_SAP_MODE;
16404 break;
16405 case NL80211_IFTYPE_ADHOC:
16406 mode = CDS_IBSS_MODE;
16407 break;
16408 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016409 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016410 type);
16411 }
16412 return mode;
16413}
16414
16415/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016416 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16417 * @wiphy: Handle to struct wiphy to get handle to module context.
16418 * @chandef: Contains information about the capture channel to be set.
16419 *
16420 * This interface is called if and only if monitor mode interface alone is
16421 * active.
16422 *
16423 * Return: 0 success or error code on failure.
16424 */
16425static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16426 struct cfg80211_chan_def *chandef)
16427{
16428 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16429 hdd_adapter_t *adapter;
16430 hdd_station_ctx_t *sta_ctx;
16431 struct hdd_mon_set_ch_info *ch_info;
16432 QDF_STATUS status;
16433 tHalHandle hal_hdl;
16434 struct qdf_mac_addr bssid;
16435 tCsrRoamProfile roam_profile;
16436 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016437 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016438 int ret;
16439 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16440
16441 ENTER();
16442
16443 ret = wlan_hdd_validate_context(hdd_ctx);
16444 if (ret)
16445 return ret;
16446
16447 hal_hdl = hdd_ctx->hHal;
16448
16449 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16450 if (!adapter)
16451 return -EIO;
16452
16453 hdd_info("%s: set monitor mode Channel %d and freq %d",
16454 adapter->dev->name, chan_num, chandef->chan->center_freq);
16455
16456 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16457 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016458 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16459 roam_profile.ChannelInfo.numOfChannels = 1;
16460 roam_profile.phyMode = ch_info->phy_mode;
16461 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016462 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016463
16464 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16465 QDF_MAC_ADDR_SIZE);
16466
16467 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016468 /*
16469 * CDS api expects secondary channel for calculating
16470 * the channel params
16471 */
16472 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16473 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16474 if (chan_num >= 1 && chan_num <= 5)
16475 sec_ch = chan_num + 4;
16476 else if (chan_num >= 6 && chan_num <= 13)
16477 sec_ch = chan_num - 4;
16478 }
16479 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016480 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16481 &roam_profile);
16482 if (status) {
16483 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16484 status);
16485 ret = qdf_status_to_os_return(status);
16486 return ret;
16487 }
16488 EXIT();
16489 return 0;
16490}
16491
16492/**
16493 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16494 * @wiphy: Handle to struct wiphy to get handle to module context.
16495 * @chandef: Contains information about the capture channel to be set.
16496 *
16497 * This interface is called if and only if monitor mode interface alone is
16498 * active.
16499 *
16500 * Return: 0 success or error code on failure.
16501 */
16502static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16503 struct cfg80211_chan_def *chandef)
16504{
16505 int ret;
16506
16507 cds_ssr_protect(__func__);
16508 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16509 cds_ssr_unprotect(__func__);
16510 return ret;
16511}
16512
16513/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016514 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16515 * @adapter: pointer to adapter
16516 *
16517 * Wrapper function to clear link layer stats.
16518 * return - void
16519 */
16520void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16521{
16522 tSirLLStatsClearReq link_layer_stats_clear_req;
16523 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16524
Mukul Sharma491021c2016-09-29 21:39:19 +053016525 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16526 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016527 link_layer_stats_clear_req.stopReq = 0;
16528 link_layer_stats_clear_req.reqId = 1;
16529 link_layer_stats_clear_req.staId = adapter->sessionId;
16530 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16531
16532 return;
16533}
16534
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016535#define CNT_DIFF(cur, prev) \
16536 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16537#define MAX_COUNT 0xffffffff
16538static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16539 struct scan_chan_info *chan,
16540 struct scan_chan_info *info, uint32_t cmd_flag)
16541{
16542 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16543 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16544 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16545
16546 mutex_lock(&hdd_ctx->chan_info_lock);
16547
16548 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16549 qdf_mem_zero(chan, sizeof(*chan));
16550
16551 chan->freq = info->freq;
16552 chan->noise_floor = info->noise_floor;
16553 chan->clock_freq = info->clock_freq;
16554 chan->cmd_flag = info->cmd_flag;
16555 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16556
16557 chan->rx_clear_count =
16558 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16559
16560 chan->tx_frame_count =
16561 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16562
16563 mutex_unlock(&hdd_ctx->chan_info_lock);
16564
16565}
16566#undef CNT_DIFF
16567#undef MAX_COUNT
16568
16569/**
16570 * wlan_hdd_chan_info_cb() - channel info callback
16571 * @chan_info: struct scan_chan_info
16572 *
16573 * Store channel info into HDD context
16574 *
16575 * Return: None.
16576 */
16577static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16578{
16579 hdd_context_t *hdd_ctx;
16580 struct scan_chan_info *chan;
16581 uint8_t idx;
16582
16583 ENTER();
16584
16585 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16586 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16587 hdd_err("hdd_ctx is invalid");
16588 return;
16589 }
16590
16591 if (!hdd_ctx->chan_info) {
16592 hdd_err("chan_info is NULL");
16593 return;
16594 }
16595
16596 chan = hdd_ctx->chan_info;
16597 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16598 if (chan[idx].freq == info->freq) {
16599 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16600 info->cmd_flag);
16601 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16602 chan[idx].cmd_flag, chan[idx].freq,
16603 chan[idx].noise_floor,
16604 chan[idx].cycle_count, chan[idx].rx_clear_count,
16605 chan[idx].clock_freq, chan[idx].cmd_flag,
16606 chan[idx].tx_frame_count, idx);
16607 if (chan[idx].freq == 0)
16608 break;
16609
16610 }
16611 }
16612
16613 EXIT();
16614}
16615
16616/**
16617 * wlan_hdd_init_chan_info() - init chan info in hdd context
16618 * @hdd_ctx: HDD context pointer
16619 *
16620 * Return: none
16621 */
16622void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16623{
16624 uint8_t num_2g, num_5g, index = 0;
16625
16626 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16627 hdd_info("SNR monitoring is disabled");
16628 return;
16629 }
16630
16631 hdd_ctx->chan_info =
16632 qdf_mem_malloc(sizeof(struct scan_chan_info)
16633 * QDF_MAX_NUM_CHAN);
16634 if (hdd_ctx->chan_info == NULL) {
16635 hdd_err("Failed to malloc for chan info");
16636 return;
16637 }
16638 mutex_init(&hdd_ctx->chan_info_lock);
16639
16640 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16641 for (; index < num_2g; index++) {
16642 hdd_ctx->chan_info[index].freq =
16643 hdd_channels_2_4_ghz[index].center_freq;
16644 }
16645
16646 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16647 for (; (index - num_2g) < num_5g; index++) {
16648 if (cds_is_dsrc_channel(
16649 hdd_channels_5_ghz[index - num_2g].center_freq))
16650 continue;
16651 hdd_ctx->chan_info[index].freq =
16652 hdd_channels_5_ghz[index - num_2g].center_freq;
16653 }
16654 sme_set_chan_info_callback(hdd_ctx->hHal,
16655 &wlan_hdd_chan_info_cb);
16656}
16657
16658/**
16659 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16660 * @hdd_ctx: hdd context pointer
16661 *
16662 * Return: none
16663 */
16664void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16665{
16666 struct scan_chan_info *chan;
16667
16668 chan = hdd_ctx->chan_info;
16669 hdd_ctx->chan_info = NULL;
16670 if (chan)
16671 qdf_mem_free(chan);
16672}
16673
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016674/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016675 * struct cfg80211_ops - cfg80211_ops
16676 *
16677 * @add_virtual_intf: Add virtual interface
16678 * @del_virtual_intf: Delete virtual interface
16679 * @change_virtual_intf: Change virtual interface
16680 * @change_station: Change station
16681 * @add_beacon: Add beacon in sap mode
16682 * @del_beacon: Delete beacon in sap mode
16683 * @set_beacon: Set beacon in sap mode
16684 * @start_ap: Start ap
16685 * @change_beacon: Change beacon
16686 * @stop_ap: Stop ap
16687 * @change_bss: Change bss
16688 * @add_key: Add key
16689 * @get_key: Get key
16690 * @del_key: Delete key
16691 * @set_default_key: Set default key
16692 * @set_channel: Set channel
16693 * @scan: Scan
16694 * @connect: Connect
16695 * @disconnect: Disconnect
16696 * @join_ibss = Join ibss
16697 * @leave_ibss = Leave ibss
16698 * @set_wiphy_params = Set wiphy params
16699 * @set_tx_power = Set tx power
16700 * @get_tx_power = get tx power
16701 * @remain_on_channel = Remain on channel
16702 * @cancel_remain_on_channel = Cancel remain on channel
16703 * @mgmt_tx = Tx management frame
16704 * @mgmt_tx_cancel_wait = Cancel management tx wait
16705 * @set_default_mgmt_key = Set default management key
16706 * @set_txq_params = Set tx queue parameters
16707 * @get_station = Get station
16708 * @set_power_mgmt = Set power management
16709 * @del_station = Delete station
16710 * @add_station = Add station
16711 * @set_pmksa = Set pmksa
16712 * @del_pmksa = Delete pmksa
16713 * @flush_pmksa = Flush pmksa
16714 * @update_ft_ies = Update FT IEs
16715 * @tdls_mgmt = Tdls management
16716 * @tdls_oper = Tdls operation
16717 * @set_rekey_data = Set rekey data
16718 * @sched_scan_start = Scheduled scan start
16719 * @sched_scan_stop = Scheduled scan stop
16720 * @resume = Resume wlan
16721 * @suspend = Suspend wlan
16722 * @set_mac_acl = Set mac acl
16723 * @testmode_cmd = Test mode command
16724 * @set_ap_chanwidth = Set AP channel bandwidth
16725 * @dump_survey = Dump survey
16726 * @key_mgmt_set_pmk = Set pmk key management
16727 */
16728static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16729 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16730 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16731 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16732 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016733 .start_ap = wlan_hdd_cfg80211_start_ap,
16734 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16735 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016736 .change_bss = wlan_hdd_cfg80211_change_bss,
16737 .add_key = wlan_hdd_cfg80211_add_key,
16738 .get_key = wlan_hdd_cfg80211_get_key,
16739 .del_key = wlan_hdd_cfg80211_del_key,
16740 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16741 .scan = wlan_hdd_cfg80211_scan,
16742 .connect = wlan_hdd_cfg80211_connect,
16743 .disconnect = wlan_hdd_cfg80211_disconnect,
16744 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16745 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16746 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16747 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16748 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16749 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16750 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16751 .mgmt_tx = wlan_hdd_mgmt_tx,
16752 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16753 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16754 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016755 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016756 .get_station = wlan_hdd_cfg80211_get_station,
16757 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16758 .del_station = wlan_hdd_cfg80211_del_station,
16759 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016760 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16761 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16762 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016763#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016764 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16765#endif
16766#ifdef FEATURE_WLAN_TDLS
16767 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16768 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16769#endif
16770#ifdef WLAN_FEATURE_GTK_OFFLOAD
16771 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16772#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16773#ifdef FEATURE_WLAN_SCAN_PNO
16774 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16775 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16776#endif /*FEATURE_WLAN_SCAN_PNO */
16777 .resume = wlan_hdd_cfg80211_resume_wlan,
16778 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16779 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16780#ifdef WLAN_NL80211_TESTMODE
16781 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16782#endif
16783#ifdef QCA_HT_2040_COEX
16784 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16785#endif
16786 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016787#ifdef CHANNEL_SWITCH_SUPPORTED
16788 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16789#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016790 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016791#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16792 defined(CFG80211_ABORT_SCAN)
16793 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16794#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016795};