blob: 633913b23846620590845e1d13d60c71ceaf60da [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
Ravi Joshideb5a8d2015-11-09 19:11:43 -080096#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053097#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070098#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070099#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530100#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800101
Leo Changfdb45c32016-10-28 11:09:23 -0700102#include <cdp_txrx_cmn.h>
103#include <cdp_txrx_misc.h>
104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define g_mode_rates_size (12)
106#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
108 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
109
110/*
111 * Android CTS verifier needs atleast this much wait time (in msec)
112 */
113#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
114
115/*
116 * Refer @tCfgProtection structure for definition of the bit map.
117 * below value is obtained by setting the following bit-fields.
118 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
119 */
120#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
121
122#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700123 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 .center_freq = (freq), \
125 .hw_value = (chan), \
126 .flags = (flag), \
127 .max_antenna_gain = 0, \
128 .max_power = 30, \
129}
130
131#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
137 .max_power = 30, \
138}
139
140#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
141 { \
142 .bitrate = rate, \
143 .hw_value = rate_id, \
144 .flags = flag, \
145 }
146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
148#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
150#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
Agrawal Ashish65634612016-08-18 13:24:32 +0530152#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
153 mode <= DFS_MODE_DEPRIORITIZE))
154#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
155 || (channel >= 36 && channel <= 184))
156
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530158#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160static const u32 hdd_cipher_suites[] = {
161 WLAN_CIPHER_SUITE_WEP40,
162 WLAN_CIPHER_SUITE_WEP104,
163 WLAN_CIPHER_SUITE_TKIP,
164#ifdef FEATURE_WLAN_ESE
165#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
166#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
167 WLAN_CIPHER_SUITE_BTK,
168 WLAN_CIPHER_SUITE_KRK,
169 WLAN_CIPHER_SUITE_CCMP,
170#else
171 WLAN_CIPHER_SUITE_CCMP,
172#endif
173#ifdef FEATURE_WLAN_WAPI
174 WLAN_CIPHER_SUITE_SMS4,
175#endif
176#ifdef WLAN_FEATURE_11W
177 WLAN_CIPHER_SUITE_AES_CMAC,
178#endif
179};
180
Abhishek Singhf512bf32016-05-04 16:47:46 +0530181static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 HDD2GHZCHAN(2412, 1, 0),
183 HDD2GHZCHAN(2417, 2, 0),
184 HDD2GHZCHAN(2422, 3, 0),
185 HDD2GHZCHAN(2427, 4, 0),
186 HDD2GHZCHAN(2432, 5, 0),
187 HDD2GHZCHAN(2437, 6, 0),
188 HDD2GHZCHAN(2442, 7, 0),
189 HDD2GHZCHAN(2447, 8, 0),
190 HDD2GHZCHAN(2452, 9, 0),
191 HDD2GHZCHAN(2457, 10, 0),
192 HDD2GHZCHAN(2462, 11, 0),
193 HDD2GHZCHAN(2467, 12, 0),
194 HDD2GHZCHAN(2472, 13, 0),
195 HDD2GHZCHAN(2484, 14, 0),
196};
197
Abhishek Singhf512bf32016-05-04 16:47:46 +0530198static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 HDD5GHZCHAN(5180, 36, 0),
200 HDD5GHZCHAN(5200, 40, 0),
201 HDD5GHZCHAN(5220, 44, 0),
202 HDD5GHZCHAN(5240, 48, 0),
203 HDD5GHZCHAN(5260, 52, 0),
204 HDD5GHZCHAN(5280, 56, 0),
205 HDD5GHZCHAN(5300, 60, 0),
206 HDD5GHZCHAN(5320, 64, 0),
207 HDD5GHZCHAN(5500, 100, 0),
208 HDD5GHZCHAN(5520, 104, 0),
209 HDD5GHZCHAN(5540, 108, 0),
210 HDD5GHZCHAN(5560, 112, 0),
211 HDD5GHZCHAN(5580, 116, 0),
212 HDD5GHZCHAN(5600, 120, 0),
213 HDD5GHZCHAN(5620, 124, 0),
214 HDD5GHZCHAN(5640, 128, 0),
215 HDD5GHZCHAN(5660, 132, 0),
216 HDD5GHZCHAN(5680, 136, 0),
217 HDD5GHZCHAN(5700, 140, 0),
218 HDD5GHZCHAN(5720, 144, 0),
219 HDD5GHZCHAN(5745, 149, 0),
220 HDD5GHZCHAN(5765, 153, 0),
221 HDD5GHZCHAN(5785, 157, 0),
222 HDD5GHZCHAN(5805, 161, 0),
223 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 HDD5GHZCHAN(5852, 170, 0),
225 HDD5GHZCHAN(5855, 171, 0),
226 HDD5GHZCHAN(5860, 172, 0),
227 HDD5GHZCHAN(5865, 173, 0),
228 HDD5GHZCHAN(5870, 174, 0),
229 HDD5GHZCHAN(5875, 175, 0),
230 HDD5GHZCHAN(5880, 176, 0),
231 HDD5GHZCHAN(5885, 177, 0),
232 HDD5GHZCHAN(5890, 178, 0),
233 HDD5GHZCHAN(5895, 179, 0),
234 HDD5GHZCHAN(5900, 180, 0),
235 HDD5GHZCHAN(5905, 181, 0),
236 HDD5GHZCHAN(5910, 182, 0),
237 HDD5GHZCHAN(5915, 183, 0),
238 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239};
240
241static struct ieee80211_rate g_mode_rates[] = {
242 HDD_G_MODE_RATETAB(10, 0x1, 0),
243 HDD_G_MODE_RATETAB(20, 0x2, 0),
244 HDD_G_MODE_RATETAB(55, 0x4, 0),
245 HDD_G_MODE_RATETAB(110, 0x8, 0),
246 HDD_G_MODE_RATETAB(60, 0x10, 0),
247 HDD_G_MODE_RATETAB(90, 0x20, 0),
248 HDD_G_MODE_RATETAB(120, 0x40, 0),
249 HDD_G_MODE_RATETAB(180, 0x80, 0),
250 HDD_G_MODE_RATETAB(240, 0x100, 0),
251 HDD_G_MODE_RATETAB(360, 0x200, 0),
252 HDD_G_MODE_RATETAB(480, 0x400, 0),
253 HDD_G_MODE_RATETAB(540, 0x800, 0),
254};
255
256static struct ieee80211_rate a_mode_rates[] = {
257 HDD_G_MODE_RATETAB(60, 0x10, 0),
258 HDD_G_MODE_RATETAB(90, 0x20, 0),
259 HDD_G_MODE_RATETAB(120, 0x40, 0),
260 HDD_G_MODE_RATETAB(180, 0x80, 0),
261 HDD_G_MODE_RATETAB(240, 0x100, 0),
262 HDD_G_MODE_RATETAB(360, 0x200, 0),
263 HDD_G_MODE_RATETAB(480, 0x400, 0),
264 HDD_G_MODE_RATETAB(540, 0x800, 0),
265};
266
267static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530268 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700270 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
278 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
279 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
280 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
281 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
282 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
283 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
284};
285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530287 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700289 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290 .bitrates = a_mode_rates,
291 .n_bitrates = a_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
297 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
298 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
299 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
300 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
301 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
302 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
303 .vht_cap.vht_supported = 1,
304};
305
306/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800307 * TX/RX direction for each kind of interface
308 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309static const struct ieee80211_txrx_stypes
310 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
311 [NL80211_IFTYPE_STATION] = {
312 .tx = 0xffff,
313 .rx = BIT(SIR_MAC_MGMT_ACTION) |
314 BIT(SIR_MAC_MGMT_PROBE_REQ),
315 },
316 [NL80211_IFTYPE_AP] = {
317 .tx = 0xffff,
318 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
319 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_PROBE_REQ) |
321 BIT(SIR_MAC_MGMT_DISASSOC) |
322 BIT(SIR_MAC_MGMT_AUTH) |
323 BIT(SIR_MAC_MGMT_DEAUTH) |
324 BIT(SIR_MAC_MGMT_ACTION),
325 },
326 [NL80211_IFTYPE_ADHOC] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_P2P_CLIENT] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ACTION) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ),
340 },
341 [NL80211_IFTYPE_P2P_GO] = {
342 /* This is also same as for SoftAP */
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ) |
347 BIT(SIR_MAC_MGMT_DISASSOC) |
348 BIT(SIR_MAC_MGMT_AUTH) |
349 BIT(SIR_MAC_MGMT_DEAUTH) |
350 BIT(SIR_MAC_MGMT_ACTION),
351 },
352};
353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354/* Interface limits and combinations registered by the driver */
355
356/* STA ( + STA ) combination */
357static const struct ieee80211_iface_limit
358 wlan_hdd_sta_iface_limit[] = {
359 {
360 .max = 3, /* p2p0 is a STA as well */
361 .types = BIT(NL80211_IFTYPE_STATION),
362 },
363};
364
365/* ADHOC (IBSS) limit */
366static const struct ieee80211_iface_limit
367 wlan_hdd_adhoc_iface_limit[] = {
368 {
369 .max = 1,
370 .types = BIT(NL80211_IFTYPE_STATION),
371 },
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_ADHOC),
375 },
376};
377
378/* AP ( + AP ) combination */
379static const struct ieee80211_iface_limit
380 wlan_hdd_ap_iface_limit[] = {
381 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530382 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 .types = BIT(NL80211_IFTYPE_AP),
384 },
385};
386
387/* P2P limit */
388static const struct ieee80211_iface_limit
389 wlan_hdd_p2p_iface_limit[] = {
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
393 },
394 {
395 .max = 1,
396 .types = BIT(NL80211_IFTYPE_P2P_GO),
397 },
398};
399
400static const struct ieee80211_iface_limit
401 wlan_hdd_sta_ap_iface_limit[] = {
402 {
403 /* We need 1 extra STA interface for OBSS scan when SAP starts
404 * with HT40 in STA+SAP concurrency mode
405 */
406 .max = (1 + SAP_MAX_OBSS_STA_CNT),
407 .types = BIT(NL80211_IFTYPE_STATION),
408 },
409 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530410 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 .types = BIT(NL80211_IFTYPE_AP),
412 },
413};
414
415/* STA + P2P combination */
416static const struct ieee80211_iface_limit
417 wlan_hdd_sta_p2p_iface_limit[] = {
418 {
419 /* One reserved for dedicated P2PDEV usage */
420 .max = 2,
421 .types = BIT(NL80211_IFTYPE_STATION)
422 },
423 {
424 /* Support for two identical (GO + GO or CLI + CLI)
425 * or dissimilar (GO + CLI) P2P interfaces
426 */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
429 },
430};
431
432/* STA + AP + P2PGO combination */
433static const struct ieee80211_iface_limit
434wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
435 /* Support for AP+P2PGO interfaces */
436 {
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_STATION)
439 },
440 {
441 .max = 1,
442 .types = BIT(NL80211_IFTYPE_P2P_GO)
443 },
444 {
445 .max = 1,
446 .types = BIT(NL80211_IFTYPE_AP)
447 }
448};
449
450/* SAP + P2P combination */
451static const struct ieee80211_iface_limit
452wlan_hdd_sap_p2p_iface_limit[] = {
453 {
454 /* 1 dedicated for p2p0 which is a STA type */
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_STATION)
457 },
458 {
459 /* The p2p interface in SAP+P2P can be GO/CLI.
460 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
461 */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
464 },
465 {
466 /* SAP+GO to support only one SAP interface */
467 .max = 1,
468 .types = BIT(NL80211_IFTYPE_AP)
469 }
470};
471
472/* P2P + P2P combination */
473static const struct ieee80211_iface_limit
474wlan_hdd_p2p_p2p_iface_limit[] = {
475 {
476 /* 1 dedicated for p2p0 which is a STA type */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_STATION)
479 },
480 {
481 /* The p2p interface in P2P+P2P can be GO/CLI.
482 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
483 */
484 .max = 2,
485 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
486 },
487};
488
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700489static const struct ieee80211_iface_limit
490 wlan_hdd_mon_iface_limit[] = {
491 {
492 .max = 3, /* Monitor interface */
493 .types = BIT(NL80211_IFTYPE_MONITOR),
494 },
495};
496
497static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800498 wlan_hdd_iface_combination[] = {
499 /* STA */
500 {
501 .limits = wlan_hdd_sta_iface_limit,
502 .num_different_channels = 2,
503 .max_interfaces = 3,
504 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
505 },
506 /* ADHOC */
507 {
508 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700509 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 .max_interfaces = 2,
511 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
512 },
513 /* AP */
514 {
515 .limits = wlan_hdd_ap_iface_limit,
516 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530517 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
519 },
520 /* P2P */
521 {
522 .limits = wlan_hdd_p2p_iface_limit,
523 .num_different_channels = 2,
524 .max_interfaces = 2,
525 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
526 },
527 /* STA + AP */
528 {
529 .limits = wlan_hdd_sta_ap_iface_limit,
530 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
533 .beacon_int_infra_match = true,
534 },
535 /* STA + P2P */
536 {
537 .limits = wlan_hdd_sta_p2p_iface_limit,
538 .num_different_channels = 2,
539 /* one interface reserved for P2PDEV dedicated usage */
540 .max_interfaces = 4,
541 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
542 .beacon_int_infra_match = true,
543 },
544 /* STA + P2P GO + SAP */
545 {
546 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
547 /* we can allow 3 channels for three different persona
548 * but due to firmware limitation, allow max 2 concrnt channels.
549 */
550 .num_different_channels = 2,
551 /* one interface reserved for P2PDEV dedicated usage */
552 .max_interfaces = 4,
553 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
554 .beacon_int_infra_match = true,
555 },
556 /* SAP + P2P */
557 {
558 .limits = wlan_hdd_sap_p2p_iface_limit,
559 .num_different_channels = 2,
560 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
561 .max_interfaces = 3,
562 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
563 .beacon_int_infra_match = true,
564 },
565 /* P2P + P2P */
566 {
567 .limits = wlan_hdd_p2p_p2p_iface_limit,
568 .num_different_channels = 2,
569 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
570 .max_interfaces = 3,
571 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
572 .beacon_int_infra_match = true,
573 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530574 /* Monitor */
575 {
576 .limits = wlan_hdd_mon_iface_limit,
577 .max_interfaces = 3,
578 .num_different_channels = 2,
579 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
580 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530584struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586#ifdef WLAN_NL80211_TESTMODE
587enum wlan_hdd_tm_attr {
588 WLAN_HDD_TM_ATTR_INVALID = 0,
589 WLAN_HDD_TM_ATTR_CMD = 1,
590 WLAN_HDD_TM_ATTR_DATA = 2,
591 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
592 WLAN_HDD_TM_ATTR_TYPE = 4,
593 /* keep last */
594 WLAN_HDD_TM_ATTR_AFTER_LAST,
595 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
596};
597
598enum wlan_hdd_tm_cmd {
599 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
600 WLAN_HDD_TM_CMD_WLAN_HB = 1,
601};
602
603#define WLAN_HDD_TM_DATA_MAX_LEN 5000
604
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530605enum wlan_hdd_vendor_ie_access_policy {
606 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
607 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
608};
609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
611 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
612 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
613 .len = WLAN_HDD_TM_DATA_MAX_LEN},
614};
615#endif /* WLAN_NL80211_TESTMODE */
616
617#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
618static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
619 .flags = WIPHY_WOWLAN_MAGIC_PKT,
620 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
621 .pattern_min_len = 1,
622 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
623};
624#endif
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530627 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
628 * @flags: Pointer to the flags to Add channel switch flag.
629 *
630 * This Function adds Channel Switch support flag, if channel switch is
631 * supported by kernel.
632 * Return: void.
633 */
634#ifdef CHANNEL_SWITCH_SUPPORTED
635static inline void hdd_add_channel_switch_support(uint32_t *flags)
636{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800637 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530638 return;
639}
640#else
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
643 return;
644}
645#endif
646
Manikandan Mohan22b83722015-12-15 15:03:23 -0800647#ifdef FEATURE_WLAN_TDLS
648
649/* TDLS capabilities params */
650#define PARAM_MAX_TDLS_SESSION \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
652#define PARAM_TDLS_FEATURE_SUPPORT \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
654
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
657 * @wiphy: WIPHY structure pointer
658 * @wdev: Wireless device structure pointer
659 * @data: Pointer to the data received
660 * @data_len: Length of the data received
661 *
662 * This function provides TDLS capabilities
663 *
664 * Return: 0 on success and errno on failure
665 */
666static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
667 struct wireless_dev *wdev,
668 const void *data,
669 int data_len)
670{
671 int status;
672 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
673 struct sk_buff *skb;
674 uint32_t set = 0;
675
Jeff Johnson1f61b612016-02-12 16:28:33 -0800676 ENTER_DEV(wdev->netdev);
677
Anurag Chouhan6d760662016-02-20 16:05:43 +0530678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 hdd_err("Command not allowed in FTM mode");
680 return -EPERM;
681 }
682
683 status = wlan_hdd_validate_context(hdd_ctx);
684 if (status)
685 return status;
686
687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
688 NLMSG_HDRLEN);
689 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700690 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 goto fail;
692 }
693
694 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
697 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701 } else {
702 set = set | WIFI_TDLS_SUPPORT;
703 set = set | (hdd_ctx->config->fTDLSExternalControl ?
704 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
705 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
706 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
709 hdd_ctx->max_num_tdls_sta) ||
710 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
711 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700712 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 goto fail;
714 }
715 }
716 return cfg80211_vendor_cmd_reply(skb);
717fail:
718 if (skb)
719 kfree_skb(skb);
720 return -EINVAL;
721}
722
723/**
724 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
725 * @wiphy: WIPHY structure pointer
726 * @wdev: Wireless device structure pointer
727 * @data: Pointer to the data received
728 * @data_len: Length of the data received
729 *
730 * This function provides TDLS capabilities
731 *
732 * Return: 0 on success and errno on failure
733 */
734static int
735wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
736 struct wireless_dev *wdev,
737 const void *data,
738 int data_len)
739{
740 int ret;
741
742 cds_ssr_protect(__func__);
743 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
744 data, data_len);
745 cds_ssr_unprotect(__func__);
746
747 return ret;
748}
749#endif
750
751#ifdef QCA_HT_2040_COEX
752static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
753#endif
754
755#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
756/*
757 * FUNCTION: wlan_hdd_send_avoid_freq_event
758 * This is called when wlan driver needs to send vendor specific
759 * avoid frequency range event to userspace
760 */
761int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
762 tHddAvoidFreqList *pAvoidFreqList)
763{
764 struct sk_buff *vendor_event;
765
766 ENTER();
767
768 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700769 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 return -EINVAL;
771 }
772
773 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700774 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return -EINVAL;
776 }
777
778 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
779 NULL,
780 sizeof(tHddAvoidFreqList),
781 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
782 GFP_KERNEL);
783 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700784 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 return -EINVAL;
786 }
787
788 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
789 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
790
791 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
792
793 EXIT();
794 return 0;
795}
796#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
797
798/* vendor specific events */
799static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
800#ifdef FEATURE_WLAN_CH_AVOID
801 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
806 },
807#endif /* FEATURE_WLAN_CH_AVOID */
808
809#ifdef WLAN_FEATURE_NAN
810 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_NAN
815 },
816#endif
817
818#ifdef WLAN_FEATURE_STATS_EXT
819 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
824 },
825#endif /* WLAN_FEATURE_STATS_EXT */
826#ifdef FEATURE_WLAN_EXTSCAN
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
832 },
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
840 .
841 vendor_id
842 =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .
853 subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd
863 =
864 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
865 },
866 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
867 .
868 vendor_id
869 =
870 QCA_NL80211_VENDOR_ID,
871 .subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
875 .vendor_id =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
881 .
882 vendor_id
883 =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .
912 subcmd =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd
922 =
923 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
924 },
925 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
926 .
927 vendor_id
928 =
929 QCA_NL80211_VENDOR_ID,
930 .
931 subcmd
932 =
933 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
938 },
939 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
940 .vendor_id = QCA_NL80211_VENDOR_ID,
941 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
942 },
943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
982#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
983 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
990 .vendor_id = QCA_NL80211_VENDOR_ID,
991 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
992 },
993#ifdef WLAN_FEATURE_ROAM_OFFLOAD
994 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
999 },
1000#endif
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1030 },
1031#ifdef FEATURE_WLAN_EXTSCAN
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1047 },
1048 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1051 },
1052#endif /* FEATURE_WLAN_EXTSCAN */
1053 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1056 },
1057#ifdef WLAN_FEATURE_MEMDUMP
1058 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1061 },
1062#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001063#ifdef WLAN_FEATURE_TSF
1064 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1067 },
1068#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1072 },
1073 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1076 },
1077 /* OCB events */
1078 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1081 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001082#ifdef FEATURE_LFR_SUBNET_DETECTION
1083 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1084 .vendor_id = QCA_NL80211_VENDOR_ID,
1085 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1086 },
1087#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001088
1089#ifdef WLAN_FEATURE_NAN_DATAPATH
1090 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1093 },
1094#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001095
1096 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1099 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301100 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1101 .vendor_id = QCA_NL80211_VENDOR_ID,
1102 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1103 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001104#ifdef WLAN_UMAC_CONVERGENCE
1105 COMMON_VENDOR_EVENTS
1106#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107};
1108
1109/**
1110 * __is_driver_dfs_capable() - get driver DFS capability
1111 * @wiphy: pointer to wireless wiphy structure.
1112 * @wdev: pointer to wireless_dev structure.
1113 * @data: Pointer to the data to be passed via vendor interface
1114 * @data_len:Length of the data to be passed
1115 *
1116 * This function is called by userspace to indicate whether or not
1117 * the driver supports DFS offload.
1118 *
1119 * Return: 0 on success, negative errno on failure
1120 */
1121static int __is_driver_dfs_capable(struct wiphy *wiphy,
1122 struct wireless_dev *wdev,
1123 const void *data,
1124 int data_len)
1125{
1126 u32 dfs_capability = 0;
1127 struct sk_buff *temp_skbuff;
1128 int ret_val;
1129 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1130
Jeff Johnson1f61b612016-02-12 16:28:33 -08001131 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132
1133 ret_val = wlan_hdd_validate_context(hdd_ctx);
1134 if (ret_val)
1135 return ret_val;
1136
Anurag Chouhan6d760662016-02-20 16:05:43 +05301137 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138 hdd_err("Command not allowed in FTM mode");
1139 return -EPERM;
1140 }
1141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143
1144 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1145 NLMSG_HDRLEN);
1146
1147 if (temp_skbuff != NULL) {
1148 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1149 dfs_capability);
1150 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001151 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 kfree_skb(temp_skbuff);
1153
1154 return ret_val;
1155 }
1156
1157 return cfg80211_vendor_cmd_reply(temp_skbuff);
1158 }
1159
Jeff Johnson020db452016-06-29 14:37:26 -07001160 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 return -ENOMEM;
1162}
1163
1164/**
1165 * is_driver_dfs_capable() - get driver DFS capability
1166 * @wiphy: pointer to wireless wiphy structure.
1167 * @wdev: pointer to wireless_dev structure.
1168 * @data: Pointer to the data to be passed via vendor interface
1169 * @data_len:Length of the data to be passed
1170 *
1171 * This function is called by userspace to indicate whether or not
1172 * the driver supports DFS offload. This is an SSR-protected
1173 * wrapper function.
1174 *
1175 * Return: 0 on success, negative errno on failure
1176 */
1177static int is_driver_dfs_capable(struct wiphy *wiphy,
1178 struct wireless_dev *wdev,
1179 const void *data,
1180 int data_len)
1181{
1182 int ret;
1183
1184 cds_ssr_protect(__func__);
1185 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1186 cds_ssr_unprotect(__func__);
1187
1188 return ret;
1189}
1190
1191/**
1192 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1193 *
1194 * @adapter: SAP adapter pointer
1195 *
1196 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1197 * radio. So in case of DFS MCC scenario override current SAP given config
1198 * to follow concurrent SAP DFS config
1199 *
1200 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1201 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1203{
1204 hdd_adapter_t *con_sap_adapter;
1205 tsap_Config_t *sap_config, *con_sap_config;
1206 int con_ch;
1207
1208 /*
1209 * Check if AP+AP case, once primary AP chooses a DFS
1210 * channel secondary AP should always follow primary APs channel
1211 */
1212 if (!cds_concurrent_beaconing_sessions_running())
1213 return 0;
1214
1215 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1216 if (!con_sap_adapter)
1217 return 0;
1218
1219 sap_config = &adapter->sessionCtx.ap.sapConfig;
1220 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1221 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1222
1223 if (!CDS_IS_DFS_CH(con_ch))
1224 return 0;
1225
Jeff Johnson020db452016-06-29 14:37:26 -07001226 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 sap_config->channel = con_ch;
1230
1231 if (con_sap_config->acs_cfg.acs_mode == true) {
1232 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1233 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001234 hdd_err("Primary AP channel config error");
1235 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 con_ch, con_sap_config->acs_cfg.pri_ch,
1237 con_sap_config->acs_cfg.ht_sec_ch);
1238 return -EINVAL;
1239 }
1240 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1241 * MCC restriction. So free ch list allocated in do_acs
1242 * func for Sec AP and realloc for Pri AP ch list size
1243 */
1244 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301245 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301247 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 &con_sap_config->acs_cfg,
1249 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301250 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 sizeof(uint8_t) *
1252 con_sap_config->acs_cfg.ch_list_count);
1253 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001254 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 return -ENOMEM;
1256 }
1257
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301258 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 con_sap_config->acs_cfg.ch_list,
1260 con_sap_config->acs_cfg.ch_list_count);
1261
1262 } else {
1263 sap_config->acs_cfg.pri_ch = con_ch;
1264 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1265 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1266 }
1267
1268 return con_ch;
1269}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001270
1271/**
1272 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1273 * @sap_cfg: pointer to SAP config struct
1274 *
1275 * This function sets the default ACS start and end channel for the given band
1276 * and also parses the given ACS channel list.
1277 *
1278 * Return: None
1279 */
1280
1281static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1282 bool vht_enabled)
1283{
1284 int i;
1285 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001287 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1288 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 }
1302
1303 if (ht_enabled)
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1305
1306 if (vht_enabled)
1307 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1308
1309
1310 /* Parse ACS Chan list from hostapd */
1311 if (!sap_cfg->acs_cfg.ch_list)
1312 return;
1313
1314 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1315 sap_cfg->acs_cfg.end_ch =
1316 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1317 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301318 /* avoid channel as start channel */
1319 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1320 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001321 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1322 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1323 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1324 }
1325}
1326
1327
1328static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1329
1330/**
1331 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1332 * @adapter: pointer to SAP adapter struct
1333 *
1334 * This function starts the ACS procedure if there are no
1335 * constraints like MBSSID DFS restrictions.
1336 *
1337 * Return: Status of ACS Start procedure
1338 */
1339
1340static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1341{
1342
1343 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1344 tsap_Config_t *sap_config;
1345 tpWLAN_SAPEventCB acs_event_callback;
1346 int status;
1347
1348 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301349 if (hdd_ctx->acs_policy.acs_channel)
1350 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1351 else
1352 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353
1354 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1355 if (status < 0) {
1356 return status;
1357 } else {
1358 if (status > 0) {
1359 /*notify hostapd about channel override */
1360 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1361 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1362 return 0;
1363 }
1364 }
1365 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1366 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001367 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 return -EINVAL;
1369 }
1370
1371 acs_event_callback = hdd_hostapd_sap_event_cb;
1372
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301373 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301374 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001375 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 acs_event_callback, sap_config, adapter->dev);
1379
1380
1381 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001382 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 return -EINVAL;
1384 }
bings394afdd2017-01-09 11:22:38 +08001385 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1386 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1388
1389 return 0;
1390}
1391
1392/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301393 * hdd_update_reg_chan_info : This API contructs channel info
1394 * for all the given channel
1395 * @adapter: pointer to SAP adapter struct
1396 * @channel_count: channel count
1397 * @channel_list: channel list
1398 *
1399 * Return: Status of of channel information updation
1400 */
1401int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
1402 uint32_t channel_count,
1403 uint8_t *channel_list)
1404{
1405 int i;
1406 struct hdd_channel_info *icv;
1407 struct ch_params_s ch_params;
1408 uint8_t bw_offset = 0, chan = 0;
1409 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1410 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1411
1412 /* memory allocation */
1413 sap_config->channel_info = qdf_mem_malloc(
1414 sizeof(struct hdd_channel_info) *
1415 channel_count);
1416 if (!sap_config->channel_info) {
1417 hdd_err("memory allocation failed");
1418 return -ENOMEM;
1419
1420 }
1421 for (i = 0; i < channel_count; i++) {
1422 icv = &sap_config->channel_info[i];
1423 chan = channel_list[i];
1424
1425 if (chan == 0)
1426 continue;
1427
1428 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1429 bw_offset = 1 << BW_40_OFFSET_BIT;
1430 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1431 bw_offset = 1 << BW_20_OFFSET_BIT;
1432 icv->freq = cds_get_channel_freq(chan);
1433 icv->ieee_chan_number = chan;
1434 icv->max_reg_power = cds_get_channel_reg_power(chan);
1435
1436 /* filling demo values */
1437 icv->max_radio_power = HDD_MAX_TX_POWER;
1438 icv->min_radio_power = HDD_MIN_TX_POWER;
1439 /* not supported in current driver */
1440 icv->max_antenna_gain = 0;
1441
1442 icv->reg_class_id = wlan_hdd_find_opclass(
1443 WLAN_HDD_GET_HAL_CTX(adapter),
1444 chan, bw_offset);
1445
1446 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1447 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1448 cds_set_channel_params(chan, 0, &ch_params);
1449 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1450 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1451 }
1452 icv->flags = 0;
1453 icv->flags = cds_get_vendor_reg_flags(chan,
1454 sap_config->acs_cfg.ch_width,
1455 sap_config->acs_cfg.is_ht_enabled,
1456 sap_config->acs_cfg.is_vht_enabled,
1457 hdd_ctx->config->enable_sub_20_channel_width);
1458
1459 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1460 icv->freq, icv->flags,
1461 icv->flagext, icv->ieee_chan_number,
1462 icv->max_reg_power, icv->max_radio_power,
1463 icv->min_radio_power, icv->reg_class_id,
1464 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1465 icv->vht_center_freq_seg1);
1466 }
1467 return 0;
1468}
1469
1470/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1471#define CHAN_INFO_ATTR_FLAGS \
1472 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1473#define CHAN_INFO_ATTR_FLAG_EXT \
1474 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1475#define CHAN_INFO_ATTR_FREQ \
1476 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1477#define CHAN_INFO_ATTR_MAX_REG_POWER \
1478 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1479#define CHAN_INFO_ATTR_MAX_POWER \
1480 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1481#define CHAN_INFO_ATTR_MIN_POWER \
1482 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1483#define CHAN_INFO_ATTR_REG_CLASS_ID \
1484 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1485#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1486 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1487#define CHAN_INFO_ATTR_VHT_SEG_0 \
1488 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1489#define CHAN_INFO_ATTR_VHT_SEG_1 \
1490 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1491
1492/**
1493 * hdd_cfg80211_update_channel_info() - add channel info attributes
1494 * @skb: pointer to sk buff
1495 * @hdd_ctx: pointer to hdd station context
1496 * @idx: attribute index
1497 *
1498 * Return: Success(0) or reason code for failure
1499 */
1500int32_t
1501hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1502 tsap_Config_t *sap_config, int idx)
1503{
1504 struct nlattr *nla_attr, *channel;
1505 struct hdd_channel_info *icv;
1506 int i;
1507
1508 nla_attr = nla_nest_start(skb, idx);
1509 if (!nla_attr)
1510 goto fail;
1511
1512 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1513 channel = nla_nest_start(skb, i);
1514 if (!channel)
1515 goto fail;
1516
1517 icv = &sap_config->channel_info[i];
1518 if (!icv) {
1519 hdd_err("channel info not found");
1520 goto fail;
1521 }
1522 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1523 icv->freq) ||
1524 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1525 icv->flags) ||
1526 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1527 icv->flagext) ||
1528 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1529 icv->max_reg_power) ||
1530 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1531 icv->max_radio_power) ||
1532 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1533 icv->min_radio_power) ||
1534 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1535 icv->reg_class_id) ||
1536 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1537 icv->max_antenna_gain) ||
1538 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1539 icv->vht_center_freq_seg0) ||
1540 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1541 icv->vht_center_freq_seg1)) {
1542 hdd_err("put fail");
1543 goto fail;
1544 }
1545 nla_nest_end(skb, channel);
1546 }
1547 nla_nest_end(skb, nla_attr);
1548 return 0;
1549fail:
1550 hdd_err("nl channel update failed");
1551 return -EINVAL;
1552}
1553#undef CHAN_INFO_ATTR_FLAGS
1554#undef CHAN_INFO_ATTR_FLAG_EXT
1555#undef CHAN_INFO_ATTR_FREQ
1556#undef CHAN_INFO_ATTR_MAX_REG_POWER
1557#undef CHAN_INFO_ATTR_MAX_POWER
1558#undef CHAN_INFO_ATTR_MIN_POWER
1559#undef CHAN_INFO_ATTR_REG_CLASS_ID
1560#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1561#undef CHAN_INFO_ATTR_VHT_SEG_0
1562#undef CHAN_INFO_ATTR_VHT_SEG_1
1563
1564/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001565 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1566 * @wiphy: Linux wiphy struct pointer
1567 * @wdev: Linux wireless device struct pointer
1568 * @data: ACS information from hostapd
1569 * @data_len: ACS information length
1570 *
1571 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1572 * and starts ACS procedure.
1573 *
1574 * Return: ACS procedure start status
1575 */
1576
1577static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1578 struct wireless_dev *wdev,
1579 const void *data, int data_len)
1580{
1581 struct net_device *ndev = wdev->netdev;
1582 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1583 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1584 tsap_Config_t *sap_config;
1585 struct sk_buff *temp_skbuff;
1586 int status = -EINVAL, i = 0;
1587 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1588 bool ht_enabled, ht40_enabled, vht_enabled;
1589 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301590 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591
1592 /* ***Note*** Donot set SME config related to ACS operation here because
1593 * ACS operation is not synchronouse and ACS for Second AP may come when
1594 * ACS operation for first AP is going on. So only do_acs is split to
1595 * seperate start_acs routine. Also SME-PMAC struct that is used to
1596 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1597 * config shall be set only from start_acs.
1598 */
1599
1600 /* nla_policy Policy template. Policy not applied as some attributes are
1601 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1602 *
1603 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1604 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1605 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1606 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1607 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1608 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1609 */
1610
Jeff Johnson1f61b612016-02-12 16:28:33 -08001611 ENTER_DEV(ndev);
1612
Anurag Chouhan6d760662016-02-20 16:05:43 +05301613 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614 hdd_err("Command not allowed in FTM mode");
1615 return -EPERM;
1616 }
1617
1618 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001619 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001620 return -EPERM;
1621 }
1622
1623 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301624 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301626
Naveen Rawat64e477e2016-05-20 10:34:56 -07001627 if (cds_is_sub_20_mhz_enabled()) {
1628 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1629 status = -EINVAL;
1630 goto out;
1631 }
1632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001633 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301634 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001635
1636 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1637 NULL);
1638 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001639 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001640 goto out;
1641 }
1642
1643 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001644 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001645 goto out;
1646 }
1647 sap_config->acs_cfg.hw_mode = nla_get_u8(
1648 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1649
1650 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1651 ht_enabled =
1652 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1653 else
1654 ht_enabled = 0;
1655
1656 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1657 ht40_enabled =
1658 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1659 else
1660 ht40_enabled = 0;
1661
1662 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1663 vht_enabled =
1664 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1665 else
1666 vht_enabled = 0;
1667
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301668 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1669 vht_enabled = 0;
1670 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1671 }
1672
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1674 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1675 } else {
1676 if (ht_enabled && ht40_enabled)
1677 ch_width = 40;
1678 else
1679 ch_width = 20;
1680 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301681
1682 /* this may be possible, when sap_force_11n_for_11ac is set */
1683 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1684 if (ht_enabled && ht40_enabled)
1685 ch_width = 40;
1686 else
1687 ch_width = 20;
1688 }
1689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690 if (ch_width == 80)
1691 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1692 else if (ch_width == 40)
1693 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1694 else
1695 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1696
1697 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1698 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1699 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1700 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1701 * since it contains the frequency values of the channels in
1702 * the channel list.
1703 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1704 * is present
1705 */
1706 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1707 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1708 sap_config->acs_cfg.ch_list_count = nla_len(
1709 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1710 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301711 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 sizeof(uint8_t) *
1713 sap_config->acs_cfg.ch_list_count);
1714 if (sap_config->acs_cfg.ch_list == NULL)
1715 goto out;
1716
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301717 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 sap_config->acs_cfg.ch_list_count);
1719 }
1720 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1721 uint32_t *freq =
1722 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1723 sap_config->acs_cfg.ch_list_count = nla_len(
1724 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1725 sizeof(uint32_t);
1726 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301727 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 sap_config->acs_cfg.ch_list_count);
1729 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001730 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001731 status = -ENOMEM;
1732 goto out;
1733 }
1734
1735 /* convert frequency to channel */
1736 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1737 sap_config->acs_cfg.ch_list[i] =
1738 ieee80211_frequency_to_channel(freq[i]);
1739 }
1740 }
1741
1742 hdd_debug("get pcl for DO_ACS vendor command");
1743
1744 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001745 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301746 sap_config->acs_cfg.pcl_channels,
1747 &sap_config->acs_cfg.pcl_ch_count,
1748 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301749 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001750 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001751
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301753 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1754 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001755 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756 vht_enabled = 1;
1757 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1758 sap_config->acs_cfg.ch_width =
1759 hdd_ctx->config->vhtChannelWidth;
1760 /* No VHT80 in 2.4G so perform ACS accordingly */
1761 if (sap_config->acs_cfg.end_ch <= 14 &&
1762 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1763 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1764 }
1765
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301766 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1767
Jeff Johnson020db452016-06-29 14:37:26 -07001768 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 -08001769 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1770 ch_width, ht_enabled, vht_enabled,
1771 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1772
1773 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001774 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 sap_config->acs_cfg.ch_list_count);
1776 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001777 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 }
1779 sap_config->acs_cfg.acs_mode = true;
1780 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001781 /* ***Note*** Completion variable usage is not allowed
1782 * here since ACS scan operation may take max 2.2 sec
1783 * for 5G band:
1784 * 9 Active channel X 40 ms active scan time +
1785 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001786 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1787 * for this long. So we split up the scanning part.
1788 */
1789 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001790 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001791 status = 0;
1792 } else {
1793 status = wlan_hdd_cfg80211_start_acs(adapter);
1794 }
1795
1796out:
1797 if (0 == status) {
1798 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1799 NLMSG_HDRLEN);
1800 if (temp_skbuff != NULL)
1801 return cfg80211_vendor_cmd_reply(temp_skbuff);
1802 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001803 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1805
1806 return status;
1807}
1808
Jeff Johnsonf3826e12017-01-12 09:49:40 -08001809/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1811 * @wiphy: Linux wiphy struct pointer
1812 * @wdev: Linux wireless device struct pointer
1813 * @data: ACS information from hostapd
1814 * @data_len: ACS information len
1815 *
1816 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1817 * and starts ACS procedure.
1818 *
1819 * Return: ACS procedure start status
1820 */
1821
1822static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1823 struct wireless_dev *wdev,
1824 const void *data, int data_len)
1825{
1826 int ret;
1827
1828 cds_ssr_protect(__func__);
1829 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1830 cds_ssr_unprotect(__func__);
1831
1832 return ret;
1833}
1834
1835/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001836 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1837 * @adapter: Pointer to adapter struct
1838 *
1839 * This function handle cleanup of what was done in DO_ACS, including free
1840 * memory.
1841 *
1842 * Return: void
1843 */
1844
1845void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1846{
1847 if (adapter == NULL)
1848 return;
1849 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1850 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1851 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1852 }
1853}
1854
1855/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1857 * @work: Linux workqueue struct pointer for ACS work
1858 *
1859 * This function starts the ACS procedure which was marked pending when an ACS
1860 * procedure was in progress for a concurrent SAP interface.
1861 *
1862 * Return: None
1863 */
1864
1865static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1866{
1867 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1868 acs_pending_work.work);
1869 wlan_hdd_cfg80211_start_acs(adapter);
1870}
1871
1872/**
1873 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1874 * @adapter: Pointer to SAP adapter struct
1875 * @pri_channel: SAP ACS procedure selected Primary channel
1876 * @sec_channel: SAP ACS procedure selected secondary channel
1877 *
1878 * This is a callback function from SAP module on ACS procedure is completed.
1879 * This function send the ACS selected channel information to hostapd
1880 *
1881 * Return: None
1882 */
1883
1884void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1885{
1886 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1887 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1888 struct sk_buff *vendor_event;
1889 int ret_val;
1890 hdd_adapter_t *con_sap_adapter;
1891 uint16_t ch_width;
1892
1893 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001894 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1896 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1897 GFP_KERNEL);
1898
1899 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001900 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 return;
1902 }
1903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001904 ret_val = nla_put_u8(vendor_event,
1905 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1906 sap_cfg->acs_cfg.pri_ch);
1907 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001908 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 kfree_skb(vendor_event);
1910 return;
1911 }
1912
1913 ret_val = nla_put_u8(vendor_event,
1914 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1915 sap_cfg->acs_cfg.ht_sec_ch);
1916 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001917 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 kfree_skb(vendor_event);
1919 return;
1920 }
1921
1922 ret_val = nla_put_u8(vendor_event,
1923 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1924 sap_cfg->acs_cfg.vht_seg0_center_ch);
1925 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001926 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 kfree_skb(vendor_event);
1928 return;
1929 }
1930
1931 ret_val = nla_put_u8(vendor_event,
1932 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1933 sap_cfg->acs_cfg.vht_seg1_center_ch);
1934 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001935 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 kfree_skb(vendor_event);
1937 return;
1938 }
1939
1940 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1941 ch_width = 80;
1942 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1943 ch_width = 40;
1944 else
1945 ch_width = 20;
1946
1947 ret_val = nla_put_u16(vendor_event,
1948 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1949 ch_width);
1950 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001951 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952 kfree_skb(vendor_event);
1953 return;
1954 }
1955 if (sap_cfg->acs_cfg.pri_ch > 14)
1956 ret_val = nla_put_u8(vendor_event,
1957 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1958 QCA_ACS_MODE_IEEE80211A);
1959 else
1960 ret_val = nla_put_u8(vendor_event,
1961 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1962 QCA_ACS_MODE_IEEE80211G);
1963
1964 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001965 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 kfree_skb(vendor_event);
1967 return;
1968 }
1969
Jeff Johnson46b40792016-06-29 14:03:14 -07001970 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 -08001971 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1972 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1973 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1974
1975 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1976 /* ***Note*** As already mentioned Completion variable usage is not
1977 * allowed here since ACS scan operation may take max 2.2 sec.
1978 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1979 * operation.
1980 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1981 * when Primary AP ACS is complete and secondary AP ACS is started here
1982 * immediately, Primary AP start_bss may come inbetween ACS operation
1983 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1984 * delay. This path and below constraint will be removed on sessionizing
1985 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1986 * As per design constraint user space control application must take
1987 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1988 * this code path. Sec AP hostapd should be started after Primary AP
1989 * start beaconing which can be confirmed by getchannel iwpriv command
1990 */
1991
1992 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1993 if (con_sap_adapter &&
1994 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1996 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 /* Lets give 500ms for OBSS + START_BSS to complete */
1998 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1999 msecs_to_jiffies(500));
2000 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2001 }
2002
2003 return;
2004}
2005
2006static int
2007__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2008 struct wireless_dev *wdev,
2009 const void *data,
2010 int data_len)
2011{
2012 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2013 struct sk_buff *skb = NULL;
2014 uint32_t fset = 0;
2015 int ret;
2016
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002017 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302018
Anurag Chouhan6d760662016-02-20 16:05:43 +05302019 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 hdd_err("Command not allowed in FTM mode");
2021 return -EPERM;
2022 }
2023
2024 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302025 if (ret)
2026 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002027
2028 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002029 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002030 fset |= WIFI_FEATURE_INFRA;
2031 }
2032 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002033 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 fset |= WIFI_FEATURE_INFRA_5G;
2035 }
2036#ifdef WLAN_FEATURE_P2P
2037 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2038 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002039 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 fset |= WIFI_FEATURE_P2P;
2041 }
2042#endif
2043 fset |= WIFI_FEATURE_SOFT_AP;
2044
2045 /* HOTSPOT is a supplicant feature, enable it by default */
2046 fset |= WIFI_FEATURE_HOTSPOT;
2047
2048#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302049 if (pHddCtx->config->extscan_enabled &&
2050 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002051 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2053 }
2054#endif
2055 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002056 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002057 fset |= WIFI_FEATURE_NAN;
2058 }
2059 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002060 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061 fset |= WIFI_FEATURE_D2D_RTT;
2062 fset |= WIFI_FEATURE_D2AP_RTT;
2063 }
2064#ifdef FEATURE_WLAN_SCAN_PNO
2065 if (pHddCtx->config->configPNOScanSupport &&
2066 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002067 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068 fset |= WIFI_FEATURE_PNO;
2069 }
2070#endif
2071 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2072#ifdef FEATURE_WLAN_TDLS
2073 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2074 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002075 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 fset |= WIFI_FEATURE_TDLS;
2077 }
2078 if (sme_is_feature_supported_by_fw(TDLS) &&
2079 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2080 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002081 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2083 }
2084#endif
2085#ifdef WLAN_AP_STA_CONCURRENCY
2086 fset |= WIFI_FEATURE_AP_STA;
2087#endif
2088 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002089 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002090
2091 if (hdd_link_layer_stats_supported())
2092 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2093
2094 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2095 NLMSG_HDRLEN);
2096 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002097 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002098 return -EINVAL;
2099 }
Jeff Johnson020db452016-06-29 14:37:26 -07002100 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002101 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002102 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103 goto nla_put_failure;
2104 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302105 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302106 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107nla_put_failure:
2108 kfree_skb(skb);
2109 return -EINVAL;
2110}
2111
2112/**
2113 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2114 * @wiphy: pointer to wireless wiphy structure.
2115 * @wdev: pointer to wireless_dev structure.
2116 * @data: Pointer to the data to be passed via vendor interface
2117 * @data_len:Length of the data to be passed
2118 *
2119 * Return: Return the Success or Failure code.
2120 */
2121static int
2122wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2123 struct wireless_dev *wdev,
2124 const void *data, int data_len)
2125{
2126 int ret = 0;
2127
2128 cds_ssr_protect(__func__);
2129 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2130 data, data_len);
2131 cds_ssr_unprotect(__func__);
2132
2133 return ret;
2134}
2135
2136/**
2137 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2138 * @wiphy: pointer to wireless wiphy structure.
2139 * @wdev: pointer to wireless_dev structure.
2140 * @data: Pointer to the data to be passed via vendor interface
2141 * @data_len:Length of the data to be passed
2142 *
2143 * Set the MAC address that is to be used for scanning.
2144 *
2145 * Return: Return the Success or Failure code.
2146 */
2147static int
2148__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2149 struct wireless_dev *wdev,
2150 const void *data,
2151 int data_len)
2152{
2153 tpSirScanMacOui pReqMsg = NULL;
2154 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2155 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302156 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002157 int ret;
2158
Jeff Johnson1f61b612016-02-12 16:28:33 -08002159 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160
Anurag Chouhan6d760662016-02-20 16:05:43 +05302161 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 hdd_err("Command not allowed in FTM mode");
2163 return -EPERM;
2164 }
2165
2166 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302167 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002169
2170 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002171 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 return -ENOTSUPP;
2173 }
2174
2175 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2176 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002177 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 return -EINVAL;
2179 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302180 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002182 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 return -ENOMEM;
2184 }
2185 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002186 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 goto fail;
2188 }
2189 nla_memcpy(&pReqMsg->oui[0],
2190 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2191 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002192 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 pReqMsg->oui[1], pReqMsg->oui[2]);
2194 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302195 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002196 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197 goto fail;
2198 }
2199 return 0;
2200fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302201 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 return -EINVAL;
2203}
2204
2205/**
2206 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2207 * @wiphy: pointer to wireless wiphy structure.
2208 * @wdev: pointer to wireless_dev structure.
2209 * @data: Pointer to the data to be passed via vendor interface
2210 * @data_len:Length of the data to be passed
2211 *
2212 * Set the MAC address that is to be used for scanning. This is an
2213 * SSR-protecting wrapper function.
2214 *
2215 * Return: Return the Success or Failure code.
2216 */
2217static int
2218wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2219 struct wireless_dev *wdev,
2220 const void *data,
2221 int data_len)
2222{
2223 int ret;
2224
2225 cds_ssr_protect(__func__);
2226 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2227 data, data_len);
2228 cds_ssr_unprotect(__func__);
2229
2230 return ret;
2231}
2232
2233/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302234 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2235 * @wiphy: pointer phy adapter
2236 * @wdev: pointer to wireless device structure
2237 * @data: pointer to data buffer
2238 * @data_len: length of data
2239 *
2240 * This routine will give concurrency matrix
2241 *
2242 * Return: int status code
2243 */
2244static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2245 struct wireless_dev *wdev,
2246 const void *data,
2247 int data_len)
2248{
2249 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2250 uint8_t i, feature_sets, max_feature_sets;
2251 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2252 struct sk_buff *reply_skb;
2253 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2254 int ret;
2255
2256 ENTER_DEV(wdev->netdev);
2257
2258 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2259 hdd_err("Command not allowed in FTM mode");
2260 return -EPERM;
2261 }
2262
2263 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302264 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302265 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302266
2267 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2268 data, data_len, NULL)) {
2269 hdd_err("Invalid ATTR");
2270 return -EINVAL;
2271 }
2272
2273 /* Parse and fetch max feature set */
2274 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2275 hdd_err("Attr max feature set size failed");
2276 return -EINVAL;
2277 }
2278 max_feature_sets = nla_get_u32(tb[
2279 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2280 hdd_info("Max feature set size: %d", max_feature_sets);
2281
2282 /* Fill feature combination matrix */
2283 feature_sets = 0;
2284 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002285 WIFI_FEATURE_P2P;
2286 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2287 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302288 /* Add more feature combinations here */
2289
2290 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002291 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302292 hdd_info("Feature set matrix");
2293 for (i = 0; i < feature_sets; i++)
2294 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2295
2296 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2297 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2298 if (!reply_skb) {
2299 hdd_err("Feature set matrix: buffer alloc fail");
2300 return -ENOMEM;
2301 }
2302
2303 if (nla_put_u32(reply_skb,
2304 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2305 feature_sets) ||
2306 nla_put(reply_skb,
2307 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2308 sizeof(u32) * feature_sets,
2309 feature_set_matrix)) {
2310 hdd_err("nla put fail");
2311 kfree_skb(reply_skb);
2312 return -EINVAL;
2313 }
2314 return cfg80211_vendor_cmd_reply(reply_skb);
2315}
2316
2317/**
2318 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2319 * @wiphy: pointer to wireless wiphy structure.
2320 * @wdev: pointer to wireless_dev structure.
2321 * @data: Pointer to the data to be passed via vendor interface
2322 * @data_len:Length of the data to be passed
2323 *
2324 * Retrieves the concurrency feature set matrix
2325 *
2326 * Return: 0 on success, negative errno on failure
2327 */
2328static int
2329wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2330 struct wireless_dev *wdev,
2331 const void *data,
2332 int data_len)
2333{
2334 int ret;
2335
2336 cds_ssr_protect(__func__);
2337 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2338 data, data_len);
2339 cds_ssr_unprotect(__func__);
2340
2341 return ret;
2342}
2343
2344/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002345 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2346 * @feature_flags: pointer to the byte array of features.
2347 * @feature: Feature to be turned ON in the byte array.
2348 *
2349 * Return: None
2350 *
2351 * This is called to turn ON or SET the feature flag for the requested feature.
2352 **/
2353#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002354static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2355 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356{
2357 uint32_t index;
2358 uint8_t bit_mask;
2359
2360 index = feature / NUM_BITS_IN_BYTE;
2361 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2362 feature_flags[index] |= bit_mask;
2363}
2364
2365/**
2366 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2367 * @wiphy: pointer to wireless wiphy structure.
2368 * @wdev: pointer to wireless_dev structure.
2369 * @data: Pointer to the data to be passed via vendor interface
2370 * @data_len:Length of the data to be passed
2371 *
2372 * This is called when wlan driver needs to send supported feature set to
2373 * supplicant upon a request/query from the supplicant.
2374 *
2375 * Return: Return the Success or Failure code.
2376 **/
2377#define MAX_CONCURRENT_CHAN_ON_24G 2
2378#define MAX_CONCURRENT_CHAN_ON_5G 2
2379static int
2380__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2381 struct wireless_dev *wdev,
2382 const void *data, int data_len)
2383{
2384 struct sk_buff *skb = NULL;
2385 uint32_t dbs_capability = 0;
2386 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302387 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 int ret_val;
2389
2390 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2391 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2392
Jeff Johnson1f61b612016-02-12 16:28:33 -08002393 ENTER_DEV(wdev->netdev);
2394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2396 if (ret_val)
2397 return ret_val;
2398
Anurag Chouhan6d760662016-02-20 16:05:43 +05302399 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 hdd_err("Command not allowed in FTM mode");
2401 return -EPERM;
2402 }
2403
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002404 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002405 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002406 wlan_hdd_cfg80211_set_feature(feature_flags,
2407 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2408 }
2409
2410 wlan_hdd_cfg80211_set_feature(feature_flags,
2411 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2412 if (wma_is_scan_simultaneous_capable())
2413 wlan_hdd_cfg80211_set_feature(feature_flags,
2414 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002415
2416 if (wma_is_p2p_lo_capable())
2417 wlan_hdd_cfg80211_set_feature(feature_flags,
2418 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2421 NLMSG_HDRLEN);
2422
2423 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002424 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 return -ENOMEM;
2426 }
2427
2428 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2429 sizeof(feature_flags), feature_flags))
2430 goto nla_put_failure;
2431
2432 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302433 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 if (one_by_one_dbs)
2435 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2436
2437 if (two_by_two_dbs)
2438 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2439
2440 if (!one_by_one_dbs && !two_by_two_dbs)
2441 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2442 } else {
2443 hdd_err("wma_get_dbs_hw_mode failed");
2444 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2445 }
2446
2447 hdd_info("dbs_capability is %d", dbs_capability);
2448
2449 if (nla_put_u32(skb,
2450 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2451 MAX_CONCURRENT_CHAN_ON_24G))
2452 goto nla_put_failure;
2453
2454 if (nla_put_u32(skb,
2455 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2456 MAX_CONCURRENT_CHAN_ON_5G))
2457 goto nla_put_failure;
2458
2459 return cfg80211_vendor_cmd_reply(skb);
2460
2461nla_put_failure:
2462 kfree_skb(skb);
2463 return -EINVAL;
2464}
2465
2466/**
2467 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2468 * @wiphy: pointer to wireless wiphy structure.
2469 * @wdev: pointer to wireless_dev structure.
2470 * @data: Pointer to the data to be passed via vendor interface
2471 * @data_len:Length of the data to be passed
2472 *
2473 * This is called when wlan driver needs to send supported feature set to
2474 * supplicant upon a request/query from the supplicant.
2475 *
2476 * Return: Return the Success or Failure code.
2477 */
2478static int
2479wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2480 struct wireless_dev *wdev,
2481 const void *data, int data_len)
2482{
2483 int ret;
2484
2485 cds_ssr_protect(__func__);
2486 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2487 data, data_len);
2488 cds_ssr_unprotect(__func__);
2489
2490 return ret;
2491}
2492
2493
2494/**
2495 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2496 * @wiphy: The wiphy structure
2497 * @wdev: The wireless device
2498 * @data: Data passed by framework
2499 * @data_len: Parameters to be configured passed as data
2500 *
2501 * The roaming related parameters are configured by the framework
2502 * using this interface.
2503 *
2504 * Return: Return either success or failure code.
2505 */
2506static int
2507__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2508 struct wireless_dev *wdev, const void *data, int data_len)
2509{
2510 struct net_device *dev = wdev->netdev;
2511 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2512 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2513 uint8_t session_id;
2514 struct roam_ext_params roam_params;
2515 uint32_t cmd_type, req_id;
2516 struct nlattr *curr_attr;
2517 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2518 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2519 int rem, i;
2520 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002521 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 int ret;
2523
Jeff Johnson1f61b612016-02-12 16:28:33 -08002524 ENTER_DEV(dev);
2525
Anurag Chouhan6d760662016-02-20 16:05:43 +05302526 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 hdd_err("Command not allowed in FTM mode");
2528 return -EPERM;
2529 }
2530
2531 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302532 if (ret)
2533 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534
2535 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2536 data, data_len,
2537 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002538 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 return -EINVAL;
2540 }
2541 /* Parse and fetch Command Type*/
2542 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002543 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 goto fail;
2545 }
2546 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302547 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2549 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002550 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 goto fail;
2552 }
2553 req_id = nla_get_u32(
2554 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002555 hdd_debug("Req Id (%d)", req_id);
2556 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 switch (cmd_type) {
2558 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2559 i = 0;
2560 nla_for_each_nested(curr_attr,
2561 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2562 rem) {
2563 if (nla_parse(tb2,
2564 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2565 nla_data(curr_attr), nla_len(curr_attr),
2566 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002567 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 goto fail;
2569 }
2570 /* Parse and Fetch allowed SSID list*/
2571 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002572 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573 goto fail;
2574 }
2575 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2576 /*
2577 * Upper Layers include a null termination character.
2578 * Check for the actual permissible length of SSID and
2579 * also ensure not to copy the NULL termination
2580 * character to the driver buffer.
2581 */
2582 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2583 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2584 nla_memcpy(
2585 roam_params.ssid_allowed_list[i].ssId,
2586 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2587 buf_len - 1);
2588 roam_params.ssid_allowed_list[i].length =
2589 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002590 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591 roam_params.ssid_allowed_list[i].length,
2592 roam_params.ssid_allowed_list[i].ssId,
2593 roam_params.ssid_allowed_list[i].length);
2594 i++;
2595 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002596 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597 }
2598 }
2599 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002600 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601 roam_params.num_ssid_allowed_list);
2602 sme_update_roam_params(pHddCtx->hHal, session_id,
2603 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2604 break;
2605 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2606 /* Parse and fetch 5G Boost Threshold */
2607 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002608 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 goto fail;
2610 }
2611 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2612 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002613 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614 roam_params.raise_rssi_thresh_5g);
2615 /* Parse and fetch 5G Penalty Threshold */
2616 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002617 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618 goto fail;
2619 }
2620 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2621 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002622 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623 roam_params.drop_rssi_thresh_5g);
2624 /* Parse and fetch 5G Boost Factor */
2625 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002626 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002627 goto fail;
2628 }
2629 roam_params.raise_factor_5g = nla_get_u32(
2630 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002631 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002632 roam_params.raise_factor_5g);
2633 /* Parse and fetch 5G Penalty factor */
2634 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002635 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636 goto fail;
2637 }
2638 roam_params.drop_factor_5g = nla_get_u32(
2639 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002640 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641 roam_params.drop_factor_5g);
2642 /* Parse and fetch 5G Max Boost */
2643 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002644 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 goto fail;
2646 }
2647 roam_params.max_raise_rssi_5g = nla_get_u32(
2648 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002649 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650 roam_params.max_raise_rssi_5g);
2651 /* Parse and fetch Rssi Diff */
2652 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002653 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002654 goto fail;
2655 }
2656 roam_params.rssi_diff = nla_get_s32(
2657 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002658 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002659 roam_params.rssi_diff);
2660 /* Parse and fetch Alert Rssi Threshold */
2661 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002662 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 goto fail;
2664 }
2665 roam_params.alert_rssi_threshold = nla_get_u32(
2666 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002667 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 roam_params.alert_rssi_threshold);
2669 sme_update_roam_params(pHddCtx->hHal, session_id,
2670 roam_params,
2671 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2672 break;
2673 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2674 /* Parse and fetch Activate Good Rssi Roam */
2675 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002676 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 goto fail;
2678 }
2679 roam_params.good_rssi_roam = nla_get_s32(
2680 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002681 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 roam_params.good_rssi_roam);
2683 sme_update_roam_params(pHddCtx->hHal, session_id,
2684 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2685 break;
2686 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2687 /* Parse and fetch number of preferred BSSID */
2688 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002689 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690 goto fail;
2691 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002692 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002693 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002694 if (count > MAX_BSSID_FAVORED) {
2695 hdd_err("Preferred BSSID count %u exceeds max %u",
2696 count, MAX_BSSID_FAVORED);
2697 goto fail;
2698 }
2699 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 i = 0;
2701 nla_for_each_nested(curr_attr,
2702 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2703 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002704
2705 if (i == count) {
2706 hdd_warn("Ignoring excess Preferred BSSID");
2707 break;
2708 }
2709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 if (nla_parse(tb2,
2711 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2712 nla_data(curr_attr), nla_len(curr_attr),
2713 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002714 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 goto fail;
2716 }
2717 /* Parse and fetch MAC address */
2718 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002719 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 goto fail;
2721 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002722 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302724 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002725 hdd_debug(MAC_ADDRESS_STR,
2726 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727 /* Parse and fetch preference factor*/
2728 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002729 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730 goto fail;
2731 }
2732 roam_params.bssid_favored_factor[i] = nla_get_u32(
2733 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002734 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 roam_params.bssid_favored_factor[i]);
2736 i++;
2737 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002738 if (i < count)
2739 hdd_warn("Num Preferred BSSID %u less than expected %u",
2740 i, count);
2741 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002742 sme_update_roam_params(pHddCtx->hHal, session_id,
2743 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2744 break;
2745 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2746 /* Parse and fetch number of blacklist BSSID */
2747 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002748 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749 goto fail;
2750 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002751 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002753 if (count > MAX_BSSID_AVOID_LIST) {
2754 hdd_err("Blacklist BSSID count %u exceeds max %u",
2755 count, MAX_BSSID_AVOID_LIST);
2756 goto fail;
2757 }
2758 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759 i = 0;
2760 nla_for_each_nested(curr_attr,
2761 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2762 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002763
2764 if (i == count) {
2765 hdd_warn("Ignoring excess Blacklist BSSID");
2766 break;
2767 }
2768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 if (nla_parse(tb2,
2770 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2771 nla_data(curr_attr), nla_len(curr_attr),
2772 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002773 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002774 goto fail;
2775 }
2776 /* Parse and fetch MAC address */
2777 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002778 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 goto fail;
2780 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002781 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302783 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002784 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002786 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 i++;
2788 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002789 if (i < count)
2790 hdd_warn("Num Blacklist BSSID %u less than expected %u",
2791 i, count);
2792 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 sme_update_roam_params(pHddCtx->hHal, session_id,
2794 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2795 break;
2796 }
2797 return 0;
2798fail:
2799 return -EINVAL;
2800}
2801
2802/**
2803 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2804 * @wiphy: pointer to wireless wiphy structure.
2805 * @wdev: pointer to wireless_dev structure.
2806 * @data: Pointer to the data to be passed via vendor interface
2807 * @data_len:Length of the data to be passed
2808 *
2809 * Return: Return the Success or Failure code.
2810 */
2811static int
2812wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2813 struct wireless_dev *wdev,
2814 const void *data,
2815 int data_len)
2816{
2817 int ret;
2818
2819 cds_ssr_protect(__func__);
2820 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2821 data, data_len);
2822 cds_ssr_unprotect(__func__);
2823
2824 return ret;
2825}
2826
2827static const struct nla_policy
2828wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2829 +1] = {
2830 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2831};
2832
2833/**
2834 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2835 * @hdd_ctx: HDD context
2836 * @device_mode: device mode
2837 * Return: bool
2838 */
2839static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002840 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841{
2842 hdd_adapter_t *adapter;
2843 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2844 hdd_ap_ctx_t *ap_ctx;
2845 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302846 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302848 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002849 &adapter_node);
2850
2851 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302852 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002853 adapter = adapter_node->pAdapter;
2854
2855 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002856 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857 ap_ctx =
2858 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2859
2860 /*
2861 * if there is SAP already running on DFS channel,
2862 * do not disable scan on dfs channels. Note that
2863 * with SAP on DFS, there cannot be conurrency on
2864 * single radio. But then we can have multiple
2865 * radios !!
2866 */
2867 if (CHANNEL_STATE_DFS ==
2868 cds_get_channel_state(
2869 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002870 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 return true;
2872 }
2873 }
2874
2875 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002876 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 sta_ctx =
2878 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2879
2880 /*
2881 * if STA is already connected on DFS channel,
2882 * do not disable scan on dfs channels
2883 */
2884 if (hdd_conn_is_connected(sta_ctx) &&
2885 (CHANNEL_STATE_DFS ==
2886 cds_get_channel_state(
2887 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002888 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 return true;
2890 }
2891 }
2892
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302893 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894 adapter_node,
2895 &next);
2896 adapter_node = next;
2897 }
2898
2899 return false;
2900}
2901
2902/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002903 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2904 * @hdd_ctx: HDD context within host driver
2905 * @adapter: Adapter pointer
2906 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2907 *
2908 * Loops through devices to see who is operating on DFS channels
2909 * and then disables/enables DFS channels by calling SME API.
2910 * Fails the disable request if any device is active on a DFS channel.
2911 *
2912 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002914
2915int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2916 hdd_adapter_t *adapter,
2917 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302920 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922
2923 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2924 if (no_dfs_flag) {
2925 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002926 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927
2928 if (true == status)
2929 return -EOPNOTSUPP;
2930
2931 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002932 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933
2934 if (true == status)
2935 return -EOPNOTSUPP;
2936 }
2937
2938 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2939
2940 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2941
2942 /*
2943 * call the SME API to tunnel down the new channel list
2944 * to the firmware
2945 */
2946 status = sme_handle_dfs_chan_scan(
2947 h_hal, hdd_ctx->config->enableDFSChnlScan);
2948
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302949 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 ret_val = 0;
2951
2952 /*
2953 * Clear the SME scan cache also. Note that the
2954 * clearing of scan results is independent of session;
2955 * so no need to iterate over
2956 * all sessions
2957 */
2958 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302959 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 ret_val = -EPERM;
2961 }
2962
2963 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002964 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 ret_val = 0;
2966 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002967 return ret_val;
2968}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002970/**
2971 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2972 * @wiphy: corestack handler
2973 * @wdev: wireless device
2974 * @data: data
2975 * @data_len: data length
2976 * Return: success(0) or reason code for failure
2977 */
2978static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2979 struct wireless_dev *wdev,
2980 const void *data,
2981 int data_len)
2982{
2983 struct net_device *dev = wdev->netdev;
2984 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2985 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2986 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2987 int ret_val;
2988 uint32_t no_dfs_flag = 0;
2989
Jeff Johnson1f61b612016-02-12 16:28:33 -08002990 ENTER_DEV(dev);
2991
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002992 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302993 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002994 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002995
2996 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2997 data, data_len,
2998 wlan_hdd_set_no_dfs_flag_config_policy)) {
2999 hdd_err("invalid attr");
3000 return -EINVAL;
3001 }
3002
3003 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3004 hdd_err("attr dfs flag failed");
3005 return -EINVAL;
3006 }
3007
3008 no_dfs_flag = nla_get_u32(
3009 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3010
Jeff Johnson020db452016-06-29 14:37:26 -07003011 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003012
3013 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003014 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003015 return -EINVAL;
3016 }
3017
3018 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3019 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020 return ret_val;
3021}
3022
3023/**
3024 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3025 *
3026 * @wiphy: wiphy device pointer
3027 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003028 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 * @data_len: Buffer length
3030 *
3031 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3032 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3033 *
3034 * Return: EOK or other error codes.
3035 */
3036
3037static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3038 struct wireless_dev *wdev,
3039 const void *data,
3040 int data_len)
3041{
3042 int ret;
3043
3044 cds_ssr_protect(__func__);
3045 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3046 data, data_len);
3047 cds_ssr_unprotect(__func__);
3048
3049 return ret;
3050}
3051
Manikandan Mohan80dea792016-04-28 16:36:48 -07003052static const struct nla_policy
3053wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3054 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3055};
3056
3057/**
3058 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3059 * @wiphy: wiphy device pointer
3060 * @wdev: wireless device pointer
3061 * @data: Vendor command data buffer
3062 * @data_len: Buffer length
3063 *
3064 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3065 * setup WISA Mode features.
3066 *
3067 * Return: Success(0) or reason code for failure
3068 */
3069static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3070 struct wireless_dev *wdev, const void *data, int data_len)
3071{
3072 struct net_device *dev = wdev->netdev;
3073 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3074 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3075 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3076 struct sir_wisa_params wisa;
3077 int ret_val;
3078 QDF_STATUS status;
3079 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003080 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3081 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003082
3083 ENTER_DEV(dev);
3084 ret_val = wlan_hdd_validate_context(hdd_ctx);
3085 if (ret_val)
3086 goto err;
3087
3088 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3089 hdd_err("Command not allowed in FTM mode");
3090 return -EPERM;
3091 }
3092
3093 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3094 wlan_hdd_wisa_cmd_policy)) {
3095 hdd_err("Invalid WISA cmd attributes");
3096 ret_val = -EINVAL;
3097 goto err;
3098 }
3099 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3100 hdd_err("Invalid WISA mode");
3101 ret_val = -EINVAL;
3102 goto err;
3103 }
3104
3105 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3106 hdd_info("WISA Mode: %d", wisa_mode);
3107 wisa.mode = wisa_mode;
3108 wisa.vdev_id = adapter->sessionId;
3109 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003110 if (!QDF_IS_STATUS_SUCCESS(status)) {
3111 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003112 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003113 }
3114 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003115 cdp_set_wisa_mode(soc,
3116 cdp_get_vdev_from_vdev_id(soc, pdev,
3117 adapter->sessionId),
3118 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003119err:
3120 EXIT();
3121 return ret_val;
3122}
3123
3124/**
3125 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3126 * @wiphy: corestack handler
3127 * @wdev: wireless device
3128 * @data: data
3129 * @data_len: data length
3130 *
3131 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3132 * setup WISA mode features.
3133 *
3134 * Return: Success(0) or reason code for failure
3135 */
3136static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3137 struct wireless_dev *wdev,
3138 const void *data,
3139 int data_len)
3140{
3141 int ret;
3142
3143 cds_ssr_protect(__func__);
3144 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3145 cds_ssr_unprotect(__func__);
3146
3147 return ret;
3148}
3149
Anurag Chouhan96919482016-07-13 16:36:57 +05303150/*
3151 * define short names for the global vendor params
3152 * used by __wlan_hdd_cfg80211_get_station_cmd()
3153 */
3154#define STATION_INVALID \
3155 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3156#define STATION_INFO \
3157 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3158#define STATION_ASSOC_FAIL_REASON \
3159 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3160#define STATION_MAX \
3161 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3162
3163static const struct nla_policy
3164hdd_get_station_policy[STATION_MAX + 1] = {
3165 [STATION_INFO] = {.type = NLA_FLAG},
3166 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3167};
3168
3169/**
3170 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3171 * @hdd_ctx: HDD context within host driver
3172 * @wdev: wireless device
3173 *
3174 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3175 * Validate cmd attributes and send the station info to upper layers.
3176 *
3177 * Return: Success(0) or reason code for failure
3178 */
3179static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3180 hdd_adapter_t *adapter)
3181{
3182 struct sk_buff *skb = NULL;
3183 uint32_t nl_buf_len;
3184 hdd_station_ctx_t *hdd_sta_ctx;
3185
3186 nl_buf_len = NLMSG_HDRLEN;
3187 nl_buf_len += sizeof(uint32_t);
3188 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3189
3190 if (!skb) {
3191 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3192 return -ENOMEM;
3193 }
3194
3195 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3196
3197 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3198 hdd_sta_ctx->conn_info.assoc_status_code)) {
3199 hdd_err("put fail");
3200 goto fail;
3201 }
3202 return cfg80211_vendor_cmd_reply(skb);
3203fail:
3204 if (skb)
3205 kfree_skb(skb);
3206 return -EINVAL;
3207}
3208
3209/**
3210 * hdd_map_auth_type() - transform auth type specific to
3211 * vendor command
3212 * @auth_type: csr auth type
3213 *
3214 * Return: Success(0) or reason code for failure
3215 */
3216static int hdd_convert_auth_type(uint32_t auth_type)
3217{
3218 uint32_t ret_val;
3219
3220 switch (auth_type) {
3221 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3222 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3223 break;
3224 case eCSR_AUTH_TYPE_SHARED_KEY:
3225 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3226 break;
3227 case eCSR_AUTH_TYPE_WPA:
3228 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3229 break;
3230 case eCSR_AUTH_TYPE_WPA_PSK:
3231 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3232 break;
3233 case eCSR_AUTH_TYPE_AUTOSWITCH:
3234 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3235 break;
3236 case eCSR_AUTH_TYPE_WPA_NONE:
3237 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3238 break;
3239 case eCSR_AUTH_TYPE_RSN:
3240 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3241 break;
3242 case eCSR_AUTH_TYPE_RSN_PSK:
3243 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3244 break;
3245 case eCSR_AUTH_TYPE_FT_RSN:
3246 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3247 break;
3248 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3249 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3250 break;
3251 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3252 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3253 break;
3254 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3255 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3256 break;
3257 case eCSR_AUTH_TYPE_CCKM_WPA:
3258 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3259 break;
3260 case eCSR_AUTH_TYPE_CCKM_RSN:
3261 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3262 break;
3263 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3264 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3265 break;
3266 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3267 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3268 break;
3269 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3270 case eCSR_AUTH_TYPE_FAILED:
3271 case eCSR_AUTH_TYPE_NONE:
3272 default:
3273 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3274 break;
3275 }
3276 return ret_val;
3277}
3278
3279/**
3280 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3281 * vendor command
3282 * @dot11mode: dot11mode
3283 *
3284 * Return: Success(0) or reason code for failure
3285 */
3286static int hdd_convert_dot11mode(uint32_t dot11mode)
3287{
3288 uint32_t ret_val;
3289
3290 switch (dot11mode) {
3291 case eCSR_CFG_DOT11_MODE_11A:
3292 ret_val = QCA_WLAN_802_11_MODE_11A;
3293 break;
3294 case eCSR_CFG_DOT11_MODE_11B:
3295 ret_val = QCA_WLAN_802_11_MODE_11B;
3296 break;
3297 case eCSR_CFG_DOT11_MODE_11G:
3298 ret_val = QCA_WLAN_802_11_MODE_11G;
3299 break;
3300 case eCSR_CFG_DOT11_MODE_11N:
3301 ret_val = QCA_WLAN_802_11_MODE_11N;
3302 break;
3303 case eCSR_CFG_DOT11_MODE_11AC:
3304 ret_val = QCA_WLAN_802_11_MODE_11AC;
3305 break;
3306 case eCSR_CFG_DOT11_MODE_AUTO:
3307 case eCSR_CFG_DOT11_MODE_ABG:
3308 default:
3309 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3310 }
3311 return ret_val;
3312}
3313
3314/**
3315 * hdd_add_tx_bitrate() - add tx bitrate attribute
3316 * @skb: pointer to sk buff
3317 * @hdd_sta_ctx: pointer to hdd station context
3318 * @idx: attribute index
3319 *
3320 * Return: Success(0) or reason code for failure
3321 */
3322static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3323 hdd_station_ctx_t *hdd_sta_ctx,
3324 int idx)
3325{
3326 struct nlattr *nla_attr;
3327 uint32_t bitrate, bitrate_compat;
3328
3329 nla_attr = nla_nest_start(skb, idx);
3330 if (!nla_attr)
3331 goto fail;
3332 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3333 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3334
3335 /* report 16-bit bitrate only if we can */
3336 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3337 if (bitrate > 0 &&
3338 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3339 hdd_err("put fail");
3340 goto fail;
3341 }
3342 if (bitrate_compat > 0 &&
3343 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3344 hdd_err("put fail");
3345 goto fail;
3346 }
3347 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3348 hdd_sta_ctx->conn_info.txrate.nss)) {
3349 hdd_err("put fail");
3350 goto fail;
3351 }
3352 nla_nest_end(skb, nla_attr);
3353 return 0;
3354fail:
3355 return -EINVAL;
3356}
3357
3358/**
3359 * hdd_add_sta_info() - add station info attribute
3360 * @skb: pointer to sk buff
3361 * @hdd_sta_ctx: pointer to hdd station context
3362 * @idx: attribute index
3363 *
3364 * Return: Success(0) or reason code for failure
3365 */
3366static int32_t hdd_add_sta_info(struct sk_buff *skb,
3367 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3368{
3369 struct nlattr *nla_attr;
3370
3371 nla_attr = nla_nest_start(skb, idx);
3372 if (!nla_attr)
3373 goto fail;
3374 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3375 (hdd_sta_ctx->conn_info.signal + 100))) {
3376 hdd_err("put fail");
3377 goto fail;
3378 }
3379 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3380 goto fail;
3381 nla_nest_end(skb, nla_attr);
3382 return 0;
3383fail:
3384 return -EINVAL;
3385}
3386
3387/**
3388 * hdd_add_survey_info() - add survey info attribute
3389 * @skb: pointer to sk buff
3390 * @hdd_sta_ctx: pointer to hdd station context
3391 * @idx: attribute index
3392 *
3393 * Return: Success(0) or reason code for failure
3394 */
3395static int32_t hdd_add_survey_info(struct sk_buff *skb,
3396 hdd_station_ctx_t *hdd_sta_ctx,
3397 int idx)
3398{
3399 struct nlattr *nla_attr;
3400
3401 nla_attr = nla_nest_start(skb, idx);
3402 if (!nla_attr)
3403 goto fail;
3404 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3405 hdd_sta_ctx->conn_info.freq) ||
3406 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3407 (hdd_sta_ctx->conn_info.noise + 100))) {
3408 hdd_err("put fail");
3409 goto fail;
3410 }
3411 nla_nest_end(skb, nla_attr);
3412 return 0;
3413fail:
3414 return -EINVAL;
3415}
3416
3417/**
3418 * hdd_add_link_standard_info() - add link info attribute
3419 * @skb: pointer to sk buff
3420 * @hdd_sta_ctx: pointer to hdd station context
3421 * @idx: attribute index
3422 *
3423 * Return: Success(0) or reason code for failure
3424 */
3425static int32_t
3426hdd_add_link_standard_info(struct sk_buff *skb,
3427 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3428{
3429 struct nlattr *nla_attr;
3430
3431 nla_attr = nla_nest_start(skb, idx);
3432 if (!nla_attr)
3433 goto fail;
3434 if (nla_put(skb,
3435 NL80211_ATTR_SSID,
3436 hdd_sta_ctx->conn_info.SSID.SSID.length,
3437 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3438 hdd_err("put fail");
3439 goto fail;
3440 }
3441 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3442 goto fail;
3443 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3444 goto fail;
3445 nla_nest_end(skb, nla_attr);
3446 return 0;
3447fail:
3448 return -EINVAL;
3449}
3450
3451/**
3452 * hdd_add_ap_standard_info() - add ap info attribute
3453 * @skb: pointer to sk buff
3454 * @hdd_sta_ctx: pointer to hdd station context
3455 * @idx: attribute index
3456 *
3457 * Return: Success(0) or reason code for failure
3458 */
3459static int32_t
3460hdd_add_ap_standard_info(struct sk_buff *skb,
3461 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3462{
3463 struct nlattr *nla_attr;
3464
3465 nla_attr = nla_nest_start(skb, idx);
3466 if (!nla_attr)
3467 goto fail;
3468 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3469 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3470 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3471 &hdd_sta_ctx->conn_info.vht_caps)) {
3472 hdd_err("put fail");
3473 goto fail;
3474 }
3475 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3476 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3477 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3478 &hdd_sta_ctx->conn_info.ht_caps)) {
3479 hdd_err("put fail");
3480 goto fail;
3481 }
3482 nla_nest_end(skb, nla_attr);
3483 return 0;
3484fail:
3485 return -EINVAL;
3486}
3487
3488/**
3489 * hdd_get_station_info() - send BSS information to supplicant
3490 * @hdd_ctx: pointer to hdd context
3491 * @adapter: pointer to adapter
3492 *
3493 * Return: 0 if success else error status
3494 */
3495static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3496 hdd_adapter_t *adapter)
3497{
3498 struct sk_buff *skb = NULL;
3499 uint8_t *tmp_hs20 = NULL;
3500 uint32_t nl_buf_len;
3501 hdd_station_ctx_t *hdd_sta_ctx;
3502
3503 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3504
3505 nl_buf_len = NLMSG_HDRLEN;
3506 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3507 sizeof(hdd_sta_ctx->conn_info.freq) +
3508 sizeof(hdd_sta_ctx->conn_info.noise) +
3509 sizeof(hdd_sta_ctx->conn_info.signal) +
3510 (sizeof(uint32_t) * 2) +
3511 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3512 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3513 sizeof(hdd_sta_ctx->conn_info.authType) +
3514 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3515 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3516 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3517 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3518 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3519 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3520 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3521 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3522 1);
3523 }
3524 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3525 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3526 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3527 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3528
3529
3530 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3531 if (!skb) {
3532 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3533 return -ENOMEM;
3534 }
3535
3536 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3537 LINK_INFO_STANDARD_NL80211_ATTR)) {
3538 hdd_err("put fail");
3539 goto fail;
3540 }
3541 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3542 AP_INFO_STANDARD_NL80211_ATTR)) {
3543 hdd_err("put fail");
3544 goto fail;
3545 }
3546 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3547 hdd_sta_ctx->conn_info.roam_count) ||
3548 nla_put_u32(skb, INFO_AKM,
3549 hdd_convert_auth_type(
3550 hdd_sta_ctx->conn_info.authType)) ||
3551 nla_put_u32(skb, WLAN802_11_MODE,
3552 hdd_convert_dot11mode(
3553 hdd_sta_ctx->conn_info.dot11Mode))) {
3554 hdd_err("put fail");
3555 goto fail;
3556 }
3557 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3558 if (nla_put(skb, HT_OPERATION,
3559 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3560 &hdd_sta_ctx->conn_info.ht_operation)) {
3561 hdd_err("put fail");
3562 goto fail;
3563 }
3564 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3565 if (nla_put(skb, VHT_OPERATION,
3566 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3567 &hdd_sta_ctx->conn_info.vht_operation)) {
3568 hdd_err("put fail");
3569 goto fail;
3570 }
3571 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3572 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3573 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3574 tmp_hs20 + 1)) {
3575 hdd_err("put fail");
3576 goto fail;
3577 }
3578
3579 return cfg80211_vendor_cmd_reply(skb);
3580fail:
3581 if (skb)
3582 kfree_skb(skb);
3583 return -EINVAL;
3584}
3585
3586/**
3587 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3588 * @wiphy: corestack handler
3589 * @wdev: wireless device
3590 * @data: data
3591 * @data_len: data length
3592 *
3593 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3594 * Validate cmd attributes and send the station info to upper layers.
3595 *
3596 * Return: Success(0) or reason code for failure
3597 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303598static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303599__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3600 struct wireless_dev *wdev,
3601 const void *data,
3602 int data_len)
3603{
3604 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3605 struct net_device *dev = wdev->netdev;
3606 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3607 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3608 int32_t status;
3609
3610 ENTER_DEV(dev);
3611 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3612 hdd_err("Command not allowed in FTM mode");
3613 status = -EPERM;
3614 goto out;
3615 }
3616
3617 status = wlan_hdd_validate_context(hdd_ctx);
3618 if (0 != status)
3619 goto out;
3620
3621
3622 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3623 data, data_len, NULL);
3624 if (status) {
3625 hdd_err("Invalid ATTR");
3626 goto out;
3627 }
3628
3629 /* Parse and fetch Command Type*/
3630 if (tb[STATION_INFO]) {
3631 status = hdd_get_station_info(hdd_ctx, adapter);
3632 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3633 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3634 } else {
3635 hdd_err("get station info cmd type failed");
3636 status = -EINVAL;
3637 goto out;
3638 }
3639 EXIT();
3640out:
3641 return status;
3642}
3643
3644/**
3645 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3646 * @wiphy: corestack handler
3647 * @wdev: wireless device
3648 * @data: data
3649 * @data_len: data length
3650 *
3651 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3652 * Validate cmd attributes and send the station info to upper layers.
3653 *
3654 * Return: Success(0) or reason code for failure
3655 */
3656static int32_t
3657hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3658 struct wireless_dev *wdev,
3659 const void *data,
3660 int data_len)
3661{
3662 int ret;
3663
3664 cds_ssr_protect(__func__);
3665 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3666 cds_ssr_unprotect(__func__);
3667
3668 return ret;
3669}
3670
3671/*
3672 * undef short names defined for get station command
3673 * used by __wlan_hdd_cfg80211_get_station_cmd()
3674 */
3675#undef STATION_INVALID
3676#undef STATION_INFO
3677#undef STATION_ASSOC_FAIL_REASON
3678#undef STATION_MAX
3679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3681/**
3682 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3683 * @wiphy: pointer to wireless wiphy structure.
3684 * @wdev: pointer to wireless_dev structure.
3685 * @data: Pointer to the Key data
3686 * @data_len:Length of the data passed
3687 *
3688 * This is called when wlan driver needs to save the keys received via
3689 * vendor specific command.
3690 *
3691 * Return: Return the Success or Failure code.
3692 */
3693static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3694 struct wireless_dev *wdev,
3695 const void *data, int data_len)
3696{
3697 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3698 struct net_device *dev = wdev->netdev;
3699 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3700 hdd_context_t *hdd_ctx_ptr;
3701 int status;
3702
Jeff Johnson1f61b612016-02-12 16:28:33 -08003703 ENTER_DEV(dev);
3704
Anurag Chouhan6d760662016-02-20 16:05:43 +05303705 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706 hdd_err("Command not allowed in FTM mode");
3707 return -EPERM;
3708 }
3709
3710 if ((data == NULL) || (data_len == 0) ||
3711 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003712 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 return -EINVAL;
3714 }
3715
3716 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3717 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003718 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003719 return -EINVAL;
3720 }
3721
3722 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303723 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003724 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003725 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3726 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003727 true,
3728 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303729 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3730 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003731 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3732 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3733 return 0;
3734}
3735
3736/**
3737 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3738 * @wiphy: pointer to wireless wiphy structure.
3739 * @wdev: pointer to wireless_dev structure.
3740 * @data: Pointer to the Key data
3741 * @data_len:Length of the data passed
3742 *
3743 * This is called when wlan driver needs to save the keys received via
3744 * vendor specific command.
3745 *
3746 * Return: Return the Success or Failure code.
3747 */
3748static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3749 struct wireless_dev *wdev,
3750 const void *data, int data_len)
3751{
3752 int ret;
3753
3754 cds_ssr_protect(__func__);
3755 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3756 cds_ssr_unprotect(__func__);
3757
3758 return ret;
3759}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003760#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761
3762static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3763 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3764 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3765 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003766 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003767};
3768
3769/**
3770 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3771 * @wiphy: pointer to wireless wiphy structure.
3772 * @wdev: pointer to wireless_dev structure.
3773 * @data: Pointer to the data to be passed via vendor interface
3774 * @data_len:Length of the data to be passed
3775 *
3776 * This is called when wlan driver needs to send wifi driver related info
3777 * (driver/fw version) to the user space application upon request.
3778 *
3779 * Return: Return the Success or Failure code.
3780 */
3781static int
3782__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3783 struct wireless_dev *wdev,
3784 const void *data, int data_len)
3785{
3786 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3787 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003788 tSirVersionString driver_version;
3789 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003790 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003791 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003792 struct sk_buff *reply_skb;
3793 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003794
Jeff Johnson1f61b612016-02-12 16:28:33 -08003795 ENTER_DEV(wdev->netdev);
3796
Anurag Chouhan6d760662016-02-20 16:05:43 +05303797 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 hdd_err("Command not allowed in FTM mode");
3799 return -EPERM;
3800 }
3801
3802 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303803 if (status)
3804 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003805
3806 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3807 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003808 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003809 return -EINVAL;
3810 }
3811
3812 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003813 hdd_err("Rcvd req for Driver version");
3814 strlcpy(driver_version, QWLAN_VERSIONSTR,
3815 sizeof(driver_version));
3816 skb_len += strlen(driver_version) + 1;
3817 count++;
3818 }
3819
3820 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3821 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3823 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003824 snprintf(firmware_version, sizeof(firmware_version),
3825 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3826 skb_len += strlen(firmware_version) + 1;
3827 count++;
3828 }
3829
3830 if (count == 0) {
3831 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003832 return -EINVAL;
3833 }
3834
Ryan Hsu7ac88852016-04-28 10:20:34 -07003835 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3836 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003839 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 return -ENOMEM;
3841 }
3842
Ryan Hsu7ac88852016-04-28 10:20:34 -07003843 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3844 if (nla_put_string(reply_skb,
3845 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3846 driver_version))
3847 goto error_nla_fail;
3848 }
3849
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303850 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003851 if (nla_put_string(reply_skb,
3852 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3853 firmware_version))
3854 goto error_nla_fail;
3855 }
3856
3857 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3858 if (nla_put_u32(reply_skb,
3859 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3860 hdd_ctx->radio_index))
3861 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003862 }
3863
3864 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003865
3866error_nla_fail:
3867 hdd_err("nla put fail");
3868 kfree_skb(reply_skb);
3869 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003870}
3871
3872/**
3873 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3874 * @wiphy: pointer to wireless wiphy structure.
3875 * @wdev: pointer to wireless_dev structure.
3876 * @data: Pointer to the data to be passed via vendor interface
3877 * @data_len:Length of the data to be passed
3878 *
3879 * This is called when wlan driver needs to send wifi driver related info
3880 * (driver/fw version) to the user space application upon request.
3881 *
3882 * Return: Return the Success or Failure code.
3883 */
3884static int
3885wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3886 struct wireless_dev *wdev,
3887 const void *data, int data_len)
3888{
3889 int ret;
3890
3891 cds_ssr_protect(__func__);
3892 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3893 cds_ssr_unprotect(__func__);
3894
3895 return ret;
3896}
3897
3898/**
3899 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3900 * @wiphy: pointer to wireless wiphy structure.
3901 * @wdev: pointer to wireless_dev structure.
3902 * @data: Pointer to the data to be passed via vendor interface
3903 * @data_len:Length of the data to be passed
3904 *
3905 * This is called by userspace to know the supported logger features
3906 *
3907 * Return: Return the Success or Failure code.
3908 */
3909static int
3910__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3911 struct wireless_dev *wdev,
3912 const void *data, int data_len)
3913{
3914 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3915 int status;
3916 uint32_t features;
3917 struct sk_buff *reply_skb = NULL;
3918
Jeff Johnson1f61b612016-02-12 16:28:33 -08003919 ENTER_DEV(wdev->netdev);
3920
Anurag Chouhan6d760662016-02-20 16:05:43 +05303921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922 hdd_err("Command not allowed in FTM mode");
3923 return -EPERM;
3924 }
3925
3926 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303927 if (status)
3928 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929
3930 features = 0;
3931
3932 if (hdd_is_memdump_supported())
3933 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3934 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3935 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3936 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3937
3938 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3939 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3940 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003941 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942 return -ENOMEM;
3943 }
3944
Jeff Johnson020db452016-06-29 14:37:26 -07003945 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003946 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3947 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003948 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949 kfree_skb(reply_skb);
3950 return -EINVAL;
3951 }
3952
3953 return cfg80211_vendor_cmd_reply(reply_skb);
3954}
3955
3956/**
3957 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3958 * @wiphy: pointer to wireless wiphy structure.
3959 * @wdev: pointer to wireless_dev structure.
3960 * @data: Pointer to the data to be passed via vendor interface
3961 * @data_len:Length of the data to be passed
3962 *
3963 * This is called by userspace to know the supported logger features
3964 *
3965 * Return: Return the Success or Failure code.
3966 */
3967static int
3968wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3969 struct wireless_dev *wdev,
3970 const void *data, int data_len)
3971{
3972 int ret;
3973
3974 cds_ssr_protect(__func__);
3975 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3976 data, data_len);
3977 cds_ssr_unprotect(__func__);
3978
3979 return ret;
3980}
3981
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003982#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003983/**
3984 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05303985 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003986 * @bssid: pointer to bssid of roamed AP.
3987 * @req_rsn_ie: Pointer to request RSN IE
3988 * @req_rsn_len: Length of the request RSN IE
3989 * @rsp_rsn_ie: Pointer to response RSN IE
3990 * @rsp_rsn_len: Length of the response RSN IE
3991 * @roam_info_ptr: Pointer to the roaming related information
3992 *
3993 * This is called when wlan driver needs to send the roaming and
3994 * authorization information after roaming.
3995 *
3996 * The information that would be sent is the request RSN IE, response
3997 * RSN IE and BSSID of the newly roamed AP.
3998 *
3999 * If the Authorized status is authenticated, then additional parameters
4000 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4001 * supplicant.
4002 *
4003 * The supplicant upon receiving this event would ignore the legacy
4004 * cfg80211_roamed call and use the entire information from this event.
4005 * The cfg80211_roamed should still co-exist since the kernel will
4006 * make use of the parameters even if the supplicant ignores it.
4007 *
4008 * Return: Return the Success or Failure code.
4009 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304010int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4012 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4013{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304014 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004016 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 ENTER();
4018
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304019 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004022 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004023 !roam_info_ptr->roamSynchInProgress)
4024 return 0;
4025
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304027 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4029 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4030 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004031 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4033 GFP_KERNEL);
4034
4035 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004036 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 return -EINVAL;
4038 }
4039
4040 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4041 ETH_ALEN, bssid) ||
4042 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4043 req_rsn_len, req_rsn_ie) ||
4044 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4045 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004046 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004047 goto nla_put_failure;
4048 }
Jeff Johnson020db452016-06-29 14:37:26 -07004049 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004050 if (roam_info_ptr->synchAuthStatus ==
4051 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004052 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004053 if (nla_put_u8(skb,
4054 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4055 hdd_err("nla put fail");
4056 goto nla_put_failure;
4057 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004058 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4059 /* if FT or CCKM connection: dont send replay counter */
4060 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4061 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4062 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4063 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4064 nla_put(skb,
4065 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4066 SIR_REPLAY_CTR_LEN,
4067 roam_info_ptr->replay_ctr)) {
4068 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004069 hdd_err("failed to send replay counter.");
4070 goto nla_put_failure;
4071 }
4072 if (nla_put(skb,
4073 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4074 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4075 nla_put(skb,
4076 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4077 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4078 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079 goto nla_put_failure;
4080 }
4081 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004082 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4084 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004085 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086 goto nla_put_failure;
4087 }
4088 }
4089
Jeff Johnson020db452016-06-29 14:37:26 -07004090 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004091 roam_info_ptr->subnet_change_status);
4092
4093 /*
4094 * Add subnet change status if subnet has changed
4095 * 0 = unchanged
4096 * 1 = changed
4097 * 2 = unknown
4098 */
4099 if (roam_info_ptr->subnet_change_status) {
4100 if (nla_put_u8(skb,
4101 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4102 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004103 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004104 goto nla_put_failure;
4105 }
4106 }
4107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 cfg80211_vendor_event(skb, GFP_KERNEL);
4109 return 0;
4110
4111nla_put_failure:
4112 kfree_skb(skb);
4113 return -EINVAL;
4114}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004115#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116
4117static const struct nla_policy
4118wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4119
4120 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4121 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4122 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304123 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304124 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4125 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004126 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4127 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4128 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4129 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4130 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304131 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132};
4133
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304135 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4136 *
4137 * @adapter: Pointer to HDD adapter
4138 * @ie_data: Pointer to Scan IEs buffer
4139 * @ie_len: Length of Scan IEs
4140 *
4141 * Return: 0 on success; error number otherwise
4142 */
4143static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4144 uint8_t *ie_data, uint8_t ie_len)
4145{
4146 hdd_scaninfo_t *scan_info = NULL;
4147 scan_info = &adapter->scan_info;
4148
4149 if (scan_info->default_scan_ies) {
4150 qdf_mem_free(scan_info->default_scan_ies);
4151 scan_info->default_scan_ies = NULL;
4152 }
4153
4154 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4155 if (!scan_info->default_scan_ies)
4156 return -ENOMEM;
4157
4158 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4159 scan_info->default_scan_ies_len = ie_len;
4160 return 0;
4161}
4162
4163/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4165 * vendor command
4166 *
4167 * @wiphy: wiphy device pointer
4168 * @wdev: wireless device pointer
4169 * @data: Vendor command data buffer
4170 * @data_len: Buffer length
4171 *
4172 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4173 *
4174 * Return: Error code.
4175 */
4176static int
4177__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4178 struct wireless_dev *wdev,
4179 const void *data,
4180 int data_len)
4181{
4182 struct net_device *dev = wdev->netdev;
4183 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4184 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4185 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4186 int ret_val = 0;
4187 u32 modulated_dtim;
4188 u16 stats_avg_factor;
4189 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304190 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004191 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004192 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304193 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304194 int attr_len;
4195 int access_policy = 0;
4196 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4197 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304198 uint16_t scan_ie_len = 0;
4199 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304200 struct sir_set_tx_rx_aggregation_size request;
4201 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004202 uint8_t retry, delay;
4203 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304204 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304205
Jeff Johnson1f61b612016-02-12 16:28:33 -08004206 ENTER_DEV(dev);
4207
Anurag Chouhan6d760662016-02-20 16:05:43 +05304208 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209 hdd_err("Command not allowed in FTM mode");
4210 return -EPERM;
4211 }
4212
4213 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304214 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216
4217 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4218 data, data_len,
4219 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004220 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 return -EINVAL;
4222 }
4223
Krunal Sonie3531942016-04-12 17:43:53 -07004224 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4225 ftm_capab = nla_get_u32(tb[
4226 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4227 hdd_ctx->config->fine_time_meas_cap =
4228 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4229 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304230 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004231 hdd_ctx->config->fine_time_meas_cap);
4232 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4233 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4234 hdd_ctx->config->fine_time_meas_cap);
4235 }
4236
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004237 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4238 modulated_dtim = nla_get_u32(
4239 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4240
4241 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4242 adapter->sessionId,
4243 modulated_dtim);
4244
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304245 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246 ret_val = -EPERM;
4247 }
4248
Kapil Gupta6213c012016-09-02 19:39:09 +05304249 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4250 qpower = nla_get_u8(
4251 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4252 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4253 ret_val = -EINVAL;
4254 }
4255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4257 stats_avg_factor = nla_get_u16(
4258 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4259 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4260 adapter->sessionId,
4261 stats_avg_factor);
4262
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304263 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 ret_val = -EPERM;
4265 }
4266
4267
4268 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4269 guard_time = nla_get_u32(
4270 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4271 status = sme_configure_guard_time(hdd_ctx->hHal,
4272 adapter->sessionId,
4273 guard_time);
4274
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304275 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 ret_val = -EPERM;
4277 }
4278
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304279 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4280 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4281 attr_len = nla_len(
4282 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4283 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4284 hdd_info("Invalid value. attr_len %d",
4285 attr_len);
4286 return -EINVAL;
4287 }
4288
4289 nla_memcpy(&vendor_ie,
4290 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4291 attr_len);
4292 vendor_ie_present = true;
4293 hdd_info("Access policy vendor ie present.attr_len %d",
4294 attr_len);
4295 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4296 &vendor_ie[0], attr_len);
4297 }
4298
4299 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4300 access_policy = (int) nla_get_u32(
4301 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4302 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4303 (access_policy >
4304 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4305 hdd_info("Invalid value. access_policy %d",
4306 access_policy);
4307 return -EINVAL;
4308 }
4309 access_policy_present = true;
4310 hdd_info("Access policy present. access_policy %d",
4311 access_policy);
4312 }
4313
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004314 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4315 retry = nla_get_u8(tb[
4316 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4317 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4318 CFG_NON_AGG_RETRY_MAX : retry;
4319 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4320 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4321 retry, PDEV_CMD);
4322 }
4323
4324 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4325 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4326 retry = retry > CFG_AGG_RETRY_MAX ?
4327 CFG_AGG_RETRY_MAX : retry;
4328
4329 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4330 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4331 CFG_AGG_RETRY_MIN : retry;
4332 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4333 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4334 retry, PDEV_CMD);
4335 }
4336
4337 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4338 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4339 retry = retry > CFG_MGMT_RETRY_MAX ?
4340 CFG_MGMT_RETRY_MAX : retry;
4341 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4342 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4343 retry, PDEV_CMD);
4344 }
4345
4346 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4347 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4348 retry = retry > CFG_CTRL_RETRY_MAX ?
4349 CFG_CTRL_RETRY_MAX : retry;
4350 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4351 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4352 retry, PDEV_CMD);
4353 }
4354
4355 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4356 delay = nla_get_u8(tb[
4357 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4358 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4359 CFG_PROPAGATION_DELAY_MAX : delay;
4360 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4361 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4362 delay, PDEV_CMD);
4363 }
4364
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304365 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4366 tx_fail_count = nla_get_u32(
4367 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4368 if (tx_fail_count) {
4369 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4370 adapter->sessionId, tx_fail_count);
4371 if (QDF_STATUS_SUCCESS != status) {
4372 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4373 status);
4374 return -EINVAL;
4375 }
4376 }
4377 }
4378
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304379 if (vendor_ie_present && access_policy_present) {
4380 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4381 access_policy =
4382 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304383 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304384 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304385 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304386
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304387 hdd_info("calling sme_update_access_policy_vendor_ie");
4388 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4389 adapter->sessionId, &vendor_ie[0],
4390 access_policy);
4391 if (QDF_STATUS_SUCCESS != status) {
4392 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304393 return -EINVAL;
4394 }
4395 }
4396
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304397 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4398 set_value = nla_get_u8(
4399 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4400 hdd_info("set_value: %d", set_value);
4401 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4402 }
4403
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304404 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4405 scan_ie_len = nla_len(
4406 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4407 hdd_info("Received default scan IE of len %d session %d device mode %d",
4408 scan_ie_len, adapter->sessionId,
4409 adapter->device_mode);
4410 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4411 scan_ie = (uint8_t *) nla_data(tb
4412 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304413
4414 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4415 scan_ie_len))
4416 hdd_err("Failed to save default scan IEs");
4417
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304418 if (adapter->device_mode == QDF_STA_MODE) {
4419 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4420 adapter->sessionId, scan_ie,
4421 scan_ie_len);
4422 if (QDF_STATUS_SUCCESS != status)
4423 ret_val = -EPERM;
4424 }
4425 } else
4426 ret_val = -EPERM;
4427 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304428
4429 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4430 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4431 /* if one is specified, both must be specified */
4432 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4433 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4434 hdd_err("Both TX and RX MPDU Aggregation required");
4435 return -EINVAL;
4436 }
4437
4438 request.tx_aggregation_size = nla_get_u8(
4439 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4440 request.rx_aggregation_size = nla_get_u8(
4441 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4442 request.vdev_id = adapter->sessionId;
4443
4444 if (request.tx_aggregation_size >=
4445 CFG_TX_AGGREGATION_SIZE_MIN &&
4446 request.tx_aggregation_size <=
4447 CFG_TX_AGGREGATION_SIZE_MAX &&
4448 request.rx_aggregation_size >=
4449 CFG_RX_AGGREGATION_SIZE_MIN &&
4450 request.rx_aggregation_size <=
4451 CFG_RX_AGGREGATION_SIZE_MAX) {
4452 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4453 if (qdf_status != QDF_STATUS_SUCCESS) {
4454 hdd_err("failed to set aggr sizes err %d",
4455 qdf_status);
4456 ret_val = -EPERM;
4457 }
4458 } else {
4459 hdd_err("TX %d RX %d MPDU aggr size not in range",
4460 request.tx_aggregation_size,
4461 request.rx_aggregation_size);
4462 ret_val = -EINVAL;
4463 }
4464 }
4465
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304466 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4467 uint8_t ignore_assoc_disallowed;
4468
4469 ignore_assoc_disallowed
4470 = nla_get_u8(tb[
4471 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4472 hdd_info("Set ignore_assoc_disallowed value - %d",
4473 ignore_assoc_disallowed);
4474 if ((ignore_assoc_disallowed <
4475 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4476 (ignore_assoc_disallowed >
4477 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4478 return -EPERM;
4479
4480 sme_update_session_param(hdd_ctx->hHal,
4481 adapter->sessionId,
4482 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4483 ignore_assoc_disallowed);
4484 }
4485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004486 return ret_val;
4487}
4488
4489/**
4490 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4491 * vendor command
4492 *
4493 * @wiphy: wiphy device pointer
4494 * @wdev: wireless device pointer
4495 * @data: Vendor command data buffer
4496 * @data_len: Buffer length
4497 *
4498 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4499 *
4500 * Return: EOK or other error codes.
4501 */
4502static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4503 struct wireless_dev *wdev,
4504 const void *data,
4505 int data_len)
4506{
4507 int ret;
4508
4509 cds_ssr_protect(__func__);
4510 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4511 data, data_len);
4512 cds_ssr_unprotect(__func__);
4513
4514 return ret;
4515}
4516
4517static const struct
4518nla_policy
4519qca_wlan_vendor_wifi_logger_start_policy
4520[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4521 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4522 = {.type = NLA_U32 },
4523 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4524 = {.type = NLA_U32 },
4525 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4526 = {.type = NLA_U32 },
4527};
4528
4529/**
4530 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4531 * or disable the collection of packet statistics from the firmware
4532 * @wiphy: WIPHY structure pointer
4533 * @wdev: Wireless device structure pointer
4534 * @data: Pointer to the data received
4535 * @data_len: Length of the data received
4536 *
4537 * This function enables or disables the collection of packet statistics from
4538 * the firmware
4539 *
4540 * Return: 0 on success and errno on failure
4541 */
4542static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4543 struct wireless_dev *wdev,
4544 const void *data,
4545 int data_len)
4546{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304547 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004548 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4549 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4550 struct sir_wifi_start_log start_log;
4551
Jeff Johnson1f61b612016-02-12 16:28:33 -08004552 ENTER_DEV(wdev->netdev);
4553
Anurag Chouhan6d760662016-02-20 16:05:43 +05304554 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 hdd_err("Command not allowed in FTM mode");
4556 return -EPERM;
4557 }
4558
4559 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304560 if (status)
4561 return status;
4562
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563
4564 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4565 data, data_len,
4566 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004567 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568 return -EINVAL;
4569 }
4570
4571 /* Parse and fetch ring id */
4572 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004573 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574 return -EINVAL;
4575 }
4576 start_log.ring_id = nla_get_u32(
4577 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004578 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004579
4580 /* Parse and fetch verbose level */
4581 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004582 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 return -EINVAL;
4584 }
4585 start_log.verbose_level = nla_get_u32(
4586 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004587 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588
4589 /* Parse and fetch flag */
4590 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004591 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592 return -EINVAL;
4593 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304594 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004595 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304596 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304598 /* size is buff size which can be set using iwpriv command*/
4599 start_log.size = 0;
4600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4602
4603 if (start_log.ring_id == RING_ID_WAKELOCK) {
4604 /* Start/stop wakelock events */
4605 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4606 cds_set_wakelock_logging(true);
4607 else
4608 cds_set_wakelock_logging(false);
4609 return 0;
4610 }
4611
4612 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304613 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004614 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004615 status);
4616 return -EINVAL;
4617 }
4618 return 0;
4619}
4620
4621/**
4622 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4623 * or disable the collection of packet statistics from the firmware
4624 * @wiphy: WIPHY structure pointer
4625 * @wdev: Wireless device structure pointer
4626 * @data: Pointer to the data received
4627 * @data_len: Length of the data received
4628 *
4629 * This function is used to enable or disable the collection of packet
4630 * statistics from the firmware
4631 *
4632 * Return: 0 on success and errno on failure
4633 */
4634static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4635 struct wireless_dev *wdev,
4636 const void *data,
4637 int data_len)
4638{
4639 int ret = 0;
4640
4641 cds_ssr_protect(__func__);
4642 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4643 wdev, data, data_len);
4644 cds_ssr_unprotect(__func__);
4645
4646 return ret;
4647}
4648
4649static const struct
4650nla_policy
4651qca_wlan_vendor_wifi_logger_get_ring_data_policy
4652[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4653 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4654 = {.type = NLA_U32 },
4655};
4656
4657/**
4658 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4659 * @wiphy: WIPHY structure pointer
4660 * @wdev: Wireless device structure pointer
4661 * @data: Pointer to the data received
4662 * @data_len: Length of the data received
4663 *
4664 * This function is used to flush or retrieve the per packet statistics from
4665 * the driver
4666 *
4667 * Return: 0 on success and errno on failure
4668 */
4669static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4670 struct wireless_dev *wdev,
4671 const void *data,
4672 int data_len)
4673{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304674 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675 uint32_t ring_id;
4676 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4677 struct nlattr *tb
4678 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4679
Jeff Johnson1f61b612016-02-12 16:28:33 -08004680 ENTER_DEV(wdev->netdev);
4681
Anurag Chouhan6d760662016-02-20 16:05:43 +05304682 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 hdd_err("Command not allowed in FTM mode");
4684 return -EPERM;
4685 }
4686
4687 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304688 if (status)
4689 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690
4691 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4692 data, data_len,
4693 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004694 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004695 return -EINVAL;
4696 }
4697
4698 /* Parse and fetch ring id */
4699 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004700 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 return -EINVAL;
4702 }
4703
4704 ring_id = nla_get_u32(
4705 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4706
4707 if (ring_id == RING_ID_PER_PACKET_STATS) {
4708 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004709 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304710 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4711 /*
4712 * As part of DRIVER ring ID, flush both driver and fw logs.
4713 * For other Ring ID's driver doesn't have any rings to flush
4714 */
4715 hdd_notice("Bug report triggered by framework");
4716
4717 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4718 WLAN_LOG_INDICATOR_FRAMEWORK,
4719 WLAN_LOG_REASON_CODE_UNUSED,
4720 true, false);
4721 if (QDF_STATUS_SUCCESS != status) {
4722 hdd_err("Failed to trigger bug report");
4723 return -EINVAL;
4724 }
4725 } else {
4726 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4727 WLAN_LOG_INDICATOR_FRAMEWORK,
4728 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730 return 0;
4731}
4732
4733/**
4734 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4735 * @wiphy: WIPHY structure pointer
4736 * @wdev: Wireless device structure pointer
4737 * @data: Pointer to the data received
4738 * @data_len: Length of the data received
4739 *
4740 * This function is used to flush or retrieve the per packet statistics from
4741 * the driver
4742 *
4743 * Return: 0 on success and errno on failure
4744 */
4745static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4746 struct wireless_dev *wdev,
4747 const void *data,
4748 int data_len)
4749{
4750 int ret = 0;
4751
4752 cds_ssr_protect(__func__);
4753 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4754 wdev, data, data_len);
4755 cds_ssr_unprotect(__func__);
4756
4757 return ret;
4758}
4759
4760#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4761/**
4762 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4763 * @hdd_ctx: HDD context
4764 * @request_id: [input] request id
4765 * @pattern_id: [output] pattern id
4766 *
4767 * This function loops through request id to pattern id array
4768 * if the slot is available, store the request id and return pattern id
4769 * if entry exists, return the pattern id
4770 *
4771 * Return: 0 on success and errno on failure
4772 */
4773static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4774 uint32_t request_id,
4775 uint8_t *pattern_id)
4776{
4777 uint32_t i;
4778
4779 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4780 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4781 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4782 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4783 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4784 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4785 return 0;
4786 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4787 request_id) {
4788 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4789 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4790 return 0;
4791 }
4792 }
4793 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4794 return -EINVAL;
4795}
4796
4797/**
4798 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4799 * @hdd_ctx: HDD context
4800 * @request_id: [input] request id
4801 * @pattern_id: [output] pattern id
4802 *
4803 * This function loops through request id to pattern id array
4804 * reset request id to 0 (slot available again) and
4805 * return pattern id
4806 *
4807 * Return: 0 on success and errno on failure
4808 */
4809static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4810 uint32_t request_id,
4811 uint8_t *pattern_id)
4812{
4813 uint32_t i;
4814
4815 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4816 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4817 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4818 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4819 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4820 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4821 return 0;
4822 }
4823 }
4824 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4825 return -EINVAL;
4826}
4827
4828
4829/*
4830 * define short names for the global vendor params
4831 * used by __wlan_hdd_cfg80211_offloaded_packets()
4832 */
4833#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4834#define PARAM_REQUEST_ID \
4835 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4836#define PARAM_CONTROL \
4837 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4838#define PARAM_IP_PACKET \
4839 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4840#define PARAM_SRC_MAC_ADDR \
4841 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4842#define PARAM_DST_MAC_ADDR \
4843 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4844#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4845
4846/**
4847 * wlan_hdd_add_tx_ptrn() - add tx pattern
4848 * @adapter: adapter pointer
4849 * @hdd_ctx: hdd context
4850 * @tb: nl attributes
4851 *
4852 * This function reads the NL attributes and forms a AddTxPtrn message
4853 * posts it to SME.
4854 *
4855 */
4856static int
4857wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4858 struct nlattr **tb)
4859{
4860 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304861 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 uint32_t request_id, ret, len;
4863 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304864 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 uint16_t eth_type = htons(ETH_P_IP);
4866
4867 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004868 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004869 return -ENOTSUPP;
4870 }
4871
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304872 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004874 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875 return -ENOMEM;
4876 }
4877
4878 /* Parse and fetch request Id */
4879 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004880 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 goto fail;
4882 }
4883
4884 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4885 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004886 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 return -EINVAL;
4888 }
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890
4891 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004892 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893 goto fail;
4894 }
4895 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004896 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004897 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004898 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004899 goto fail;
4900 }
4901
4902 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004903 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 goto fail;
4905 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004906 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304907 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004908 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004909 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004910
Anurag Chouhanc5548422016-02-24 18:33:27 +05304911 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004912 &adapter->macAddressCurrent)) {
4913 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 goto fail;
4915 }
4916
4917 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004918 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004919 goto fail;
4920 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304921 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004922 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004923 MAC_ADDR_ARRAY(dst_addr.bytes));
4924
4925 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004926 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 goto fail;
4928 }
4929 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004930 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931
4932 if (add_req->ucPtrnSize < 0 ||
4933 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4934 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004935 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004936 add_req->ucPtrnSize);
4937 goto fail;
4938 }
4939
4940 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304941 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304942 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304943 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304944 QDF_MAC_ADDR_SIZE);
4945 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304946 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947 len += 2;
4948
4949 /*
4950 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4951 * ------------------------------------------------------------
4952 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4953 * ------------------------------------------------------------
4954 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304955 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004956 nla_data(tb[PARAM_IP_PACKET]),
4957 add_req->ucPtrnSize);
4958 add_req->ucPtrnSize += len;
4959
4960 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4961 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004962 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004963 goto fail;
4964 }
4965 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004966 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004967
4968 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304969 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004970 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 goto fail;
4972 }
4973
4974 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304975 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 return 0;
4977
4978fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304979 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004980 return -EINVAL;
4981}
4982
4983/**
4984 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4985 * @adapter: adapter pointer
4986 * @hdd_ctx: hdd context
4987 * @tb: nl attributes
4988 *
4989 * This function reads the NL attributes and forms a DelTxPtrn message
4990 * posts it to SME.
4991 *
4992 */
4993static int
4994wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4995 struct nlattr **tb)
4996{
4997 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304998 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 uint32_t request_id, ret;
5000 uint8_t pattern_id = 0;
5001
5002 /* Parse and fetch request Id */
5003 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005004 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 return -EINVAL;
5006 }
5007 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5008 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005009 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010 return -EINVAL;
5011 }
5012
5013 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5014 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005015 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005016 return -EINVAL;
5017 }
5018
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305019 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005021 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005022 return -ENOMEM;
5023 }
5024
Anurag Chouhanc5548422016-02-24 18:33:27 +05305025 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005026 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005028 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029 request_id, del_req->ucPtrnId);
5030
5031 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305032 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005033 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005034 goto fail;
5035 }
5036
5037 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305038 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039 return 0;
5040
5041fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305042 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005043 return -EINVAL;
5044}
5045
5046
5047/**
5048 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5049 * @wiphy: Pointer to wireless phy
5050 * @wdev: Pointer to wireless device
5051 * @data: Pointer to data
5052 * @data_len: Data length
5053 *
5054 * Return: 0 on success, negative errno on failure
5055 */
5056static int
5057__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5058 struct wireless_dev *wdev,
5059 const void *data,
5060 int data_len)
5061{
5062 struct net_device *dev = wdev->netdev;
5063 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5064 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5065 struct nlattr *tb[PARAM_MAX + 1];
5066 uint8_t control;
5067 int ret;
5068 static const struct nla_policy policy[PARAM_MAX + 1] = {
5069 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5070 [PARAM_CONTROL] = { .type = NLA_U32 },
5071 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305072 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005073 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305074 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005075 [PARAM_PERIOD] = { .type = NLA_U32 },
5076 };
5077
Jeff Johnson1f61b612016-02-12 16:28:33 -08005078 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005079
Anurag Chouhan6d760662016-02-20 16:05:43 +05305080 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 hdd_err("Command not allowed in FTM mode");
5082 return -EPERM;
5083 }
5084
5085 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305086 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005088
5089 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005090 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005091 return -ENOTSUPP;
5092 }
5093
5094 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005095 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005096 return -EINVAL;
5097 }
5098
5099 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005100 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005101 return -EINVAL;
5102 }
5103 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005104 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005105
5106 if (control == WLAN_START_OFFLOADED_PACKETS)
5107 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
5108 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
5109 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
5110 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005111 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005112 return -EINVAL;
5113 }
5114}
5115
5116/*
5117 * done with short names for the global vendor params
5118 * used by __wlan_hdd_cfg80211_offloaded_packets()
5119 */
5120#undef PARAM_MAX
5121#undef PARAM_REQUEST_ID
5122#undef PARAM_CONTROL
5123#undef PARAM_IP_PACKET
5124#undef PARAM_SRC_MAC_ADDR
5125#undef PARAM_DST_MAC_ADDR
5126#undef PARAM_PERIOD
5127
5128/**
5129 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5130 * @wiphy: wiphy structure pointer
5131 * @wdev: Wireless device structure pointer
5132 * @data: Pointer to the data received
5133 * @data_len: Length of @data
5134 *
5135 * Return: 0 on success; errno on failure
5136 */
5137static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5138 struct wireless_dev *wdev,
5139 const void *data,
5140 int data_len)
5141{
5142 int ret = 0;
5143
5144 cds_ssr_protect(__func__);
5145 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5146 wdev, data, data_len);
5147 cds_ssr_unprotect(__func__);
5148
5149 return ret;
5150}
5151#endif
5152
5153/*
5154 * define short names for the global vendor params
5155 * used by __wlan_hdd_cfg80211_monitor_rssi()
5156 */
5157#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5158#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5159#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5160#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5161#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5162
5163/**
5164 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5165 * @wiphy: Pointer to wireless phy
5166 * @wdev: Pointer to wireless device
5167 * @data: Pointer to data
5168 * @data_len: Data length
5169 *
5170 * Return: 0 on success, negative errno on failure
5171 */
5172static int
5173__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5174 struct wireless_dev *wdev,
5175 const void *data,
5176 int data_len)
5177{
5178 struct net_device *dev = wdev->netdev;
5179 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5180 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5181 struct nlattr *tb[PARAM_MAX + 1];
5182 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305183 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005184 int ret;
5185 uint32_t control;
5186 static const struct nla_policy policy[PARAM_MAX + 1] = {
5187 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5188 [PARAM_CONTROL] = { .type = NLA_U32 },
5189 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5190 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5191 };
5192
Jeff Johnson1f61b612016-02-12 16:28:33 -08005193 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305195 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5196 hdd_err("invalid session id: %d", adapter->sessionId);
5197 return -EINVAL;
5198 }
5199
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305201 if (ret)
5202 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203
5204 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005205 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206 return -ENOTSUPP;
5207 }
5208
5209 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 return -EINVAL;
5212 }
5213
5214 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005215 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 return -EINVAL;
5217 }
5218
5219 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005220 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005221 return -EINVAL;
5222 }
5223
5224 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5225 req.session_id = adapter->sessionId;
5226 control = nla_get_u32(tb[PARAM_CONTROL]);
5227
5228 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5229 req.control = true;
5230 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005231 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232 return -EINVAL;
5233 }
5234
5235 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005236 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237 return -EINVAL;
5238 }
5239
5240 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5241 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5242
5243 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005244 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 req.min_rssi, req.max_rssi);
5246 return -EINVAL;
5247 }
Jeff Johnson77848112016-06-29 14:52:06 -07005248 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249 req.min_rssi, req.max_rssi);
5250
5251 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5252 req.control = false;
5253 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005254 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 return -EINVAL;
5256 }
Jeff Johnson77848112016-06-29 14:52:06 -07005257 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005258 req.request_id, req.session_id, req.control);
5259
5260 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305261 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005262 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263 return -EINVAL;
5264 }
5265
5266 return 0;
5267}
5268
5269/*
5270 * done with short names for the global vendor params
5271 * used by __wlan_hdd_cfg80211_monitor_rssi()
5272 */
5273#undef PARAM_MAX
5274#undef PARAM_CONTROL
5275#undef PARAM_REQUEST_ID
5276#undef PARAM_MAX_RSSI
5277#undef PARAM_MIN_RSSI
5278
5279/**
5280 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5281 * @wiphy: wiphy structure pointer
5282 * @wdev: Wireless device structure pointer
5283 * @data: Pointer to the data received
5284 * @data_len: Length of @data
5285 *
5286 * Return: 0 on success; errno on failure
5287 */
5288static int
5289wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5290 const void *data, int data_len)
5291{
5292 int ret;
5293
5294 cds_ssr_protect(__func__);
5295 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5296 cds_ssr_unprotect(__func__);
5297
5298 return ret;
5299}
5300
5301/**
5302 * hdd_rssi_threshold_breached() - rssi breached NL event
5303 * @hddctx: HDD context
5304 * @data: rssi breached event data
5305 *
5306 * This function reads the rssi breached event %data and fill in the skb with
5307 * NL attributes and send up the NL event.
5308 *
5309 * Return: none
5310 */
5311void hdd_rssi_threshold_breached(void *hddctx,
5312 struct rssi_breach_event *data)
5313{
5314 hdd_context_t *hdd_ctx = hddctx;
5315 struct sk_buff *skb;
5316
5317 ENTER();
5318
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305319 if (wlan_hdd_validate_context(hdd_ctx))
5320 return;
5321 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005322 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005323 return;
5324 }
5325
5326 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5327 NULL,
5328 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5329 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5330 GFP_KERNEL);
5331
5332 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005333 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 return;
5335 }
5336
Jeff Johnson77848112016-06-29 14:52:06 -07005337 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005339 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5341
5342 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5343 data->request_id) ||
5344 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5345 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5346 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5347 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005348 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 goto fail;
5350 }
5351
5352 cfg80211_vendor_event(skb, GFP_KERNEL);
5353 return;
5354
5355fail:
5356 kfree_skb(skb);
5357 return;
5358}
5359
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305360static const struct nla_policy
5361ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5362 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5363};
5364
5365/**
5366 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5367 * @wiphy: Pointer to wireless phy
5368 * @wdev: Pointer to wireless device
5369 * @data: Pointer to data
5370 * @data_len: Length of @data
5371 *
5372 * Return: 0 on success, negative errno on failure
5373 */
5374static int
5375__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5376 struct wireless_dev *wdev,
5377 const void *data, int data_len)
5378{
5379 int status;
5380 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5381 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005382 struct net_device *dev = wdev->netdev;
5383 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305384
5385 ENTER_DEV(wdev->netdev);
5386
5387 status = wlan_hdd_validate_context(pHddCtx);
5388 if (0 != status)
5389 return status;
5390 if (!pHddCtx->config->fhostNSOffload) {
5391 hdd_err("ND Offload not supported");
5392 return -EINVAL;
5393 }
5394
5395 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5396 (struct nlattr *)data,
5397 data_len, ns_offload_set_policy)) {
5398 hdd_err("nla_parse failed");
5399 return -EINVAL;
5400 }
5401
5402 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5403 hdd_err("ND Offload flag attribute not present");
5404 return -EINVAL;
5405 }
5406
5407 pHddCtx->ns_offload_enable =
5408 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5409
Dustin Brownd8279d22016-09-07 14:52:57 -07005410 /* update ns offload in case it is already enabled/disabled */
5411 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5412
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305413 return 0;
5414}
5415
5416/**
5417 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5418 * @wiphy: pointer to wireless wiphy structure.
5419 * @wdev: pointer to wireless_dev structure.
5420 * @data: Pointer to the data to be passed via vendor interface
5421 * @data_len:Length of the data to be passed
5422 *
5423 * Return: Return the Success or Failure code.
5424 */
5425static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5426 struct wireless_dev *wdev,
5427 const void *data, int data_len)
5428{
5429 int ret;
5430
5431 cds_ssr_protect(__func__);
5432 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5433 cds_ssr_unprotect(__func__);
5434
5435 return ret;
5436}
5437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5439 * @wiphy: Pointer to wireless phy
5440 * @wdev: Pointer to wireless device
5441 * @data: Pointer to data
5442 * @data_len: Data length
5443 *
5444 * This function return the preferred frequency list generated by the policy
5445 * manager.
5446 *
5447 * Return: success or failure code
5448 */
5449static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5450 struct wireless_dev
5451 *wdev, const void *data,
5452 int data_len)
5453{
5454 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5455 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305456 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305457 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305459 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460 enum cds_con_mode intf_mode;
5461 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5462 struct sk_buff *reply_skb;
5463
Jeff Johnson1f61b612016-02-12 16:28:33 -08005464 ENTER_DEV(wdev->netdev);
5465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005466 ret = wlan_hdd_validate_context(hdd_ctx);
5467 if (ret)
5468 return -EINVAL;
5469
5470 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5471 data, data_len, NULL)) {
5472 hdd_err("Invalid ATTR");
5473 return -EINVAL;
5474 }
5475
5476 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5477 hdd_err("attr interface type failed");
5478 return -EINVAL;
5479 }
5480
5481 intf_mode = nla_get_u32(tb
5482 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5483
5484 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5485 hdd_err("Invalid interface type");
5486 return -EINVAL;
5487 }
5488
5489 hdd_debug("Userspace requested pref freq list");
5490
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305491 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5492 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305493 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005494 hdd_err("Get pcl failed");
5495 return -EINVAL;
5496 }
5497
5498 /* convert channel number to frequency */
5499 for (i = 0; i < pcl_len; i++) {
5500 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5501 freq_list[i] =
5502 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005503 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005504 else
5505 freq_list[i] =
5506 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005507 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005508 }
5509
5510 /* send the freq_list back to supplicant */
5511 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5512 sizeof(u32) *
5513 pcl_len +
5514 NLMSG_HDRLEN);
5515
5516 if (!reply_skb) {
5517 hdd_err("Allocate reply_skb failed");
5518 return -EINVAL;
5519 }
5520
5521 if (nla_put_u32(reply_skb,
5522 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5523 intf_mode) ||
5524 nla_put(reply_skb,
5525 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5526 sizeof(uint32_t) * pcl_len,
5527 freq_list)) {
5528 hdd_err("nla put fail");
5529 kfree_skb(reply_skb);
5530 return -EINVAL;
5531 }
5532
5533 return cfg80211_vendor_cmd_reply(reply_skb);
5534}
5535
5536/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5537 * @wiphy: Pointer to wireless phy
5538 * @wdev: Pointer to wireless device
5539 * @data: Pointer to data
5540 * @data_len: Data length
5541 *
5542 * This function return the preferred frequency list generated by the policy
5543 * manager.
5544 *
5545 * Return: success or failure code
5546 */
5547static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5548 struct wireless_dev
5549 *wdev, const void *data,
5550 int data_len)
5551{
5552 int ret = 0;
5553
5554 cds_ssr_protect(__func__);
5555 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5556 data, data_len);
5557 cds_ssr_unprotect(__func__);
5558
5559 return ret;
5560}
5561
5562/**
5563 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5564 * @wiphy: Pointer to wireless phy
5565 * @wdev: Pointer to wireless device
5566 * @data: Pointer to data
5567 * @data_len: Data length
5568 *
5569 * Return: 0 on success, negative errno on failure
5570 */
5571static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5572 struct wireless_dev *wdev,
5573 const void *data,
5574 int data_len)
5575{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305576 struct net_device *ndev = wdev->netdev;
5577 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5579 int ret = 0;
5580 enum cds_con_mode intf_mode;
5581 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5582 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583
Jeff Johnson1f61b612016-02-12 16:28:33 -08005584 ENTER_DEV(ndev);
5585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586 ret = wlan_hdd_validate_context(hdd_ctx);
5587 if (ret)
5588 return ret;
5589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5591 data, data_len, NULL)) {
5592 hdd_err("Invalid ATTR");
5593 return -EINVAL;
5594 }
5595
5596 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5597 hdd_err("attr interface type failed");
5598 return -EINVAL;
5599 }
5600
5601 intf_mode = nla_get_u32(tb
5602 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5603
5604 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5605 hdd_err("Invalid interface type");
5606 return -EINVAL;
5607 }
5608
5609 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5610 hdd_err("attr probable freq failed");
5611 return -EINVAL;
5612 }
5613
5614 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5615 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5616
5617 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005618 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619 channel_hint, HW_MODE_20_MHZ)) {
5620 hdd_err("Set channel hint failed due to concurrency check");
5621 return -EINVAL;
5622 }
5623
Krunal Soni09e55032016-06-07 10:06:55 -07005624 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5625 hdd_warn("Remain On Channel Pending");
5626
Krunal Soni3091bcc2016-06-23 12:28:21 -07005627 ret = qdf_reset_connection_update();
5628 if (!QDF_IS_STATUS_SUCCESS(ret))
5629 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630
Krunal Soni3091bcc2016-06-23 12:28:21 -07005631 ret = cds_current_connections_update(adapter->sessionId,
5632 channel_hint,
5633 SIR_UPDATE_REASON_SET_OPER_CHAN);
5634 if (QDF_STATUS_E_FAILURE == ret) {
5635 /* return in the failure case */
5636 hdd_err("ERROR: connections update failed!!");
5637 return -EINVAL;
5638 }
5639
5640 if (QDF_STATUS_SUCCESS == ret) {
5641 /*
5642 * Success is the only case for which we expect hw mode
5643 * change to take place, hence we need to wait.
5644 * For any other return value it should be a pass
5645 * through
5646 */
5647 ret = qdf_wait_for_connection_update();
5648 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5649 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 return -EINVAL;
5651 }
5652
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653 }
5654
5655 return 0;
5656}
5657
5658/**
5659 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5660 * @wiphy: Pointer to wireless phy
5661 * @wdev: Pointer to wireless device
5662 * @data: Pointer to data
5663 * @data_len: Data length
5664 *
5665 * Return: 0 on success, negative errno on failure
5666 */
5667static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5668 struct wireless_dev *wdev,
5669 const void *data,
5670 int data_len)
5671{
5672 int ret = 0;
5673
5674 cds_ssr_protect(__func__);
5675 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5676 data, data_len);
5677 cds_ssr_unprotect(__func__);
5678
5679 return ret;
5680}
5681
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305682static const struct
5683nla_policy
5684qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5685 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5686};
5687
5688/**
5689 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5690 * @wiphy: WIPHY structure pointer
5691 * @wdev: Wireless device structure pointer
5692 * @data: Pointer to the data received
5693 * @data_len: Length of the data received
5694 *
5695 * This function is used to get link properties like nss, rate flags and
5696 * operating frequency for the active connection with the given peer.
5697 *
5698 * Return: 0 on success and errno on failure
5699 */
5700static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5701 struct wireless_dev *wdev,
5702 const void *data,
5703 int data_len)
5704{
5705 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5706 struct net_device *dev = wdev->netdev;
5707 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5708 hdd_station_ctx_t *hdd_sta_ctx;
5709 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305710 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305711 uint32_t sta_id;
5712 struct sk_buff *reply_skb;
5713 uint32_t rate_flags = 0;
5714 uint8_t nss;
5715 uint8_t final_rate_flags = 0;
5716 uint32_t freq;
5717
Jeff Johnson1f61b612016-02-12 16:28:33 -08005718 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305719
Anurag Chouhan6d760662016-02-20 16:05:43 +05305720 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305721 hdd_err("Command not allowed in FTM mode");
5722 return -EPERM;
5723 }
5724
5725 if (0 != wlan_hdd_validate_context(hdd_ctx))
5726 return -EINVAL;
5727
5728 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5729 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005730 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305731 return -EINVAL;
5732 }
5733
5734 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005735 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305736 adapter->device_mode);
5737 return -EINVAL;
5738 }
5739
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305740 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305741 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005742 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305743 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5744
Krunal Sonib4326f22016-03-10 13:05:51 -08005745 if (adapter->device_mode == QDF_STA_MODE ||
5746 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305747 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5748 if ((hdd_sta_ctx->conn_info.connState !=
5749 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305750 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305751 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005752 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305753 MAC_ADDR_ARRAY(peer_mac));
5754 return -EINVAL;
5755 }
5756
5757 nss = hdd_sta_ctx->conn_info.nss;
5758 freq = cds_chan_to_freq(
5759 hdd_sta_ctx->conn_info.operationChannel);
5760 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005761 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5762 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305763
5764 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5765 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305766 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305767 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305768 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305769 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305770 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305771 break;
5772 }
5773
5774 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005775 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305776 MAC_ADDR_ARRAY(peer_mac));
5777 return -EINVAL;
5778 }
5779
5780 nss = adapter->aStaInfo[sta_id].nss;
5781 freq = cds_chan_to_freq(
5782 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5783 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5784 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005785 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305786 MAC_ADDR_ARRAY(peer_mac));
5787 return -EINVAL;
5788 }
5789
5790 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5791 if (rate_flags & eHAL_TX_RATE_VHT80) {
5792 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005793#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305794 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005795#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305796 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5797 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005798#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305799 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005800#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305801 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5802 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5803 } else if (rate_flags &
5804 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5805 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005806#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305807 if (rate_flags & eHAL_TX_RATE_HT40)
5808 final_rate_flags |=
5809 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005810#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305811 }
5812
5813 if (rate_flags & eHAL_TX_RATE_SGI) {
5814 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5815 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5816 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5817 }
5818 }
5819
5820 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5821 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5822
5823 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005824 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305825 return -EINVAL;
5826 }
5827
5828 if (nla_put_u8(reply_skb,
5829 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5830 nss) ||
5831 nla_put_u8(reply_skb,
5832 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5833 final_rate_flags) ||
5834 nla_put_u32(reply_skb,
5835 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5836 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005837 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305838 kfree_skb(reply_skb);
5839 return -EINVAL;
5840 }
5841
5842 return cfg80211_vendor_cmd_reply(reply_skb);
5843}
5844
5845/**
5846 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5847 * properties.
5848 * @wiphy: WIPHY structure pointer
5849 * @wdev: Wireless device structure pointer
5850 * @data: Pointer to the data received
5851 * @data_len: Length of the data received
5852 *
5853 * This function is used to get link properties like nss, rate flags and
5854 * operating frequency for the active connection with the given peer.
5855 *
5856 * Return: 0 on success and errno on failure
5857 */
5858static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5859 struct wireless_dev *wdev,
5860 const void *data,
5861 int data_len)
5862{
5863 int ret = 0;
5864
5865 cds_ssr_protect(__func__);
5866 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5867 wdev, data, data_len);
5868 cds_ssr_unprotect(__func__);
5869
5870 return ret;
5871}
5872
Peng Xu278d0122015-09-24 16:34:17 -07005873static const struct
5874nla_policy
5875qca_wlan_vendor_ota_test_policy
5876[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5877 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5878};
5879
5880/**
5881 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5882 * @wiphy: Pointer to wireless phy
5883 * @wdev: Pointer to wireless device
5884 * @data: Pointer to data
5885 * @data_len: Data length
5886 *
5887 * Return: 0 on success, negative errno on failure
5888 */
5889static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5890 struct wireless_dev *wdev,
5891 const void *data,
5892 int data_len)
5893{
5894 struct net_device *dev = wdev->netdev;
5895 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5896 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5897 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5898 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5899 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305900 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005901 uint32_t current_roam_state;
5902
Jeff Johnson1f61b612016-02-12 16:28:33 -08005903 ENTER_DEV(dev);
5904
Anurag Chouhan6d760662016-02-20 16:05:43 +05305905 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005906 hdd_err("Command not allowed in FTM mode");
5907 return -EPERM;
5908 }
5909
5910 if (0 != wlan_hdd_validate_context(hdd_ctx))
5911 return -EINVAL;
5912
5913 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5914 data, data_len,
5915 qca_wlan_vendor_ota_test_policy)) {
5916 hdd_err("invalid attr");
5917 return -EINVAL;
5918 }
5919
5920 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5921 hdd_err("attr ota test failed");
5922 return -EINVAL;
5923 }
5924
5925 ota_enable = nla_get_u8(
5926 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5927
5928 hdd_info(" OTA test enable = %d", ota_enable);
5929 if (ota_enable != 1) {
5930 hdd_err("Invalid value, only enable test mode is supported!");
5931 return -EINVAL;
5932 }
5933
5934 current_roam_state =
5935 sme_get_current_roam_state(hal, adapter->sessionId);
5936 status = sme_stop_roaming(hal, adapter->sessionId,
5937 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305938 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005939 hdd_err("Enable/Disable roaming failed");
5940 return -EINVAL;
5941 }
5942
5943 status = sme_ps_enable_disable(hal, adapter->sessionId,
5944 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305945 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005946 hdd_err("Enable/Disable power save failed");
5947 /* restore previous roaming setting */
5948 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5949 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5950 status = sme_start_roaming(hal, adapter->sessionId,
5951 eCsrHddIssued);
5952 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5953 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5954 status = sme_stop_roaming(hal, adapter->sessionId,
5955 eCsrHddIssued);
5956
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305957 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005958 hdd_err("Restoring roaming state failed");
5959
5960 return -EINVAL;
5961 }
5962
5963
5964 return 0;
5965}
5966
5967/**
5968 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5969 * @wiphy: Pointer to wireless phy
5970 * @wdev: Pointer to wireless device
5971 * @data: Pointer to data
5972 * @data_len: Data length
5973 *
5974 * Return: 0 on success, negative errno on failure
5975 */
5976static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5977 struct wireless_dev *wdev,
5978 const void *data,
5979 int data_len)
5980{
5981 int ret = 0;
5982
5983 cds_ssr_protect(__func__);
5984 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5985 cds_ssr_unprotect(__func__);
5986
5987 return ret;
5988}
5989
Peng Xu4d67c8f2015-10-16 16:02:26 -07005990/**
5991 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5992 * @wiphy: Pointer to wireless phy
5993 * @wdev: Pointer to wireless device
5994 * @data: Pointer to data
5995 * @data_len: Data length
5996 *
5997 * Return: 0 on success, negative errno on failure
5998 */
5999static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6000 struct wireless_dev *wdev,
6001 const void *data,
6002 int data_len)
6003{
6004 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6005 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006006 hdd_adapter_t *adapter;
6007 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006008 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6009 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006010 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006011
Jeff Johnson1f61b612016-02-12 16:28:33 -08006012 ENTER_DEV(dev);
6013
Peng Xu4d67c8f2015-10-16 16:02:26 -07006014 ret = wlan_hdd_validate_context(hdd_ctx);
6015 if (ret)
6016 return ret;
6017
6018 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6019
6020 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6021 data, data_len, NULL)) {
6022 hdd_err("Invalid ATTR");
6023 return -EINVAL;
6024 }
6025
6026 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6027 hdd_err("attr tx power scale failed");
6028 return -EINVAL;
6029 }
6030
6031 scale_value = nla_get_u8(tb
6032 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6033
6034 if (scale_value > MAX_TXPOWER_SCALE) {
6035 hdd_err("Invalid tx power scale level");
6036 return -EINVAL;
6037 }
6038
Peng Xu62c8c432016-05-09 15:23:02 -07006039 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006040
Peng Xu62c8c432016-05-09 15:23:02 -07006041 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006042 hdd_err("Set tx power scale failed");
6043 return -EINVAL;
6044 }
6045
6046 return 0;
6047}
6048
6049/**
6050 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6051 * @wiphy: Pointer to wireless phy
6052 * @wdev: Pointer to wireless device
6053 * @data: Pointer to data
6054 * @data_len: Data length
6055 *
6056 * Return: 0 on success, negative errno on failure
6057 */
6058static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6059 struct wireless_dev *wdev,
6060 const void *data,
6061 int data_len)
6062{
Peng Xu62c8c432016-05-09 15:23:02 -07006063 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006064
6065 cds_ssr_protect(__func__);
6066 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6067 data, data_len);
6068 cds_ssr_unprotect(__func__);
6069
6070 return ret;
6071}
6072
6073/**
6074 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6075 * @wiphy: Pointer to wireless phy
6076 * @wdev: Pointer to wireless device
6077 * @data: Pointer to data
6078 * @data_len: Data length
6079 *
6080 * Return: 0 on success, negative errno on failure
6081 */
6082static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6083 struct wireless_dev *wdev,
6084 const void *data,
6085 int data_len)
6086{
6087 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6088 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006089 hdd_adapter_t *adapter;
6090 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006091 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6092 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006093 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006094
Jeff Johnson1f61b612016-02-12 16:28:33 -08006095 ENTER_DEV(dev);
6096
Peng Xu4d67c8f2015-10-16 16:02:26 -07006097 ret = wlan_hdd_validate_context(hdd_ctx);
6098 if (ret)
6099 return ret;
6100
6101 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6102
6103 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6104 data, data_len, NULL)) {
6105 hdd_err("Invalid ATTR");
6106 return -EINVAL;
6107 }
6108
6109 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6110 hdd_err("attr tx power decrease db value failed");
6111 return -EINVAL;
6112 }
6113
6114 scale_value = nla_get_u8(tb
6115 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6116
Peng Xu62c8c432016-05-09 15:23:02 -07006117 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6118 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006119
Peng Xu62c8c432016-05-09 15:23:02 -07006120 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006121 hdd_err("Set tx power decrease db failed");
6122 return -EINVAL;
6123 }
6124
6125 return 0;
6126}
6127
6128/**
6129 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6130 * @wiphy: Pointer to wireless phy
6131 * @wdev: Pointer to wireless device
6132 * @data: Pointer to data
6133 * @data_len: Data length
6134 *
6135 * Return: 0 on success, negative errno on failure
6136 */
6137static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6138 struct wireless_dev *wdev,
6139 const void *data,
6140 int data_len)
6141{
Peng Xu62c8c432016-05-09 15:23:02 -07006142 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006143
6144 cds_ssr_protect(__func__);
6145 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6146 data, data_len);
6147 cds_ssr_unprotect(__func__);
6148
6149 return ret;
6150}
Peng Xu8fdaa492016-06-22 10:20:47 -07006151
6152/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306153 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6154 * @wiphy: Pointer to wireless phy
6155 * @wdev: Pointer to wireless device
6156 * @data: Pointer to data
6157 * @data_len: Data length
6158 *
6159 * Processes the conditional channel switch request and invokes the helper
6160 * APIs to process the channel switch request.
6161 *
6162 * Return: 0 on success, negative errno on failure
6163 */
6164static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6165 struct wireless_dev *wdev,
6166 const void *data,
6167 int data_len)
6168{
6169 int ret;
6170 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6171 struct net_device *dev = wdev->netdev;
6172 hdd_adapter_t *adapter;
6173 struct nlattr
6174 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6175 uint32_t freq_len, i;
6176 uint32_t *freq;
6177 uint8_t chans[QDF_MAX_NUM_CHAN];
6178
6179 ENTER_DEV(dev);
6180
6181 ret = wlan_hdd_validate_context(hdd_ctx);
6182 if (ret)
6183 return ret;
6184
6185 if (!hdd_ctx->config->enableDFSMasterCap) {
6186 hdd_err("DFS master capability is not present in the driver");
6187 return -EINVAL;
6188 }
6189
6190 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6191 hdd_err("Command not allowed in FTM mode");
6192 return -EPERM;
6193 }
6194
6195 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6196 if (adapter->device_mode != QDF_SAP_MODE) {
6197 hdd_err("Invalid device mode %d", adapter->device_mode);
6198 return -EINVAL;
6199 }
6200
6201 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6202 data, data_len, NULL)) {
6203 hdd_err("Invalid ATTR");
6204 return -EINVAL;
6205 }
6206
6207 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6208 hdd_err("Frequency list is missing");
6209 return -EINVAL;
6210 }
6211
6212 freq_len = nla_len(
6213 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6214 sizeof(uint32_t);
6215
6216 if (freq_len > QDF_MAX_NUM_CHAN) {
6217 hdd_err("insufficient space to hold channels");
6218 return -ENOMEM;
6219 }
6220
6221 hdd_debug("freq_len=%d", freq_len);
6222
6223 freq = nla_data(
6224 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6225
6226
6227 for (i = 0; i < freq_len; i++) {
6228 if (freq[i] == 0)
6229 chans[i] = 0;
6230 else
6231 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6232
6233 hdd_debug("freq[%d]=%d", i, freq[i]);
6234 }
6235
6236 /*
6237 * The input frequency list from user space is designed to be a
6238 * priority based frequency list. This is only to accommodate any
6239 * future request. But, current requirement is only to perform CAC
6240 * on a single channel. So, the first entry from the list is picked.
6241 *
6242 * If channel is zero, any channel in the available outdoor regulatory
6243 * domain will be selected.
6244 */
6245 ret = wlan_hdd_request_pre_cac(chans[0]);
6246 if (ret) {
6247 hdd_err("pre cac request failed with reason:%d", ret);
6248 return ret;
6249 }
6250
6251 return 0;
6252}
6253
6254/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006255 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6256 * @wiphy: Pointer to wireless phy
6257 * @wdev: Pointer to wireless device
6258 * @data: Pointer to data
6259 * @data_len: Data length
6260 *
6261 * This function is to process the p2p listen offload start vendor
6262 * command. It parses the input parameters and invoke WMA API to
6263 * send the command to firmware.
6264 *
6265 * Return: 0 on success, negative errno on failure
6266 */
6267static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6268 struct wireless_dev *wdev,
6269 const void *data,
6270 int data_len)
6271{
6272 int ret;
6273 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6274 struct net_device *dev = wdev->netdev;
6275 hdd_adapter_t *adapter;
6276 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6277 struct sir_p2p_lo_start params;
6278 QDF_STATUS status;
6279
6280 ENTER_DEV(dev);
6281
6282 ret = wlan_hdd_validate_context(hdd_ctx);
6283 if (ret)
6284 return ret;
6285
6286 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6287 hdd_err("Command not allowed in FTM mode");
6288 return -EPERM;
6289 }
6290
6291 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6292 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6293 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6294 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6295 hdd_err("Invalid device mode %d", adapter->device_mode);
6296 return -EINVAL;
6297 }
6298
6299 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6300 data, data_len, NULL)) {
6301 hdd_err("Invalid ATTR");
6302 return -EINVAL;
6303 }
6304
6305 memset(&params, 0, sizeof(params));
6306
6307 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6308 params.ctl_flags = 1; /* set to default value */
6309 else
6310 params.ctl_flags = nla_get_u32(tb
6311 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6312
6313 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6314 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6315 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6316 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6317 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6318 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6319 hdd_err("Attribute parsing failed");
6320 return -EINVAL;
6321 }
6322
6323 params.vdev_id = adapter->sessionId;
6324 params.freq = nla_get_u32(tb
6325 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6326 if ((params.freq != 2412) && (params.freq != 2437) &&
6327 (params.freq != 2462)) {
6328 hdd_err("Invalid listening channel: %d", params.freq);
6329 return -EINVAL;
6330 }
6331
6332 params.period = nla_get_u32(tb
6333 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6334 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6335 hdd_err("Invalid period: %d", params.period);
6336 return -EINVAL;
6337 }
6338
6339 params.interval = nla_get_u32(tb
6340 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6341 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6342 hdd_err("Invalid interval: %d", params.interval);
6343 return -EINVAL;
6344 }
6345
6346 params.count = nla_get_u32(tb
6347 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006348 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006349 hdd_err("Invalid count: %d", params.count);
6350 return -EINVAL;
6351 }
6352
6353 params.device_types = nla_data(tb
6354 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6355 if (params.device_types == NULL) {
6356 hdd_err("Invalid device types");
6357 return -EINVAL;
6358 }
6359
6360 params.dev_types_len = nla_len(tb
6361 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6362 if (params.dev_types_len < 8) {
6363 hdd_err("Invalid device type length: %d", params.dev_types_len);
6364 return -EINVAL;
6365 }
6366
6367 params.probe_resp_tmplt = nla_data(tb
6368 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6369 if (params.probe_resp_tmplt == NULL) {
6370 hdd_err("Invalid probe response template");
6371 return -EINVAL;
6372 }
6373
6374 params.probe_resp_len = nla_len(tb
6375 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6376 if (params.probe_resp_len == 0) {
6377 hdd_err("Invalid probe resp template length: %d",
6378 params.probe_resp_len);
6379 return -EINVAL;
6380 }
6381
6382 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6383 params.freq, params.period, params.interval, params.count);
6384
6385 status = wma_p2p_lo_start(&params);
6386
6387 if (!QDF_IS_STATUS_SUCCESS(status)) {
6388 hdd_err("P2P LO start failed");
6389 return -EINVAL;
6390 }
6391
6392 return 0;
6393}
6394
6395
6396/**
6397 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6398 * @wiphy: Pointer to wireless phy
6399 * @wdev: Pointer to wireless device
6400 * @data: Pointer to data
6401 * @data_len: Data length
6402 *
6403 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6404 * to process p2p listen offload start vendor command.
6405 *
6406 * Return: 0 on success, negative errno on failure
6407 */
6408static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6409 struct wireless_dev *wdev,
6410 const void *data,
6411 int data_len)
6412{
6413 int ret = 0;
6414
6415 cds_ssr_protect(__func__);
6416 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6417 data, data_len);
6418 cds_ssr_unprotect(__func__);
6419
6420 return ret;
6421}
6422
6423/**
6424 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6425 * @wiphy: Pointer to wireless phy
6426 * @wdev: Pointer to wireless device
6427 * @data: Pointer to data
6428 * @data_len: Data length
6429 *
6430 * This function is to process the p2p listen offload stop vendor
6431 * command. It invokes WMA API to send command to firmware.
6432 *
6433 * Return: 0 on success, negative errno on failure
6434 */
6435static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6436 struct wireless_dev *wdev,
6437 const void *data,
6438 int data_len)
6439{
6440 QDF_STATUS status;
6441 hdd_adapter_t *adapter;
6442 struct net_device *dev = wdev->netdev;
6443
6444 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6445 hdd_err("Command not allowed in FTM mode");
6446 return -EPERM;
6447 }
6448
6449 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6450 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6451 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6452 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6453 hdd_err("Invalid device mode");
6454 return -EINVAL;
6455 }
6456
6457 status = wma_p2p_lo_stop(adapter->sessionId);
6458
6459 if (!QDF_IS_STATUS_SUCCESS(status)) {
6460 hdd_err("P2P LO stop failed");
6461 return -EINVAL;
6462 }
6463
6464 return 0;
6465}
6466
6467/**
6468 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6469 * @wiphy: Pointer to wireless phy
6470 * @wdev: Pointer to wireless device
6471 * @data: Pointer to data
6472 * @data_len: Data length
6473 *
6474 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6475 * to process p2p listen offload stop vendor command.
6476 *
6477 * Return: 0 on success, negative errno on failure
6478 */
6479static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6480 struct wireless_dev *wdev,
6481 const void *data,
6482 int data_len)
6483{
6484 int ret = 0;
6485
6486 cds_ssr_protect(__func__);
6487 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6488 data, data_len);
6489 cds_ssr_unprotect(__func__);
6490
6491 return ret;
6492}
6493
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306494/**
6495 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6496 * @wiphy: Pointer to wireless phy
6497 * @wdev: Pointer to wireless device
6498 * @data: Pointer to data
6499 * @data_len: Data length
6500 *
6501 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6502 * to process the conditional channel switch request.
6503 *
6504 * Return: 0 on success, negative errno on failure
6505 */
6506static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6507 struct wireless_dev *wdev,
6508 const void *data,
6509 int data_len)
6510{
6511 int ret;
6512
6513 cds_ssr_protect(__func__);
6514 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6515 data, data_len);
6516 cds_ssr_unprotect(__func__);
6517
6518 return ret;
6519}
6520
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306521/*
6522 * define short names for the global vendor params
6523 * used by __wlan_hdd_cfg80211_bpf_offload()
6524 */
6525#define BPF_INVALID \
6526 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6527#define BPF_SET_RESET \
6528 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6529#define BPF_VERSION \
6530 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6531#define BPF_FILTER_ID \
6532 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6533#define BPF_PACKET_SIZE \
6534 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6535#define BPF_CURRENT_OFFSET \
6536 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6537#define BPF_PROGRAM \
6538 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6539#define BPF_MAX \
6540 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006541
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306542static const struct nla_policy
6543wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6544 [BPF_SET_RESET] = {.type = NLA_U32},
6545 [BPF_VERSION] = {.type = NLA_U32},
6546 [BPF_FILTER_ID] = {.type = NLA_U32},
6547 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6548 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6549 [BPF_PROGRAM] = {.type = NLA_U8},
6550};
6551
6552/**
6553 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6554 * @hdd_context: hdd_context
6555 * @bpf_get_offload: struct for get offload
6556 *
6557 * This function receives the response/data from the lower layer and
6558 * checks to see if the thread is still waiting then post the results to
6559 * upper layer, if the request has timed out then ignore.
6560 *
6561 * Return: None
6562 */
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006563static void hdd_get_bpf_offload_cb(void *hdd_context,
6564 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306565{
6566 hdd_context_t *hdd_ctx = hdd_context;
6567 struct hdd_bpf_context *context;
6568
6569 ENTER();
6570
6571 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006572 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306573 data);
6574 return;
6575 }
6576
6577 spin_lock(&hdd_context_lock);
6578
6579 context = &bpf_context;
6580 /* The caller presumably timed out so there is nothing we can do */
6581 if (context->magic != BPF_CONTEXT_MAGIC) {
6582 spin_unlock(&hdd_context_lock);
6583 return;
6584 }
6585
6586 /* context is valid so caller is still waiting */
6587 /* paranoia: invalidate the magic */
6588 context->magic = 0;
6589
6590 context->capability_response = *data;
6591 complete(&context->completion);
6592
6593 spin_unlock(&hdd_context_lock);
6594
6595 return;
6596}
6597
6598/**
6599 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6600 * @hdd_context: hdd_context
6601 * @bpf_get_offload: struct for get offload
6602 *
6603 * Return: 0 on success, error number otherwise.
6604 */
6605static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6606 struct sir_bpf_get_offload *bpf_get_offload)
6607{
6608 struct sk_buff *skb;
6609 uint32_t nl_buf_len;
6610
6611 ENTER();
6612
6613 nl_buf_len = NLMSG_HDRLEN;
6614 nl_buf_len +=
6615 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6616 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6617
6618 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6619 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006620 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306621 return -ENOMEM;
6622 }
6623
Jeff Johnson77848112016-06-29 14:52:06 -07006624 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306625 bpf_get_offload->bpf_version,
6626 bpf_get_offload->max_bytes_for_bpf_inst);
6627
6628 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6629 bpf_get_offload->max_bytes_for_bpf_inst) ||
6630 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006631 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306632 goto nla_put_failure;
6633 }
6634
6635 cfg80211_vendor_cmd_reply(skb);
6636 EXIT();
6637 return 0;
6638
6639nla_put_failure:
6640 kfree_skb(skb);
6641 return -EINVAL;
6642}
6643
6644/**
6645 * hdd_get_bpf_offload - Get BPF offload Capabilities
6646 * @hdd_ctx: Hdd context
6647 *
6648 * Return: 0 on success, errno on failure
6649 */
6650static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6651{
6652 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006653 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306654 QDF_STATUS status;
6655 int ret;
6656
6657 ENTER();
6658
6659 spin_lock(&hdd_context_lock);
6660 context = &bpf_context;
6661 context->magic = BPF_CONTEXT_MAGIC;
6662 INIT_COMPLETION(context->completion);
6663 spin_unlock(&hdd_context_lock);
6664
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006665 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6666 hdd_get_bpf_offload_cb,
6667 hdd_ctx);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306668 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006669 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306670 return -EINVAL;
6671 }
6672 /* request was sent -- wait for the response */
6673 rc = wait_for_completion_timeout(&context->completion,
6674 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6675 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006676 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306677 spin_lock(&hdd_context_lock);
6678 context->magic = 0;
6679 spin_unlock(&hdd_context_lock);
6680
6681 return -ETIMEDOUT;
6682 }
6683 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6684 &bpf_context.capability_response);
6685 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006686 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306687
6688 EXIT();
6689 return ret;
6690}
6691
6692/**
6693 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6694 * @hdd_ctx: Hdd context
6695 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306696 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306697 *
6698 * Return: 0 on success; errno on failure
6699 */
6700static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6701 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306702 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306703{
6704 struct sir_bpf_set_offload *bpf_set_offload;
6705 QDF_STATUS status;
6706 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306707 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306708
6709 ENTER();
6710
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306711 if (adapter->device_mode == QDF_STA_MODE ||
6712 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6713 if (!hdd_conn_is_connected(
6714 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6715 hdd_err("Not in Connected state!");
6716 return -ENOTSUPP;
6717 }
6718 }
6719
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306720 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6721 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006722 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306723 return -ENOMEM;
6724 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306725
6726 /* Parse and fetch bpf packet size */
6727 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006728 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306729 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306730 goto fail;
6731 }
6732 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6733
6734 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006735 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306736 goto post_sme;
6737 }
6738
6739 /* Parse and fetch bpf program */
6740 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006741 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306742 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306743 goto fail;
6744 }
6745
6746 prog_len = nla_len(tb[BPF_PROGRAM]);
6747 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306748
6749 if (bpf_set_offload->program == NULL) {
6750 hdd_err("qdf_mem_malloc failed for bpf offload program");
6751 ret = -ENOMEM;
6752 goto fail;
6753 }
6754
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306755 bpf_set_offload->current_length = prog_len;
6756 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306757 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306758
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306759 hdd_info("BPF set instructions");
6760 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6761 bpf_set_offload->program, prog_len);
6762
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306763 /* Parse and fetch filter Id */
6764 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006765 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306766 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306767 goto fail;
6768 }
6769 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6770
6771 /* Parse and fetch current offset */
6772 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006773 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306774 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306775 goto fail;
6776 }
6777 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6778
6779post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006780 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 +05306781 bpf_set_offload->session_id,
6782 bpf_set_offload->version,
6783 bpf_set_offload->filter_id,
6784 bpf_set_offload->total_length,
6785 bpf_set_offload->current_length,
6786 bpf_set_offload->current_offset);
6787
6788 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6789 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006790 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306791 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306792 goto fail;
6793 }
6794 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306795
6796fail:
6797 if (bpf_set_offload->current_length)
6798 qdf_mem_free(bpf_set_offload->program);
6799 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306800 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306801}
6802
6803/**
6804 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6805 * @wiphy: wiphy structure pointer
6806 * @wdev: Wireless device structure pointer
6807 * @data: Pointer to the data received
6808 * @data_len: Length of @data
6809 *
6810 * Return: 0 on success; errno on failure
6811 */
6812static int
6813__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6814 struct wireless_dev *wdev,
6815 const void *data, int data_len)
6816{
6817 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6818 struct net_device *dev = wdev->netdev;
6819 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6820 struct nlattr *tb[BPF_MAX + 1];
6821 int ret_val, packet_filter_subcmd;
6822
6823 ENTER();
6824
6825 ret_val = wlan_hdd_validate_context(hdd_ctx);
6826 if (ret_val)
6827 return ret_val;
6828
6829 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006830 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306831 return -EINVAL;
6832 }
6833
6834 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006835 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306836 return -ENOTSUPP;
6837 }
6838
6839 if (nla_parse(tb, BPF_MAX, data, data_len,
6840 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006841 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306842 return -EINVAL;
6843 }
6844
6845 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006846 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306847 return -EINVAL;
6848 }
6849
6850 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6851
6852 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6853 return hdd_get_bpf_offload(hdd_ctx);
6854 else
6855 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306856 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306857}
6858
6859/**
6860 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6861 * @wiphy: wiphy structure pointer
6862 * @wdev: Wireless device structure pointer
6863 * @data: Pointer to the data received
6864 * @data_len: Length of @data
6865 *
6866 * Return: 0 on success; errno on failure
6867 */
6868
6869static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6870 struct wireless_dev *wdev,
6871 const void *data, int data_len)
6872{
6873 int ret;
6874
6875 cds_ssr_protect(__func__);
6876 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6877 cds_ssr_unprotect(__func__);
6878
6879 return ret;
6880}
6881
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306882/**
6883 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6884 * @pre_cac_adapter: AP adapter used for pre cac
6885 * @status: Status (true or false)
6886 * @handle: Global handle
6887 *
6888 * Sets the status of pre cac i.e., whether the pre cac is active or not
6889 *
6890 * Return: Zero on success, non-zero on failure
6891 */
6892static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6893 bool status, tHalHandle handle)
6894{
6895 QDF_STATUS ret;
6896
6897 ret = wlan_sap_set_pre_cac_status(
6898 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6899 if (QDF_IS_STATUS_ERROR(ret))
6900 return -EINVAL;
6901
6902 return 0;
6903}
6904
6905/**
6906 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6907 * @ap_adapter: AP adapter
6908 * @chan_before_pre_cac: Channel
6909 *
6910 * Saves the channel which the AP was beaconing on before moving to the pre
6911 * cac channel. If radar is detected on the pre cac channel, this saved
6912 * channel will be used for AP operations.
6913 *
6914 * Return: Zero on success, non-zero on failure
6915 */
6916static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6917 uint8_t chan_before_pre_cac)
6918{
6919 QDF_STATUS ret;
6920
6921 ret = wlan_sap_set_chan_before_pre_cac(
6922 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6923 if (QDF_IS_STATUS_ERROR(ret))
6924 return -EINVAL;
6925
6926 return 0;
6927}
6928
6929/**
6930 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6931 * @ap_adapter: AP adapter
6932 * @nol: Non-occupancy list
6933 * @nol_len: Length of NOL
6934 *
6935 * Get the NOL for SAP
6936 *
6937 * Return: Zero on success, non-zero on failure
6938 */
6939static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6940 uint32_t *nol_len)
6941{
6942 QDF_STATUS ret;
6943
6944 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6945 nol, nol_len);
6946 if (QDF_IS_STATUS_ERROR(ret))
6947 return -EINVAL;
6948
6949 return 0;
6950}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306951
6952/**
6953 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6954 * @hdd_ctx: HDD context
6955 * @ap_adapter: AP adapter
6956 * @channel: Channel requested by userspace
6957 * @pre_cac_chan: Pointer to the pre CAC channel
6958 *
6959 * Validates the channel provided by userspace. If user provided channel 0,
6960 * a valid outdoor channel must be selected from the regulatory channel.
6961 *
6962 * Return: Zero on success and non zero value on error
6963 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006964static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6965 hdd_adapter_t *ap_adapter,
6966 uint8_t channel,
6967 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306968{
6969 uint32_t i, j;
6970 QDF_STATUS status;
6971 int ret;
6972 uint8_t nol[QDF_MAX_NUM_CHAN];
6973 uint32_t nol_len = 0, weight_len = 0;
6974 bool found;
6975 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6976 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6977 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6978
6979 if (0 == channel) {
6980 /* Channel is not obtained from PCL because PCL may not have
6981 * the entire channel list. For example: if SAP is up on
6982 * channel 6 and PCL is queried for the next SAP interface,
6983 * if SCC is preferred, the PCL will contain only the channel
6984 * 6. But, we are in need of a DFS channel. So, going with the
6985 * first channel from the valid channel list.
6986 */
6987 status = cds_get_valid_chans(channel_list, &len);
6988 if (QDF_IS_STATUS_ERROR(status)) {
6989 hdd_err("Failed to get channel list");
6990 return -EINVAL;
6991 }
6992 cds_update_with_safe_channel_list(channel_list, &len,
6993 pcl_weights, weight_len);
6994 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6995 for (i = 0; i < len; i++) {
6996 found = false;
6997 for (j = 0; j < nol_len; j++) {
6998 if (channel_list[i] == nol[j]) {
6999 found = true;
7000 break;
7001 }
7002 }
7003 if (found)
7004 continue;
7005 if (CDS_IS_DFS_CH(channel_list[i])) {
7006 *pre_cac_chan = channel_list[i];
7007 break;
7008 }
7009 }
7010 if (*pre_cac_chan == 0) {
7011 hdd_err("unable to find outdoor channel");
7012 return -EINVAL;
7013 }
7014 } else {
7015 /* Only when driver selects a channel, check is done for
7016 * unnsafe and NOL channels. When user provides a fixed channel
7017 * the user is expected to take care of this.
7018 */
7019 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7020 !CDS_IS_DFS_CH(channel)) {
7021 hdd_err("Invalid channel for pre cac:%d", channel);
7022 return -EINVAL;
7023 } else {
7024 *pre_cac_chan = channel;
7025 }
7026 }
7027 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7028 return 0;
7029}
7030
7031/**
7032 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7033 * @channel: Channel option provided by userspace
7034 *
7035 * Sets the driver to the required hardware mode and start an adapater for
7036 * pre CAC which will mimic an AP.
7037 *
7038 * Return: Zero on success, non-zero value on error
7039 */
7040int wlan_hdd_request_pre_cac(uint8_t channel)
7041{
Krunal Sonib37bb352016-12-20 14:12:21 -08007042 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307043 hdd_context_t *hdd_ctx;
7044 int ret;
7045 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7046 hdd_ap_ctx_t *hdd_ap_ctx;
7047 QDF_STATUS status;
7048 struct wiphy *wiphy;
7049 struct net_device *dev;
7050 struct cfg80211_chan_def chandef;
7051 enum nl80211_channel_type channel_type;
7052 uint32_t freq;
7053 struct ieee80211_channel *chan;
7054 tHalHandle handle;
7055 bool val;
7056
7057 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7058 if (0 != wlan_hdd_validate_context(hdd_ctx))
7059 return -EINVAL;
7060
7061 if (cds_get_connection_count() > 1) {
7062 hdd_err("pre cac not allowed in concurrency");
7063 return -EINVAL;
7064 }
7065
7066 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7067 if (!ap_adapter) {
7068 hdd_err("unable to get SAP adapter");
7069 return -EINVAL;
7070 }
7071
7072 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7073 if (!handle) {
7074 hdd_err("Invalid handle");
7075 return -EINVAL;
7076 }
7077
7078 val = wlan_sap_is_pre_cac_active(handle);
7079 if (val) {
7080 hdd_err("pre cac is already in progress");
7081 return -EINVAL;
7082 }
7083
7084 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7085 if (!hdd_ap_ctx) {
7086 hdd_err("SAP context is NULL");
7087 return -EINVAL;
7088 }
7089
7090 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7091 hdd_err("SAP is already on DFS channel:%d",
7092 hdd_ap_ctx->operatingChannel);
7093 return -EINVAL;
7094 }
7095
7096 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7097 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7098 hdd_ap_ctx->operatingChannel);
7099 return -EINVAL;
7100 }
7101
Krunal Sonib37bb352016-12-20 14:12:21 -08007102 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7103 if (!mac_addr) {
7104 hdd_err("can't add virtual intf: Not getting valid mac addr");
7105 return -EINVAL;
7106 }
7107
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307108 hdd_info("channel:%d", channel);
7109
7110 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7111 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007112 if (ret != 0) {
7113 hdd_err("can't validate pre-cac channel");
7114 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307115 }
7116
7117 hdd_debug("starting pre cac SAP adapter");
7118
7119 /* Starting a SAP adapter:
7120 * Instead of opening an adapter, we could just do a SME open session
7121 * for AP type. But, start BSS would still need an adapter.
7122 * So, this option is not taken.
7123 *
7124 * hdd open adapter is going to register this precac interface with
7125 * user space. This interface though exposed to user space will be in
7126 * DOWN state. Consideration was done to avoid this registration to the
7127 * user space. But, as part of SAP operations multiple events are sent
7128 * to user space. Some of these events received from unregistered
7129 * interface was causing crashes. So, retaining the registration.
7130 *
7131 * So, this interface would remain registered and will remain in DOWN
7132 * state for the CAC duration. We will add notes in the feature
7133 * announcement to not use this temporary interface for any activity
7134 * from user space.
7135 */
7136 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007137 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307138 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307139 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007140 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307141 }
7142
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307143 /*
7144 * This interface is internally created by the driver. So, no interface
7145 * up comes for this interface from user space and hence starting
7146 * the adapter internally.
7147 */
7148 if (hdd_start_adapter(pre_cac_adapter)) {
7149 hdd_err("error starting the pre cac adapter");
7150 goto close_pre_cac_adapter;
7151 }
7152
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307153 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7154
7155 wiphy = hdd_ctx->wiphy;
7156 dev = pre_cac_adapter->dev;
7157
7158 /* Since this is only a dummy interface lets us use the IEs from the
7159 * other active SAP interface. In regular scenarios, these IEs would
7160 * come from the user space entity
7161 */
7162 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7163 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7164 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7165 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307166 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307167 }
7168 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7169 ap_adapter->sessionCtx.ap.beacon,
7170 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7171 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7172 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7173 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7174 ap_adapter->sessionCtx.ap.sapConfig.authType;
7175
7176 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7177 * to operate on the same bandwidth as that of the 2.4GHz operations.
7178 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7179 */
7180 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7181 case CH_WIDTH_20MHZ:
7182 channel_type = NL80211_CHAN_HT20;
7183 break;
7184 case CH_WIDTH_40MHZ:
7185 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7186 ap_adapter->sessionCtx.ap.sapConfig.channel)
7187 channel_type = NL80211_CHAN_HT40PLUS;
7188 else
7189 channel_type = NL80211_CHAN_HT40MINUS;
7190 break;
7191 default:
7192 channel_type = NL80211_CHAN_NO_HT;
7193 break;
7194 }
7195
7196 freq = cds_chan_to_freq(pre_cac_chan);
7197 chan = __ieee80211_get_channel(wiphy, freq);
7198 if (!chan) {
7199 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307200 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307201 }
7202
7203 cfg80211_chandef_create(&chandef, chan, channel_type);
7204
7205 hdd_debug("orig width:%d channel_type:%d freq:%d",
7206 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7207 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007208 /*
7209 * Doing update after opening and starting pre-cac adapter will make
7210 * sure that driver won't do hardware mode change if there are any
7211 * initial hick-ups or issues in pre-cac adapter's configuration.
7212 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7213 * connection update should result in DBS mode
7214 */
7215 status = cds_update_and_wait_for_connection_update(
7216 ap_adapter->sessionId,
7217 pre_cac_chan,
7218 SIR_UPDATE_REASON_PRE_CAC);
7219 if (QDF_IS_STATUS_ERROR(status)) {
7220 hdd_err("error in moving to DBS mode");
7221 goto stop_close_pre_cac_adapter;
7222 }
7223
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307224
7225 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7226 if (0 != ret) {
7227 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307228 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307229 }
7230
7231 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7232 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007233 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307234 if (QDF_IS_STATUS_ERROR(status)) {
7235 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307236 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307237 }
7238
7239 /*
7240 * The pre cac status is set here. But, it would not be reset explicitly
7241 * anywhere, since after the pre cac success/failure, the pre cac
7242 * adapter itself would be removed.
7243 */
7244 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7245 if (0 != ret) {
7246 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307247 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307248 }
7249
7250 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7251 hdd_ap_ctx->operatingChannel);
7252 if (0 != ret) {
7253 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307254 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307255 }
7256
7257 ap_adapter->pre_cac_chan = pre_cac_chan;
7258
7259 return 0;
7260
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307261stop_close_pre_cac_adapter:
7262 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307263 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7264 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307265close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307266 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007267release_intf_addr_and_return_failure:
7268 /*
7269 * Release the interface address as the adapter
7270 * failed to start, if you don't release then next
7271 * adapter which is trying to come wouldn't get valid
7272 * mac address. Remember we have limited pool of mac addresses
7273 */
7274 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307275 return -EINVAL;
7276}
7277
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307278/**
7279 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7280 *
7281 * Return: None
7282 */
7283void hdd_init_bpf_completion(void)
7284{
7285 init_completion(&bpf_context.completion);
7286}
7287
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307288static const struct nla_policy
7289wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7290 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7291};
7292
Agrawal Ashish65634612016-08-18 13:24:32 +05307293static const struct nla_policy
7294wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7295 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7296 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7297};
7298
7299/**
7300 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7301 * @wiphy: Pointer to wireless phy
7302 * @wdev: Pointer to wireless device
7303 * @data: Pointer to data
7304 * @data_len: Length of @data
7305 *
7306 * This function parses the incoming NL vendor command data attributes and
7307 * updates the SAP context about channel_hint and DFS mode.
7308 * If channel_hint is set, SAP will choose that channel
7309 * as operating channel.
7310 *
7311 * If DFS mode is enabled, driver will include DFS channels
7312 * in ACS else driver will skip DFS channels.
7313 *
7314 * Return: 0 on success, negative errno on failure
7315 */
7316static int
7317__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7318 struct wireless_dev *wdev,
7319 const void *data, int data_len)
7320{
7321 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7322 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7323 int ret;
7324 struct acs_dfs_policy *acs_policy;
7325 int mode = DFS_MODE_NONE;
7326 int channel_hint = 0;
7327
7328 ENTER_DEV(wdev->netdev);
7329
7330 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7331 hdd_err("Command not allowed in FTM mode");
7332 return -EINVAL;
7333 }
7334
7335 ret = wlan_hdd_validate_context(hdd_ctx);
7336 if (0 != ret)
7337 return ret;
7338
7339 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7340 data, data_len,
7341 wlan_hdd_set_acs_dfs_config_policy)) {
7342 hdd_err("invalid attr");
7343 return -EINVAL;
7344 }
7345
7346 acs_policy = &hdd_ctx->acs_policy;
7347 /*
7348 * SCM sends this attribute to restrict SAP from choosing
7349 * DFS channels from ACS.
7350 */
7351 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7352 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7353
7354 if (!IS_DFS_MODE_VALID(mode)) {
7355 hdd_err("attr acs dfs mode is not valid");
7356 return -EINVAL;
7357 }
7358 acs_policy->acs_dfs_mode = mode;
7359
7360 /*
7361 * SCM sends this attribute to provide an active channel,
7362 * to skip redundant ACS between drivers, and save driver start up time
7363 */
7364 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7365 channel_hint = nla_get_u8(
7366 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7367
7368 if (!IS_CHANNEL_VALID(channel_hint)) {
7369 hdd_err("acs channel is not valid");
7370 return -EINVAL;
7371 }
7372 acs_policy->acs_channel = channel_hint;
7373
7374 return 0;
7375}
7376
7377/**
7378 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7379 * @wiphy: wiphy structure pointer
7380 * @wdev: Wireless device structure pointer
7381 * @data: Pointer to the data received
7382 * @data_len: Length of @data
7383 *
7384 * This function parses the incoming NL vendor command data attributes and
7385 * updates the SAP context about channel_hint and DFS mode.
7386 *
7387 * Return: 0 on success; errno on failure
7388 */
7389static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7390 struct wireless_dev *wdev,
7391 const void *data, int data_len)
7392{
7393 int ret;
7394
7395 cds_ssr_protect(__func__);
7396 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7397 cds_ssr_unprotect(__func__);
7398
7399 return ret;
7400}
7401
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307402/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307403 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7404 * @mode : cfg80211 dfs mode
7405 *
7406 * Return: return csr sta roam dfs mode else return NONE
7407 */
7408static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7409 enum dfs_mode mode)
7410{
7411 switch (mode) {
7412 case DFS_MODE_ENABLE:
7413 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7414 break;
7415 case DFS_MODE_DISABLE:
7416 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7417 break;
7418 case DFS_MODE_DEPRIORITIZE:
7419 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7420 break;
7421 default:
7422 hdd_err("STA Roam policy dfs mode is NONE");
7423 return CSR_STA_ROAM_POLICY_NONE;
7424 }
7425}
7426
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307427/*
7428 * hdd_get_sap_operating_band: Get current operating channel
7429 * for sap.
7430 * @hdd_ctx: hdd context
7431 *
7432 * Return : Corresponding band for SAP operating channel
7433 */
7434uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7435{
7436 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7437 QDF_STATUS status;
7438 hdd_adapter_t *adapter;
7439 uint8_t operating_channel = 0;
7440 uint8_t sap_operating_band = 0;
7441 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7442 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7443 adapter = adapter_node->pAdapter;
7444
7445 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7446 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7447 &next);
7448 adapter_node = next;
7449 continue;
7450 }
7451 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7452 if (IS_24G_CH(operating_channel))
7453 sap_operating_band = eCSR_BAND_24;
7454 else if (IS_5G_CH(operating_channel))
7455 sap_operating_band = eCSR_BAND_5G;
7456 else
7457 sap_operating_band = eCSR_BAND_ALL;
7458 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7459 &next);
bings373b99b2017-01-23 10:35:08 +08007460 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307461 }
7462 return sap_operating_band;
7463}
7464
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307465static const struct nla_policy
7466wlan_hdd_set_sta_roam_config_policy[
7467QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7468 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7469 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7470};
7471
7472/**
7473 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7474 * for station connection or roaming.
7475 * @wiphy: Pointer to wireless phy
7476 * @wdev: Pointer to wireless device
7477 * @data: Pointer to data
7478 * @data_len: Length of @data
7479 *
7480 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7481 * channels needs to be skipped in scanning or not.
7482 * If dfs_mode is disabled, driver will not scan DFS channels.
7483 * If skip_unsafe_channels is set, driver will skip unsafe channels
7484 * in Scanning.
7485 *
7486 * Return: 0 on success, negative errno on failure
7487 */
7488static int
7489__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7490 struct wireless_dev *wdev,
7491 const void *data, int data_len)
7492{
7493 struct net_device *dev = wdev->netdev;
7494 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7495 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7496 struct nlattr *tb[
7497 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7498 int ret;
7499 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7500 enum dfs_mode mode = DFS_MODE_NONE;
7501 bool skip_unsafe_channels = false;
7502 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307503 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307504
7505 ENTER_DEV(dev);
7506
7507 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7508 hdd_err("Command not allowed in FTM mode");
7509 return -EINVAL;
7510 }
7511
7512 ret = wlan_hdd_validate_context(hdd_ctx);
7513 if (0 != ret)
7514 return ret;
7515 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7516 data, data_len,
7517 wlan_hdd_set_sta_roam_config_policy)) {
7518 hdd_err("invalid attr");
7519 return -EINVAL;
7520 }
7521 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7522 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7523 if (!IS_DFS_MODE_VALID(mode)) {
7524 hdd_err("attr sta roam dfs mode policy is not valid");
7525 return -EINVAL;
7526 }
7527
7528 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7529
7530 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7531 skip_unsafe_channels = nla_get_u8(
7532 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307533 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307534 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307535 skip_unsafe_channels, adapter->sessionId,
7536 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307537
7538 if (!QDF_IS_STATUS_SUCCESS(status)) {
7539 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7540 return -EINVAL;
7541 }
7542 return 0;
7543}
7544
7545/**
7546 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7547 * connection and roaming for station.
7548 * @wiphy: wiphy structure pointer
7549 * @wdev: Wireless device structure pointer
7550 * @data: Pointer to the data received
7551 * @data_len: Length of @data
7552 *
7553 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7554 * channels needs to be skipped in scanning or not.
7555 * If dfs_mode is disabled, driver will not scan DFS channels.
7556 * If skip_unsafe_channels is set, driver will skip unsafe channels
7557 * in Scanning.
7558 * Return: 0 on success; errno on failure
7559 */
7560static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7561 struct wireless_dev *wdev,
7562 const void *data, int data_len)
7563{
7564 int ret;
7565
7566 cds_ssr_protect(__func__);
7567 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7568 cds_ssr_unprotect(__func__);
7569
7570 return ret;
7571}
7572
Agrawal Ashish467dde42016-09-08 18:44:22 +05307573#ifdef FEATURE_WLAN_CH_AVOID
7574/**
7575 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7576 * is on unsafe channel.
7577 * @wiphy: wiphy structure pointer
7578 * @wdev: Wireless device structure pointer
7579 * @data: Pointer to the data received
7580 * @data_len: Length of @data
7581 *
7582 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7583 * on any of unsafe channels.
7584 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7585 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7586 *
7587 * Return: 0 on success; errno on failure
7588 */
7589static int
7590__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7591 struct wireless_dev *wdev,
7592 const void *data, int data_len)
7593{
7594 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7595 int ret;
7596 uint16_t unsafe_channel_count;
7597 int unsafe_channel_index;
7598 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7599
7600 ENTER_DEV(wdev->netdev);
7601
7602 if (!qdf_ctx) {
7603 cds_err("qdf_ctx is NULL");
7604 return -EINVAL;
7605 }
7606
7607 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7608 hdd_err("Command not allowed in FTM mode");
7609 return -EINVAL;
7610 }
7611
7612 ret = wlan_hdd_validate_context(hdd_ctx);
7613 if (0 != ret)
7614 return ret;
7615 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7616 &(hdd_ctx->unsafe_channel_count),
7617 sizeof(hdd_ctx->unsafe_channel_list));
7618
7619 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7620 (uint16_t)NUM_CHANNELS);
7621 for (unsafe_channel_index = 0;
7622 unsafe_channel_index < unsafe_channel_count;
7623 unsafe_channel_index++) {
7624 hdd_info("Channel %d is not safe",
7625 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7626 }
7627 hdd_unsafe_channel_restart_sap(hdd_ctx);
7628 return 0;
7629}
7630
7631/**
7632 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7633 * is on unsafe channel.
7634 * @wiphy: wiphy structure pointer
7635 * @wdev: Wireless device structure pointer
7636 * @data: Pointer to the data received
7637 * @data_len: Length of @data
7638 *
7639 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7640 * on any of unsafe channels.
7641 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7642 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7643 *
7644 * Return: 0 on success; errno on failure
7645 */
7646static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7647 struct wireless_dev *wdev,
7648 const void *data, int data_len)
7649{
7650 int ret;
7651
7652 cds_ssr_protect(__func__);
7653 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7654 cds_ssr_unprotect(__func__);
7655
7656 return ret;
7657}
7658
7659#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307660/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307661 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7662 * SAP is on unsafe channel.
7663 * @wiphy: wiphy structure pointer
7664 * @wdev: Wireless device structure pointer
7665 * @data: Pointer to the data received
7666 * @data_len: Length of @data
7667 *
7668 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7669 * driver.
7670 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7671 * will initiate restart of sap.
7672 *
7673 * Return: 0 on success; errno on failure
7674 */
7675static int
7676__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7677 struct wireless_dev *wdev,
7678 const void *data, int data_len)
7679{
7680 struct net_device *ndev = wdev->netdev;
7681 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7682 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7683 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7684 uint8_t config_channel = 0;
7685 hdd_ap_ctx_t *ap_ctx;
7686 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307687 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307688
7689 ENTER();
7690
7691 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007692 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307693 return -EINVAL;
7694 }
7695
7696 ret = wlan_hdd_validate_context(hdd_ctx);
7697 if (0 != ret)
7698 return -EINVAL;
7699
7700 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7701 data, data_len,
7702 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007703 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307704 return -EINVAL;
7705 }
7706
7707 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7708 if (!test_bit(SOFTAP_BSS_STARTED,
7709 &hostapd_adapter->event_flags)) {
7710 hdd_err("SAP is not started yet. Restart sap will be invalid");
7711 return -EINVAL;
7712 }
7713
7714 config_channel =
7715 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7716
7717 if (!((IS_24G_CH(config_channel)) ||
7718 (IS_5G_CH(config_channel)))) {
7719 hdd_err("Channel %d is not valid to restart SAP",
7720 config_channel);
7721 return -ENOTSUPP;
7722 }
7723
7724 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7725 ap_ctx->sapConfig.channel = config_channel;
7726 ap_ctx->sapConfig.ch_params.ch_width =
7727 ap_ctx->sapConfig.ch_width_orig;
7728
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007729 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307730 ap_ctx->sapConfig.sec_ch,
7731 &ap_ctx->sapConfig.ch_params);
7732
7733 cds_restart_sap(hostapd_adapter);
7734 }
7735
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307736 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7737 uint32_t freq_len, i;
7738 uint32_t *freq;
7739 uint8_t chans[QDF_MAX_NUM_CHAN];
7740
7741 hdd_debug("setting mandatory freq/chan list");
7742
7743 freq_len = nla_len(
7744 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7745 sizeof(uint32_t);
7746
7747 if (freq_len > QDF_MAX_NUM_CHAN) {
7748 hdd_err("insufficient space to hold channels");
7749 return -ENOMEM;
7750 }
7751
7752 freq = nla_data(
7753 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7754
7755 hdd_debug("freq_len=%d", freq_len);
7756
7757 for (i = 0; i < freq_len; i++) {
7758 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7759 hdd_debug("freq[%d]=%d", i, freq[i]);
7760 }
7761
7762 status = cds_set_sap_mandatory_channels(chans, freq_len);
7763 if (QDF_IS_STATUS_ERROR(status))
7764 return -EINVAL;
7765 }
7766
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307767 return 0;
7768}
7769
7770/**
7771 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7772 * @wiphy: wiphy structure pointer
7773 * @wdev: Wireless device structure pointer
7774 * @data: Pointer to the data received
7775 * @data_len: Length of @data
7776 *
7777 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7778 * driver.
7779 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7780 * will initiate restart of sap.
7781 *
7782 * Return: 0 on success; errno on failure
7783 */
7784static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7785 struct wireless_dev *wdev,
7786 const void *data, int data_len)
7787{
7788 int ret;
7789
7790 cds_ssr_protect(__func__);
7791 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7792 wdev, data, data_len);
7793 cds_ssr_unprotect(__func__);
7794
7795 return ret;
7796}
7797
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307798#undef BPF_INVALID
7799#undef BPF_SET_RESET
7800#undef BPF_VERSION
7801#undef BPF_ID
7802#undef BPF_PACKET_SIZE
7803#undef BPF_CURRENT_OFFSET
7804#undef BPF_PROGRAM
7805#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307806
7807/**
7808 * define short names for the global vendor params
7809 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7810 */
7811#define PARAM_TOTAL_CMD_EVENT_WAKE \
7812 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7813#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7814 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7815#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7816 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7817#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7818 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7819#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7820 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7821#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7822 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7823#define PARAM_TOTAL_RX_DATA_WAKE \
7824 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7825#define PARAM_RX_UNICAST_CNT \
7826 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7827#define PARAM_RX_MULTICAST_CNT \
7828 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7829#define PARAM_RX_BROADCAST_CNT \
7830 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7831#define PARAM_ICMP_PKT \
7832 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7833#define PARAM_ICMP6_PKT \
7834 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7835#define PARAM_ICMP6_RA \
7836 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7837#define PARAM_ICMP6_NA \
7838 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7839#define PARAM_ICMP6_NS \
7840 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7841#define PARAM_ICMP4_RX_MULTICAST_CNT \
7842 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7843#define PARAM_ICMP6_RX_MULTICAST_CNT \
7844 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7845#define PARAM_OTHER_RX_MULTICAST_CNT \
7846 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307847#define PARAM_RSSI_BREACH_CNT \
7848 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
7849#define PARAM_LOW_RSSI_CNT \
7850 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
7851#define PARAM_GSCAN_CNT \
7852 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
7853#define PARAM_PNO_COMPLETE_CNT \
7854 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
7855#define PARAM_PNO_MATCH_CNT \
7856 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
7857
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307858
7859
7860/**
7861 * hdd_send_wakelock_stats() - API to send wakelock stats
7862 * @ctx: context to be passed to callback
7863 * @data: data passed to callback
7864 *
7865 * This function is used to send wake lock stats to HAL layer
7866 *
7867 * Return: 0 on success, error number otherwise.
7868 */
7869static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7870 const struct sir_wake_lock_stats *data)
7871{
7872 struct sk_buff *skb;
7873 uint32_t nl_buf_len;
7874 uint32_t total_rx_data_wake, rx_multicast_cnt;
7875 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307876 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307877
7878 ENTER();
7879
7880 nl_buf_len = NLMSG_HDRLEN;
7881 nl_buf_len +=
7882 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7883 (NLMSG_HDRLEN + sizeof(uint32_t));
7884
7885 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7886
7887 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007888 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307889 return -ENOMEM;
7890 }
7891
Jeff Johnson64943bd2016-08-23 13:14:06 -07007892 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307893 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007894 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307895 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007896 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307897 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007898 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307899 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007900 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307901 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007902 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307903 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007904 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307905 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007906 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7907 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307908 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307909 hdd_info("wow_rssi_breach_wake_up_count %d",
7910 data->wow_rssi_breach_wake_up_count);
7911 hdd_info("wow_low_rssi_wake_up_count %d",
7912 data->wow_low_rssi_wake_up_count);
7913 hdd_info("wow_gscan_wake_up_count %d",
7914 data->wow_gscan_wake_up_count);
7915 hdd_info("wow_pno_complete_wake_up_count %d",
7916 data->wow_pno_complete_wake_up_count);
7917 hdd_info("wow_pno_match_wake_up_count %d",
7918 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307919
7920 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307921 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307922
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307923 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307924 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307925
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307926 rx_multicast_cnt =
7927 data->wow_ipv4_mcast_wake_up_count +
7928 ipv6_rx_multicast_addr_cnt;
7929
7930 total_rx_data_wake =
7931 data->wow_ucast_wake_up_count +
7932 data->wow_bcast_wake_up_count +
7933 rx_multicast_cnt;
7934
7935 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7936 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7937 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7938 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7939 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7940 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7941 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7942 total_rx_data_wake) ||
7943 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7944 data->wow_ucast_wake_up_count) ||
7945 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7946 rx_multicast_cnt) ||
7947 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7948 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307949 nla_put_u32(skb, PARAM_ICMP_PKT,
7950 data->wow_icmpv4_count) ||
7951 nla_put_u32(skb, PARAM_ICMP6_PKT,
7952 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307953 nla_put_u32(skb, PARAM_ICMP6_RA,
7954 data->wow_ipv6_mcast_ra_stats) ||
7955 nla_put_u32(skb, PARAM_ICMP6_NA,
7956 data->wow_ipv6_mcast_na_stats) ||
7957 nla_put_u32(skb, PARAM_ICMP6_NS,
7958 data->wow_ipv6_mcast_ns_stats) ||
7959 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7960 data->wow_ipv4_mcast_wake_up_count) ||
7961 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7962 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307963 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
7964 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
7965 data->wow_rssi_breach_wake_up_count) ||
7966 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
7967 data->wow_low_rssi_wake_up_count) ||
7968 nla_put_u32(skb, PARAM_GSCAN_CNT,
7969 data->wow_gscan_wake_up_count) ||
7970 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
7971 data->wow_pno_complete_wake_up_count) ||
7972 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
7973 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007974 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307975 goto nla_put_failure;
7976 }
7977
7978 cfg80211_vendor_cmd_reply(skb);
7979
7980 EXIT();
7981 return 0;
7982
7983nla_put_failure:
7984 kfree_skb(skb);
7985 return -EINVAL;
7986}
7987
7988/**
7989 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7990 * @wiphy: wiphy pointer
7991 * @wdev: pointer to struct wireless_dev
7992 * @data: pointer to incoming NL vendor data
7993 * @data_len: length of @data
7994 *
7995 * This function parses the incoming NL vendor command data attributes and
7996 * invokes the SME Api and blocks on a completion variable.
7997 * WMA copies required data and invokes callback
7998 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7999 *
8000 * Return: 0 on success; error number otherwise.
8001 */
8002static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8003 struct wireless_dev *wdev,
8004 const void *data,
8005 int data_len)
8006{
8007 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8008 int status, ret;
8009 struct sir_wake_lock_stats wake_lock_stats;
8010 QDF_STATUS qdf_status;
8011
8012 ENTER();
8013
8014 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008015 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308016 return -EINVAL;
8017 }
8018
8019 status = wlan_hdd_validate_context(hdd_ctx);
8020 if (0 != status)
8021 return -EINVAL;
8022
8023 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8024 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008025 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308026 return -EINVAL;
8027 }
8028
8029 ret = hdd_send_wakelock_stats(hdd_ctx,
8030 &wake_lock_stats);
8031 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008032 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308033
8034 EXIT();
8035 return ret;
8036}
8037
8038/**
8039 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8040 * @wiphy: wiphy pointer
8041 * @wdev: pointer to struct wireless_dev
8042 * @data: pointer to incoming NL vendor data
8043 * @data_len: length of @data
8044 *
8045 * This function parses the incoming NL vendor command data attributes and
8046 * invokes the SME Api and blocks on a completion variable.
8047 * WMA copies required data and invokes callback
8048 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8049 *
8050 * Return: 0 on success; error number otherwise.
8051 */
8052static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8053 struct wireless_dev *wdev,
8054 const void *data, int data_len)
8055{
8056 int ret;
8057
8058 cds_ssr_protect(__func__);
8059 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8060 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008061 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308062
8063 return ret;
8064}
8065
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308066/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308067 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8068 * @wiphy: wiphy structure pointer
8069 * @wdev: Wireless device structure pointer
8070 * @data: Pointer to the data received
8071 * @data_len: Length of @data
8072 *
8073 * This function reads wmi max bus size and fill in the skb with
8074 * NL attributes and send up the NL event.
8075 * Return: 0 on success; errno on failure
8076 */
8077static int
8078__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8079 struct wireless_dev *wdev,
8080 const void *data, int data_len)
8081{
8082 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8083 int ret_val;
8084 struct sk_buff *skb;
8085 uint32_t nl_buf_len;
8086
8087 ENTER();
8088
8089 ret_val = wlan_hdd_validate_context(hdd_ctx);
8090 if (ret_val)
8091 return ret_val;
8092
8093 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8094 hdd_err("Command not allowed in FTM mode");
8095 return -EINVAL;
8096 }
8097
8098 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8099
8100 nl_buf_len = NLMSG_HDRLEN;
8101 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8102
8103 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8104 if (!skb) {
8105 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8106 return -ENOMEM;
8107 }
8108
8109 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8110 hdd_ctx->wmi_max_len)) {
8111 hdd_err("nla put failure");
8112 goto nla_put_failure;
8113 }
8114
8115 cfg80211_vendor_cmd_reply(skb);
8116
8117 EXIT();
8118
8119 return 0;
8120
8121nla_put_failure:
8122 kfree_skb(skb);
8123 return -EINVAL;
8124}
8125
8126/**
8127 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8128 * @wiphy: wiphy structure pointer
8129 * @wdev: Wireless device structure pointer
8130 * @data: Pointer to the data received
8131 * @data_len: Length of @data
8132 *
8133 * Return: 0 on success; errno on failure
8134 */
8135static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8136 struct wireless_dev *wdev,
8137 const void *data, int data_len)
8138{
8139 int ret;
8140
8141 cds_ssr_protect(__func__);
8142 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8143 cds_ssr_unprotect(__func__);
8144
8145 return ret;
8146}
8147
8148/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308149 *__wlan_hdd_cfg80211_setband() - set band
8150 * @wiphy: Pointer to wireless phy
8151 * @wdev: Pointer to wireless device
8152 * @data: Pointer to data
8153 * @data_len: Length of @data
8154 *
8155 * Return: 0 on success, negative errno on failure
8156 */
8157static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8158 struct wireless_dev *wdev,
8159 const void *data, int data_len)
8160{
8161 struct net_device *dev = wdev->netdev;
8162 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8163 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8164 int ret;
8165 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8166 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8167
8168 ENTER();
8169
8170 ret = wlan_hdd_validate_context(hdd_ctx);
8171 if (ret)
8172 return ret;
8173
8174 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8175 hdd_err(FL("Invalid ATTR"));
8176 return -EINVAL;
8177 }
8178
8179 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8180 hdd_err(FL("attr SETBAND_VALUE failed"));
8181 return -EINVAL;
8182 }
8183
8184 ret = hdd_set_band(dev,
8185 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8186
8187 EXIT();
8188 return ret;
8189}
8190
8191/**
8192 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8193 * @wiphy: wiphy structure pointer
8194 * @wdev: Wireless device structure pointer
8195 * @data: Pointer to the data received
8196 * @data_len: Length of @data
8197 *
8198 * Return: 0 on success; errno on failure
8199 */
8200static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8201 struct wireless_dev *wdev,
8202 const void *data, int data_len)
8203{
8204 int ret;
8205
8206 cds_ssr_protect(__func__);
8207 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8208 cds_ssr_unprotect(__func__);
8209
8210 return ret;
8211}
8212
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008213/**
8214 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8215 * @nl80211_value: Vendor command attribute value
8216 * @wmi_value: Pointer to return converted WMI return value
8217 *
8218 * Convert NL80211 vendor command value for SAR limit set to WMI value
8219 * Return: 0 on success, -1 on invalid value
8220 */
8221static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8222 u32 *wmi_value)
8223{
8224 int ret = 0;
8225
8226 switch (nl80211_value) {
8227 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8228 *wmi_value = WMI_SAR_FEATURE_OFF;
8229 break;
8230 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8231 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8232 break;
8233 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8234 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8235 break;
8236 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8237 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8238 break;
8239 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8240 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8241 break;
8242 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8243 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8244 break;
8245 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8246 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8247 break;
8248 default:
8249 ret = -1;
8250 }
8251 return ret;
8252}
8253
8254/**
8255 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8256 * @nl80211_value: Vendor command attribute value
8257 * @wmi_value: Pointer to return converted WMI return value
8258 *
8259 * Convert NL80211 vendor command value for SAR BAND to WMI value
8260 * Return: 0 on success, -1 on invalid value
8261 */
8262static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8263{
8264 int ret = 0;
8265
8266 switch (nl80211_value) {
8267 case NL80211_BAND_2GHZ:
8268 *wmi_value = WMI_SAR_2G_ID;
8269 break;
8270 case NL80211_BAND_5GHZ:
8271 *wmi_value = WMI_SAR_5G_ID;
8272 break;
8273 default:
8274 ret = -1;
8275 }
8276 return ret;
8277}
8278
8279/**
8280 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8281 * @nl80211_value: Vendor command attribute value
8282 * @wmi_value: Pointer to return converted WMI return value
8283 *
8284 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8285 * Return: 0 on success, -1 on invalid value
8286 */
8287static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8288 u32 *wmi_value)
8289{
8290 int ret = 0;
8291
8292 switch (nl80211_value) {
8293 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8294 *wmi_value = WMI_SAR_MOD_CCK;
8295 break;
8296 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8297 *wmi_value = WMI_SAR_MOD_OFDM;
8298 break;
8299 default:
8300 ret = -1;
8301 }
8302 return ret;
8303}
8304
8305
8306/**
8307 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8308 * @wiphy: Pointer to wireless phy
8309 * @wdev: Pointer to wireless device
8310 * @data: Pointer to data
8311 * @data_len: Length of @data
8312 *
8313 * This function is used to setup Specific Absorption Rate limit specs.
8314 *
8315 * Return: 0 on success, negative errno on failure
8316 */
8317static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8318 struct wireless_dev *wdev,
8319 const void *data, int data_len)
8320{
8321 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8322 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8323 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8324 *sar_spec_list;
8325 struct sar_limit_cmd_params sar_limit_cmd = {0};
8326 int ret = -EINVAL, i = 0, rem = 0;
8327
8328 ENTER();
8329
8330 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8331 hdd_err("Command not allowed in FTM mode");
8332 return -EPERM;
8333 }
8334
8335 if (wlan_hdd_validate_context(hdd_ctx))
8336 return -EINVAL;
8337
8338 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8339 data, data_len, NULL)) {
8340 hdd_err("Invalid SAR attributes");
8341 return -EINVAL;
8342 }
8343
8344 /* Vendor command manadates all SAR Specs in single call */
8345 sar_limit_cmd.commit_limits = 1;
8346 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
8347 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
8348 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
8349 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
8350 &sar_limit_cmd.sar_enable) < 0) {
8351 hdd_err("Invalid SAR Enable attr");
8352 goto fail;
8353 }
8354 }
8355 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
8356
8357 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
8358 sar_limit_cmd.num_limit_rows = nla_get_u32(
8359 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
8360 hdd_info("attr sar num_limit_rows %d",
8361 sar_limit_cmd.num_limit_rows);
8362 }
8363 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
8364 hdd_err("SAR Spec list exceed supported size");
8365 goto fail;
8366 }
8367 if (sar_limit_cmd.num_limit_rows == 0)
8368 goto send_sar_limits;
8369 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
8370 struct sar_limit_cmd_row) *
8371 sar_limit_cmd.num_limit_rows);
8372 if (!sar_limit_cmd.sar_limit_row_list) {
8373 ret = -ENOMEM;
8374 goto fail;
8375 }
8376 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
8377 hdd_err("Invalid SAR SPECs list");
8378 goto fail;
8379 }
8380
8381 nla_for_each_nested(sar_spec_list,
8382 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
8383 if (i == sar_limit_cmd.num_limit_rows) {
8384 hdd_warn("SAR Cmd has excess SPECs in list");
8385 break;
8386 }
8387
8388 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8389 nla_data(sar_spec_list), nla_len(sar_spec_list),
8390 NULL)) {
8391 hdd_err("nla_parse failed for SAR Spec list");
8392 goto fail;
8393 }
8394 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
8395 if (sar_spec[
8396 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
8397 sar_limit_cmd.sar_limit_row_list[i].limit_value =
8398 nla_get_u32(sar_spec[
8399 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
8400 } else {
8401 hdd_err("SAR Spec does not have power limit value");
8402 goto fail;
8403 }
8404
8405 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
8406 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
8407 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
8408 &sar_limit_cmd.sar_limit_row_list[i].band_id)
8409 < 0) {
8410 hdd_err("Invalid SAR Band attr");
8411 goto fail;
8412 }
8413 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8414 WMI_SAR_BAND_ID_VALID_MASK;
8415 }
8416 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
8417 sar_limit_cmd.sar_limit_row_list[i].chain_id =
8418 nla_get_u32(sar_spec[
8419 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
8420 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8421 WMI_SAR_CHAIN_ID_VALID_MASK;
8422 }
8423 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
8424 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
8425 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
8426 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
8427 < 0) {
8428 hdd_err("Invalid SAR Modulation attr");
8429 goto fail;
8430 }
8431 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8432 WMI_SAR_MOD_ID_VALID_MASK;
8433 }
8434 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
8435 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
8436 sar_limit_cmd.sar_limit_row_list[i].chain_id,
8437 sar_limit_cmd.sar_limit_row_list[i].mod_id,
8438 sar_limit_cmd.sar_limit_row_list[i].limit_value,
8439 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
8440 i++;
8441 }
8442
8443 if (i < sar_limit_cmd.num_limit_rows) {
8444 hdd_warn("SAR Cmd has less SPECs in list");
8445 sar_limit_cmd.num_limit_rows = i;
8446 }
8447
8448send_sar_limits:
8449 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
8450 QDF_STATUS_SUCCESS)
8451 ret = 0;
8452fail:
8453 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
8454 return ret;
8455}
8456
8457/**
8458 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
8459 * @wiphy: Pointer to wireless phy
8460 * @wdev: Pointer to wireless device
8461 * @data: Pointer to data
8462 * @data_len: Length of @data
8463 *
8464 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
8465 *
8466 * Return: 0 on success, negative errno on failure
8467 */
8468static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
8469 struct wireless_dev *wdev,
8470 const void *data,
8471 int data_len)
8472{
8473 int ret;
8474
8475 cds_ssr_protect(__func__);
8476 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
8477 data_len);
8478 cds_ssr_unprotect(__func__);
8479
8480 return ret;
8481}
8482
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308483static const struct
8484nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
8485 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
8486 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
8487 .len = QDF_MAC_ADDR_SIZE},
8488};
8489
8490/**
8491 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8492 * @wiphy: Pointer to wireless phy
8493 * @wdev: Pointer to wireless device
8494 * @data: Pointer to data
8495 * @data_len: Length of @data
8496 *
8497 * This function is used to enable/disable roaming using vendor commands
8498 *
8499 * Return: 0 on success, negative errno on failure
8500 */
8501static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8502 struct wireless_dev *wdev,
8503 const void *data, int data_len)
8504{
8505 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8506 struct net_device *dev = wdev->netdev;
8507 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8508 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8509 uint32_t is_fast_roam_enabled;
8510 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308511 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308512
8513 ENTER_DEV(dev);
8514
8515 ret = wlan_hdd_validate_context(hdd_ctx);
8516 if (0 != ret)
8517 return ret;
8518
8519 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8520 hdd_err("Command not allowed in FTM mode");
8521 return -EINVAL;
8522 }
8523
8524 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
8525 qca_wlan_vendor_attr);
8526 if (ret) {
8527 hdd_err("Invalid ATTR");
8528 return -EINVAL;
8529 }
8530
8531 /* Parse and fetch Enable flag */
8532 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
8533 hdd_err("attr enable failed");
8534 return -EINVAL;
8535 }
8536
8537 is_fast_roam_enabled = nla_get_u32(
8538 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008539 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
8540 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308541
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008542 if (!adapter->fast_roaming_allowed) {
8543 hdd_err("fast roaming not allowed on %s interface",
8544 adapter->dev->name);
8545 return -EINVAL;
8546 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308547 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308548 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008549 (is_fast_roam_enabled &&
8550 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308551 if (qdf_status != QDF_STATUS_SUCCESS)
8552 hdd_err("sme_config_fast_roaming failed with status=%d",
8553 qdf_status);
8554 ret = qdf_status_to_os_return(qdf_status);
8555
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308556 EXIT();
8557 return ret;
8558}
8559
8560/**
8561 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8562 * @wiphy: Pointer to wireless phy
8563 * @wdev: Pointer to wireless device
8564 * @data: Pointer to data
8565 * @data_len: Length of @data
8566 *
8567 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8568 *
8569 * Return: 0 on success, negative errno on failure
8570 */
8571static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8572 struct wireless_dev *wdev,
8573 const void *data, int data_len)
8574{
8575 int ret;
8576
8577 cds_ssr_protect(__func__);
8578 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8579 cds_ssr_unprotect(__func__);
8580
8581 return ret;
8582}
8583
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05308584static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
8585 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
8586 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
8587 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
8588 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
8589};
8590
8591/**
8592 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
8593 * @wiphy: Pointer to wireless phy
8594 * @wdev: Pointer to wireless device
8595 * @data: Pointer to data
8596 * @data_len: Length of @data
8597 *
8598 * Return: 0 on success, negative errno on failure
8599 */
8600static int
8601__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
8602 struct wireless_dev *wdev,
8603 const void *data,
8604 int data_len)
8605{
8606 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8607 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
8608 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
8609 struct nlattr *apth;
8610 int rem;
8611 int ret = 1;
8612 int print_idx = -1;
8613 int module_id = -1;
8614 int bit_mask = -1;
8615 int status;
8616
8617 ENTER();
8618
8619 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8620 hdd_err("Command not allowed in FTM mode");
8621 return -EINVAL;
8622 }
8623
8624 ret = wlan_hdd_validate_context(hdd_ctx);
8625 if (ret != 0)
8626 return -EINVAL;
8627
8628 print_idx = qdf_get_pidx();
8629 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
8630 hdd_err("Invalid print controle object index");
8631 return -EINVAL;
8632 }
8633
8634 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
8635 data_len, qca_wlan_vendor_set_trace_level_policy)) {
8636 hdd_err("Invalid attr");
8637 return -EINVAL;
8638 }
8639
8640 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
8641 hdd_err("attr trace level param failed");
8642 return -EINVAL;
8643 }
8644
8645 nla_for_each_nested(apth,
8646 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
8647 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
8648 nla_data(apth), nla_len(apth), NULL)) {
8649 hdd_err("Invalid attr");
8650 return -EINVAL;
8651 }
8652
8653 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
8654 hdd_err("attr Module ID failed");
8655 return -EINVAL;
8656 }
8657 module_id = nla_get_u32
8658 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
8659
8660 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
8661 hdd_err("attr Verbose mask failed");
8662 return -EINVAL;
8663 }
8664 bit_mask = nla_get_u32
8665 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
8666
8667 status = hdd_qdf_trace_enable(module_id, bit_mask);
8668
8669 if (status != 0)
8670 hdd_err("can not set verbose mask %d for the category %d",
8671 bit_mask, module_id);
8672 }
8673
8674 EXIT();
8675 return ret;
8676}
8677
8678/**
8679 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
8680 * @wiphy: Pointer to wireless phy
8681 * @wdev: Pointer to wireless device
8682 * @data: Pointer to data
8683 * @data_len: Length of @data
8684 *
8685 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
8686 *
8687 * Return: 0 on success, negative errno on failure
8688 */
8689
8690static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
8691 struct wireless_dev *wdev,
8692 const void *data,
8693 int data_len)
8694{
8695 int ret;
8696
8697 cds_ssr_protect(__func__);
8698 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
8699 cds_ssr_unprotect(__func__);
8700
8701 return ret;
8702}
8703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008704const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8705 {
8706 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8707 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8708 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308709 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008710 .doit = is_driver_dfs_capable
8711 },
8712
8713#ifdef WLAN_FEATURE_NAN
8714 {
8715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8716 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8717 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8718 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8719 .doit = wlan_hdd_cfg80211_nan_request
8720 },
8721#endif
8722
8723#ifdef WLAN_FEATURE_STATS_EXT
8724 {
8725 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8726 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8727 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8728 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8729 .doit = wlan_hdd_cfg80211_stats_ext_request
8730 },
8731#endif
8732#ifdef FEATURE_WLAN_EXTSCAN
8733 {
8734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8737 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8738 .doit = wlan_hdd_cfg80211_extscan_start
8739 },
8740 {
8741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8742 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8743 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8744 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8745 .doit = wlan_hdd_cfg80211_extscan_stop
8746 },
8747 {
8748 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8749 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8750 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8751 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8752 },
8753 {
8754 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8755 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8756 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8757 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8758 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8759 },
8760 {
8761 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8762 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8763 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8764 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8765 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8766 },
8767 {
8768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8769 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8770 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8771 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8772 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8773 },
8774 {
8775 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8776 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8777 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8778 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8779 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8780 },
8781 {
8782 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8783 .info.subcmd =
8784 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8785 .flags =
8786 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8787 WIPHY_VENDOR_CMD_NEED_RUNNING,
8788 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8789 },
8790 {
8791 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8792 .info.subcmd =
8793 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8794 .flags =
8795 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8796 WIPHY_VENDOR_CMD_NEED_RUNNING,
8797 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8798 },
8799 {
8800 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8801 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8802 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8803 WIPHY_VENDOR_CMD_NEED_NETDEV |
8804 WIPHY_VENDOR_CMD_NEED_RUNNING,
8805 .doit = wlan_hdd_cfg80211_set_epno_list
8806 },
8807#endif /* FEATURE_WLAN_EXTSCAN */
8808
8809#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8810 {
8811 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8812 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8813 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8814 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8815 .doit = wlan_hdd_cfg80211_ll_stats_clear
8816 },
8817
8818 {
8819 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8820 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8821 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8822 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8823 .doit = wlan_hdd_cfg80211_ll_stats_set
8824 },
8825
8826 {
8827 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8828 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8829 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8830 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8831 .doit = wlan_hdd_cfg80211_ll_stats_get
8832 },
8833#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8834#ifdef FEATURE_WLAN_TDLS
8835 {
8836 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8837 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8838 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8839 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8840 .doit = wlan_hdd_cfg80211_exttdls_enable
8841 },
8842 {
8843 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8844 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8845 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8846 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8847 .doit = wlan_hdd_cfg80211_exttdls_disable
8848 },
8849 {
8850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8851 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8852 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8853 .doit = wlan_hdd_cfg80211_exttdls_get_status
8854 },
8855#endif
8856 {
8857 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8858 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8859 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8860 .doit = wlan_hdd_cfg80211_get_supported_features
8861 },
8862 {
8863 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8864 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8865 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8866 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8867 },
8868 {
8869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308872 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008873 },
8874 {
8875 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8876 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8877 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8878 WIPHY_VENDOR_CMD_NEED_NETDEV,
8879 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8880 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008881 {
8882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8883 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8884 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8885 WIPHY_VENDOR_CMD_NEED_NETDEV,
8886 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8887 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008888 {
8889 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308890 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8891 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8892 WIPHY_VENDOR_CMD_NEED_NETDEV |
8893 WIPHY_VENDOR_CMD_NEED_RUNNING,
8894 .doit = hdd_cfg80211_get_station_cmd
8895 },
8896 {
8897 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008898 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8899 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8900 WIPHY_VENDOR_CMD_NEED_NETDEV |
8901 WIPHY_VENDOR_CMD_NEED_RUNNING,
8902 .doit = wlan_hdd_cfg80211_do_acs
8903 },
8904
8905 {
8906 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8907 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8908 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8909 WIPHY_VENDOR_CMD_NEED_NETDEV,
8910 .doit = wlan_hdd_cfg80211_get_features
8911 },
8912#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8913 {
8914 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8915 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8916 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8917 WIPHY_VENDOR_CMD_NEED_NETDEV |
8918 WIPHY_VENDOR_CMD_NEED_RUNNING,
8919 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8920 },
8921#endif
8922#ifdef FEATURE_WLAN_EXTSCAN
8923 {
8924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8927 WIPHY_VENDOR_CMD_NEED_NETDEV |
8928 WIPHY_VENDOR_CMD_NEED_RUNNING,
8929 .doit = wlan_hdd_cfg80211_set_passpoint_list
8930 },
8931 {
8932 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8933 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8934 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8935 WIPHY_VENDOR_CMD_NEED_NETDEV |
8936 WIPHY_VENDOR_CMD_NEED_RUNNING,
8937 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8938 },
8939 {
8940 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8941 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8943 WIPHY_VENDOR_CMD_NEED_NETDEV |
8944 WIPHY_VENDOR_CMD_NEED_RUNNING,
8945 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8946 },
8947 {
8948 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8949 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8951 WIPHY_VENDOR_CMD_NEED_NETDEV |
8952 WIPHY_VENDOR_CMD_NEED_RUNNING,
8953 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8954 },
8955#endif /* FEATURE_WLAN_EXTSCAN */
8956 {
8957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8958 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8960 WIPHY_VENDOR_CMD_NEED_NETDEV,
8961 .doit = wlan_hdd_cfg80211_get_wifi_info
8962 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008963#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008964 {
8965 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8966 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8967 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8968 WIPHY_VENDOR_CMD_NEED_NETDEV |
8969 WIPHY_VENDOR_CMD_NEED_RUNNING,
8970 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8971 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008972#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008973 {
8974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8975 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8976 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8977 WIPHY_VENDOR_CMD_NEED_NETDEV,
8978 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8979 },
8980 {
8981 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8982 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8983 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8984 WIPHY_VENDOR_CMD_NEED_NETDEV,
8985 .doit = wlan_hdd_cfg80211_wifi_logger_start
8986 },
8987 {
8988 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8989 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8990 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8991 WIPHY_VENDOR_CMD_NEED_NETDEV,
8992 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8993 },
8994 {
8995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8996 .info.subcmd =
8997 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8998 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8999 WIPHY_VENDOR_CMD_NEED_NETDEV |
9000 WIPHY_VENDOR_CMD_NEED_RUNNING,
9001 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9002 },
9003 {
9004 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9005 .info.subcmd =
9006 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9007 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9008 WIPHY_VENDOR_CMD_NEED_NETDEV |
9009 WIPHY_VENDOR_CMD_NEED_RUNNING,
9010 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9011 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009012#ifdef WLAN_FEATURE_TSF
9013 {
9014 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9015 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9016 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9017 WIPHY_VENDOR_CMD_NEED_NETDEV |
9018 WIPHY_VENDOR_CMD_NEED_RUNNING,
9019 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9020 },
9021#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009022#ifdef FEATURE_WLAN_TDLS
9023 {
9024 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9025 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9026 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9027 WIPHY_VENDOR_CMD_NEED_NETDEV |
9028 WIPHY_VENDOR_CMD_NEED_RUNNING,
9029 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9030 },
9031#endif
9032#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9033 {
9034 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9035 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9036 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9037 WIPHY_VENDOR_CMD_NEED_NETDEV |
9038 WIPHY_VENDOR_CMD_NEED_RUNNING,
9039 .doit = wlan_hdd_cfg80211_offloaded_packets
9040 },
9041#endif
9042 {
9043 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9044 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9045 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9046 WIPHY_VENDOR_CMD_NEED_NETDEV |
9047 WIPHY_VENDOR_CMD_NEED_RUNNING,
9048 .doit = wlan_hdd_cfg80211_monitor_rssi
9049 },
9050 {
9051 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309052 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9053 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9054 WIPHY_VENDOR_CMD_NEED_NETDEV |
9055 WIPHY_VENDOR_CMD_NEED_RUNNING,
9056 .doit = wlan_hdd_cfg80211_set_ns_offload
9057 },
9058 {
9059 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009060 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9061 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9062 WIPHY_VENDOR_CMD_NEED_NETDEV |
9063 WIPHY_VENDOR_CMD_NEED_RUNNING,
9064 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9065 },
9066#ifdef WLAN_FEATURE_MEMDUMP
9067 {
9068 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9069 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9070 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9071 WIPHY_VENDOR_CMD_NEED_NETDEV |
9072 WIPHY_VENDOR_CMD_NEED_RUNNING,
9073 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9074 },
9075#endif /* WLAN_FEATURE_MEMDUMP */
9076 {
9077 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9078 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9079 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9080 WIPHY_VENDOR_CMD_NEED_NETDEV |
9081 WIPHY_VENDOR_CMD_NEED_RUNNING,
9082 .doit = wlan_hdd_cfg80211_vendor_scan
9083 },
9084
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309085 /* Vendor abort scan */
9086 {
9087 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9088 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9089 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9090 WIPHY_VENDOR_CMD_NEED_NETDEV |
9091 WIPHY_VENDOR_CMD_NEED_RUNNING,
9092 .doit = wlan_hdd_vendor_abort_scan
9093 },
9094
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009095 /* OCB commands */
9096 {
9097 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9098 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9099 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9100 WIPHY_VENDOR_CMD_NEED_NETDEV |
9101 WIPHY_VENDOR_CMD_NEED_RUNNING,
9102 .doit = wlan_hdd_cfg80211_ocb_set_config
9103 },
9104 {
9105 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9106 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9107 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9108 WIPHY_VENDOR_CMD_NEED_NETDEV |
9109 WIPHY_VENDOR_CMD_NEED_RUNNING,
9110 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9111 },
9112 {
9113 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9114 .info.subcmd =
9115 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9116 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9117 WIPHY_VENDOR_CMD_NEED_NETDEV |
9118 WIPHY_VENDOR_CMD_NEED_RUNNING,
9119 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9120 },
9121 {
9122 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9123 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9124 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9125 WIPHY_VENDOR_CMD_NEED_NETDEV |
9126 WIPHY_VENDOR_CMD_NEED_RUNNING,
9127 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9128 },
9129 {
9130 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9131 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9132 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9133 WIPHY_VENDOR_CMD_NEED_NETDEV |
9134 WIPHY_VENDOR_CMD_NEED_RUNNING,
9135 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9136 },
9137 {
9138 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9139 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9140 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9141 WIPHY_VENDOR_CMD_NEED_NETDEV |
9142 WIPHY_VENDOR_CMD_NEED_RUNNING,
9143 .doit = wlan_hdd_cfg80211_dcc_get_stats
9144 },
9145 {
9146 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9147 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9148 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9149 WIPHY_VENDOR_CMD_NEED_NETDEV |
9150 WIPHY_VENDOR_CMD_NEED_RUNNING,
9151 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9152 },
9153 {
9154 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9155 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9156 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9157 WIPHY_VENDOR_CMD_NEED_NETDEV |
9158 WIPHY_VENDOR_CMD_NEED_RUNNING,
9159 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9160 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309161 {
9162 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9163 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9164 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9165 WIPHY_VENDOR_CMD_NEED_NETDEV |
9166 WIPHY_VENDOR_CMD_NEED_RUNNING,
9167 .doit = wlan_hdd_cfg80211_get_link_properties
9168 },
Peng Xu278d0122015-09-24 16:34:17 -07009169 {
Peng Xud2220962016-07-11 17:59:17 -07009170 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009171 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9172 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9173 WIPHY_VENDOR_CMD_NEED_NETDEV |
9174 WIPHY_VENDOR_CMD_NEED_RUNNING,
9175 .doit = wlan_hdd_cfg80211_set_ota_test
9176 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009177#ifdef FEATURE_LFR_SUBNET_DETECTION
9178 {
9179 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9180 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9181 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9182 WIPHY_VENDOR_CMD_NEED_NETDEV |
9183 WIPHY_VENDOR_CMD_NEED_RUNNING,
9184 .doit = wlan_hdd_cfg80211_set_gateway_params
9185 },
9186#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009187 {
Peng Xud2220962016-07-11 17:59:17 -07009188 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009189 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9190 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9191 WIPHY_VENDOR_CMD_NEED_NETDEV |
9192 WIPHY_VENDOR_CMD_NEED_RUNNING,
9193 .doit = wlan_hdd_cfg80211_txpower_scale
9194 },
9195 {
9196 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9197 .info.subcmd =
9198 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9199 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9200 WIPHY_VENDOR_CMD_NEED_NETDEV |
9201 WIPHY_VENDOR_CMD_NEED_RUNNING,
9202 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9203 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309204 {
9205 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9206 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9207 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9208 WIPHY_VENDOR_CMD_NEED_NETDEV |
9209 WIPHY_VENDOR_CMD_NEED_RUNNING,
9210 .doit = wlan_hdd_cfg80211_bpf_offload
9211 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309212 {
9213 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309214 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9215 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9216 WIPHY_VENDOR_CMD_NEED_NETDEV |
9217 WIPHY_VENDOR_CMD_NEED_RUNNING,
9218 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9219 },
9220 {
9221 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309222 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9223 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9224 WIPHY_VENDOR_CMD_NEED_NETDEV |
9225 WIPHY_VENDOR_CMD_NEED_RUNNING,
9226 .doit = wlan_hdd_cfg80211_sta_roam_policy
9227 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309228#ifdef FEATURE_WLAN_CH_AVOID
9229 {
9230 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9231 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9232 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9233 WIPHY_VENDOR_CMD_NEED_NETDEV |
9234 WIPHY_VENDOR_CMD_NEED_RUNNING,
9235 .doit = wlan_hdd_cfg80211_avoid_freq
9236 },
9237#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309238 {
9239 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309240 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9241 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9242 WIPHY_VENDOR_CMD_NEED_NETDEV |
9243 WIPHY_VENDOR_CMD_NEED_RUNNING,
9244 .doit = wlan_hdd_cfg80211_sap_configuration_set
9245 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009246 {
Peng Xu4225c152016-07-14 21:18:14 -07009247 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009248 .info.subcmd =
9249 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9250 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9251 WIPHY_VENDOR_CMD_NEED_NETDEV |
9252 WIPHY_VENDOR_CMD_NEED_RUNNING,
9253 .doit = wlan_hdd_cfg80211_p2p_lo_start
9254 },
9255 {
9256 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9257 .info.subcmd =
9258 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9259 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9260 WIPHY_VENDOR_CMD_NEED_NETDEV |
9261 WIPHY_VENDOR_CMD_NEED_RUNNING,
9262 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9263 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309264 {
9265 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9266 .info.subcmd =
9267 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9268 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9269 WIPHY_VENDOR_CMD_NEED_NETDEV |
9270 WIPHY_VENDOR_CMD_NEED_RUNNING,
9271 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9272 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009273#ifdef WLAN_FEATURE_NAN_DATAPATH
9274 {
9275 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9276 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9277 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9278 WIPHY_VENDOR_CMD_NEED_NETDEV |
9279 WIPHY_VENDOR_CMD_NEED_RUNNING,
9280 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9281 },
9282#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309283 {
9284 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9285 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9286 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9287 WIPHY_VENDOR_CMD_NEED_NETDEV |
9288 WIPHY_VENDOR_CMD_NEED_RUNNING,
9289 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9290 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309291 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309292 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9293 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9294 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9295 WIPHY_VENDOR_CMD_NEED_NETDEV |
9296 WIPHY_VENDOR_CMD_NEED_RUNNING,
9297 .doit = wlan_hdd_cfg80211_get_bus_size
9298 },
9299 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309300 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9301 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9302 WIPHY_VENDOR_CMD_NEED_NETDEV |
9303 WIPHY_VENDOR_CMD_NEED_RUNNING,
9304 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309305 },
9306 {
9307 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9308 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9309 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9310 WIPHY_VENDOR_CMD_NEED_NETDEV |
9311 WIPHY_VENDOR_CMD_NEED_RUNNING,
9312 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309313 },
9314#ifdef WLAN_FEATURE_DISA
9315 {
9316 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9317 .info.subcmd =
9318 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
9319 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9320 WIPHY_VENDOR_CMD_NEED_NETDEV |
9321 WIPHY_VENDOR_CMD_NEED_RUNNING,
9322 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
9323 },
9324#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009325#ifdef FEATURE_WLAN_TDLS
9326 {
9327 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9328 .info.subcmd =
9329 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
9330 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9331 WIPHY_VENDOR_CMD_NEED_NETDEV |
9332 WIPHY_VENDOR_CMD_NEED_RUNNING,
9333 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009334 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009335#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009336 {
9337 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9338 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
9339 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9340 WIPHY_VENDOR_CMD_NEED_RUNNING,
9341 .doit = wlan_hdd_cfg80211_set_sar_power_limits
9342 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309343 {
9344 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9345 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
9346 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9347 WIPHY_VENDOR_CMD_NEED_NETDEV |
9348 WIPHY_VENDOR_CMD_NEED_RUNNING,
9349 .doit = wlan_hdd_cfg80211_set_trace_level
9350 },
9351
Paul Zhang3a210c52016-12-08 10:18:12 +08009352#ifdef WLAN_UMAC_CONVERGENCE
9353 COMMON_VENDOR_COMMANDS
9354#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009355};
9356
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309357#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
9358 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
9359 defined(FEATURE_WLAN_SCAN_PNO)
9360/**
9361 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
9362 * @wiphy: pointer to wiphy
9363 * @config: pointer to config
9364 *
9365 * Return: None
9366 */
9367static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9368 struct hdd_config *config)
9369{
9370 if (config->configPNOScanSupport) {
9371 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9372 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
9373 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
9374 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
9375 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
9376 if (config->max_sched_scan_plan_interval)
9377 wiphy->max_sched_scan_plan_interval =
9378 config->max_sched_scan_plan_interval;
9379 if (config->max_sched_scan_plan_iterations)
9380 wiphy->max_sched_scan_plan_iterations =
9381 config->max_sched_scan_plan_iterations;
9382 }
9383}
9384#else
9385static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9386 struct hdd_config *config)
9387{
9388}
9389#endif
9390
9391
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009392/**
9393 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
9394 * @priv_size: Size of the hdd context.
9395 *
9396 * Allocate wiphy context and hdd context.
9397 *
9398 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009399 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009400hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009401{
9402 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009403 hdd_context_t *hdd_ctx;
9404
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009405 ENTER();
9406
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009407 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
9408
9409 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009410 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009411 return NULL;
9412 }
9413
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009414 hdd_ctx = wiphy_priv(wiphy);
9415
9416 hdd_ctx->wiphy = wiphy;
9417
9418 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009419}
9420
9421/*
9422 * FUNCTION: wlan_hdd_cfg80211_update_band
9423 * This function is called from the supplicant through a
9424 * private ioctl to change the band value
9425 */
9426int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
9427{
9428 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07009429 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009430
9431 ENTER();
9432
Dustin Browna30892e2016-10-12 17:28:36 -07009433 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009434
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009435 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009436 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009437
9438 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9439 struct ieee80211_supported_band *band = wiphy->bands[i];
9440
9441 channelEnabledState =
9442 cds_get_channel_state(band->channels[j].
9443 hw_value);
9444
Dustin Browna30892e2016-10-12 17:28:36 -07009445 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446 /* 5G only */
9447#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9448 /* Enable Social channels for P2P */
9449 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9450 (band->channels[j].center_freq)
9451 && CHANNEL_STATE_ENABLE ==
9452 channelEnabledState)
9453 band->channels[j].flags &=
9454 ~IEEE80211_CHAN_DISABLED;
9455 else
9456#endif
9457 band->channels[j].flags |=
9458 IEEE80211_CHAN_DISABLED;
9459 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009460 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009461 eCSR_BAND_24 == eBand) {
9462 /* 2G only */
9463 band->channels[j].flags |=
9464 IEEE80211_CHAN_DISABLED;
9465 continue;
9466 }
9467
Amar Singhal6842e8f2016-02-23 16:30:32 -08009468 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009469 band->channels[j].flags &=
9470 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009471 }
9472 }
9473 return 0;
9474}
9475
Peng Xuacfdda12017-02-06 16:15:38 -08009476#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009477/*
9478 * FUNCTION: wlan_hdd_cfg80211_init
9479 * This function is called by hdd_wlan_startup()
9480 * during initialization.
9481 * This function is used to initialize and register wiphy structure.
9482 */
9483int wlan_hdd_cfg80211_init(struct device *dev,
9484 struct wiphy *wiphy, struct hdd_config *pCfg)
9485{
9486 int i, j;
9487 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9488
9489 ENTER();
9490
9491 /* Now bind the underlying wlan device with wiphy */
9492 set_wiphy_dev(wiphy, dev);
9493
9494 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
9495
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009496#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9497 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009498 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009499#else
9500 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009501 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009502#endif
9503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009504 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
9505 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
9506 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
9507#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
9508 | WIPHY_FLAG_4ADDR_STATION
9509#endif
9510 | WIPHY_FLAG_OFFCHAN_TX;
9511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009512#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9513 wiphy->wowlan = &wowlan_support_cfg80211_init;
9514#else
9515 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
9516 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
9517 wiphy->wowlan.pattern_min_len = 1;
9518 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
9519#endif
9520
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07009521 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009522#ifdef FEATURE_WLAN_ESE
9523 || pCfg->isEseIniFeatureEnabled
9524#endif
9525 ) {
9526 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9527 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009528#ifdef FEATURE_WLAN_TDLS
9529 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
9530 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
9531#endif
9532
9533 wiphy->features |= NL80211_FEATURE_HT_IBSS;
9534
Naveen Rawatc77e6e72016-08-05 15:19:03 -07009535#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
9536 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
9537#endif
9538
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309539 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009540
9541#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05309542 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009543#endif
9544
9545 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009546 * driver can still register regulatory callback and
9547 * it will get regulatory settings in wiphy->band[], but
9548 * driver need to determine what to do with both
9549 * regulatory settings
9550 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009551
9552 wiphy->reg_notifier = hdd_reg_notifier;
9553
9554#if defined QCA_WIFI_FTM
9555}
9556#endif
9557
9558 wiphy->max_scan_ssids = MAX_SCAN_SSID;
9559
9560 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
9561
9562 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
9563
Arun Khandavallifae92942016-08-01 13:31:08 +05309564 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
9565 | BIT(NL80211_IFTYPE_ADHOC)
9566 | BIT(NL80211_IFTYPE_P2P_CLIENT)
9567 | BIT(NL80211_IFTYPE_P2P_GO)
9568 | BIT(NL80211_IFTYPE_AP)
9569 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009570
Arun Khandavallifae92942016-08-01 13:31:08 +05309571 if (pCfg->advertiseConcurrentOperation) {
9572 if (pCfg->enableMCC) {
9573 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07009574
Arun Khandavallifae92942016-08-01 13:31:08 +05309575 for (i = 0;
9576 i < ARRAY_SIZE(wlan_hdd_iface_combination);
9577 i++) {
9578 if (!pCfg->allowMCCGODiffBI)
9579 wlan_hdd_iface_combination[i].
9580 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581 }
9582 }
9583 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05309584 ARRAY_SIZE(wlan_hdd_iface_combination);
9585 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009586 }
9587
9588 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009589 * on ini values
9590 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009591 if (!pCfg->ShortGI20MhzEnable) {
9592 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
9593 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009594 }
9595
9596 if (!pCfg->ShortGI40MhzEnable) {
9597 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
9598 }
9599
9600 if (!pCfg->nChannelBondingMode5GHz) {
9601 wlan_hdd_band_5_ghz.ht_cap.cap &=
9602 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
9603 }
9604
Abhishek Singhf512bf32016-05-04 16:47:46 +05309605 /*
9606 * In case of static linked driver at the time of driver unload,
9607 * module exit doesn't happens. Module cleanup helps in cleaning
9608 * of static memory.
9609 * If driver load happens statically, at the time of driver unload,
9610 * wiphy flags don't get reset because of static memory.
9611 * It's better not to store channel in static memory.
9612 */
Dustin Browna30892e2016-10-12 17:28:36 -07009613 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
9614 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309615 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009616 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309617 hdd_err("Not enough memory to allocate channels");
9618 return -ENOMEM;
9619 }
Dustin Browna30892e2016-10-12 17:28:36 -07009620 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309621 &hdd_channels_2_4_ghz[0],
9622 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05309623 if ((hdd_is_5g_supported(pHddCtx)) &&
9624 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
9625 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
9626 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
9627 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07009628 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
9629 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309630 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009631 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309632 hdd_err("Not enough memory to allocate channels");
9633 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07009634 bands[NL80211_BAND_2GHZ]->channels);
9635 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05309636 return -ENOMEM;
9637 }
Dustin Browna30892e2016-10-12 17:28:36 -07009638 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309639 &hdd_channels_5_ghz[0],
9640 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009641 }
9642
Dustin Browna30892e2016-10-12 17:28:36 -07009643 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009644
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009645 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009646 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009647
9648 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9649 struct ieee80211_supported_band *band = wiphy->bands[i];
9650
Dustin Browna30892e2016-10-12 17:28:36 -07009651 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009652 eCSR_BAND_5G == pCfg->nBandCapability) {
9653 /* 5G only */
9654#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9655 /* Enable social channels for P2P */
9656 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9657 (band->channels[j].center_freq))
9658 band->channels[j].flags &=
9659 ~IEEE80211_CHAN_DISABLED;
9660 else
9661#endif
9662 band->channels[j].flags |=
9663 IEEE80211_CHAN_DISABLED;
9664 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009665 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009666 eCSR_BAND_24 == pCfg->nBandCapability) {
9667 /* 2G only */
9668 band->channels[j].flags |=
9669 IEEE80211_CHAN_DISABLED;
9670 continue;
9671 }
9672 }
9673 }
9674 /*Initialise the supported cipher suite details */
9675 wiphy->cipher_suites = hdd_cipher_suites;
9676 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
9677
9678 /*signal strength in mBm (100*dBm) */
9679 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9680 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
9681
Anurag Chouhan6d760662016-02-20 16:05:43 +05309682 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 wiphy->n_vendor_commands =
9684 ARRAY_SIZE(hdd_wiphy_vendor_commands);
9685 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
9686
9687 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
9688 wiphy->n_vendor_events =
9689 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
9690 }
9691
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009692 if (pCfg->enableDFSMasterCap) {
9693 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
9694 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695
9696 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
9697
9698#ifdef QCA_HT_2040_COEX
9699 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9700#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309701 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309702 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -08009703 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009705 EXIT();
9706 return 0;
9707}
9708
Abhishek Singhf512bf32016-05-04 16:47:46 +05309709/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009710 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9711 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309712 *
9713 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309714 * memory allocated in wlan_hdd_cfg80211_init also
9715 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309716 *
9717 * Return: void
9718 */
9719void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9720{
9721 int i;
9722
Dustin Browna30892e2016-10-12 17:28:36 -07009723 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309724 if (NULL != wiphy->bands[i] &&
9725 (NULL != wiphy->bands[i]->channels)) {
9726 qdf_mem_free(wiphy->bands[i]->channels);
9727 wiphy->bands[i]->channels = NULL;
9728 }
9729 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309730 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309731}
9732
Yingying Tang80e15f32016-09-27 18:23:01 +08009733/**
9734 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9735 * @hdd_ctx: HDD context
9736 *
9737 * this function will update capabilities for supported bands
9738 *
9739 * Return: void
9740 */
9741static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9742{
9743 uint32_t val32;
9744 uint16_t val16;
9745 tSirMacHTCapabilityInfo *ht_cap_info;
9746 QDF_STATUS status;
9747
9748 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9749 if (QDF_STATUS_SUCCESS != status) {
9750 hdd_err("could not get HT capability info");
9751 val32 = 0;
9752 }
9753 val16 = (uint16_t)val32;
9754 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9755
9756 if (ht_cap_info->txSTBC == true) {
9757 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9758 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9759 IEEE80211_HT_CAP_TX_STBC;
9760 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9761 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9762 IEEE80211_HT_CAP_TX_STBC;
9763 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009764
9765 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9766 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9767 vht_cap.vht_supported = 0;
9768 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9769 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9770 vht_cap.vht_supported = 0;
9771 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9772 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009773}
9774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009775/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309776 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009777 * initialization. In wlan_hdd_cfg80211_init, only the
9778 * default values will be initialized. The final initialization
9779 * of all required members can be done here.
9780 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009781void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009782{
Yingying Tang80e15f32016-09-27 18:23:01 +08009783 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9784
9785 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009786}
9787
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009788/**
9789 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9790 * @cfg: hdd cfg
9791 *
9792 * this function update 11n mode in hdd cfg
9793 *
9794 * Return: void
9795 */
9796void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9797{
9798 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9799 hdd_notice("support 11ac");
9800 } else {
9801 hdd_notice("not support 11ac");
9802 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9803 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9804 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9805 cfg->sap_p2p_11ac_override = 0;
9806 }
9807 }
9808}
9809
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810/* In this function we are registering wiphy. */
9811int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9812{
9813 ENTER();
9814 /* Register our wiphy dev with cfg80211 */
9815 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009816 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009817 return -EIO;
9818 }
9819
9820 EXIT();
9821 return 0;
9822}
9823
9824/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009825 * HDD function to update wiphy capability based on target offload status.
9826 *
9827 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
9828 * capability even before downloading firmware to the target. In discrete
9829 * case, host will get know certain offload capability (say sched_scan
9830 * caps) only after downloading firmware to the target and target boots up.
9831 * This function is used to override setting done in wlan_hdd_cfg80211_init()
9832 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009833 */
9834void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9835{
9836#ifdef FEATURE_WLAN_SCAN_PNO
9837 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9838 struct hdd_config *pCfg = pHddCtx->config;
9839
9840 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9841 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009842 * have PNO support.
9843 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009844 if (!pCfg->PnoOffload) {
9845 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9846 wiphy->max_sched_scan_ssids = 0;
9847 wiphy->max_match_sets = 0;
9848 wiphy->max_sched_scan_ie_len = 0;
9849 }
9850#endif
9851}
9852
9853/* This function registers for all frame which supplicant is interested in */
9854void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9855{
9856 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9857 /* Register for all P2P action, public action etc frames */
9858 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9859
9860 ENTER();
9861
Abhishek Singh7996eb72015-12-30 17:24:02 +05309862 /* Register frame indication call back */
9863 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9864
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309865 /* Register for p2p ack indication */
9866 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9867
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009868 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009869 * initialized. Once we will move to 2.6.37 kernel, in which we have
9870 * frame register ops, we will move this code as a part of that
9871 */
9872
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009873 /* GAS Initial Request */
9874 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9875 (uint8_t *) GAS_INITIAL_REQ,
9876 GAS_INITIAL_REQ_SIZE);
9877
9878 /* GAS Initial Response */
9879 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9880 (uint8_t *) GAS_INITIAL_RSP,
9881 GAS_INITIAL_RSP_SIZE);
9882
9883 /* GAS Comeback Request */
9884 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9885 (uint8_t *) GAS_COMEBACK_REQ,
9886 GAS_COMEBACK_REQ_SIZE);
9887
9888 /* GAS Comeback Response */
9889 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9890 (uint8_t *) GAS_COMEBACK_RSP,
9891 GAS_COMEBACK_RSP_SIZE);
9892
9893 /* P2P Public Action */
9894 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9895 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9896 P2P_PUBLIC_ACTION_FRAME_SIZE);
9897
9898 /* P2P Action */
9899 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9900 (uint8_t *) P2P_ACTION_FRAME,
9901 P2P_ACTION_FRAME_SIZE);
9902
9903 /* WNM BSS Transition Request frame */
9904 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9905 (uint8_t *) WNM_BSS_ACTION_FRAME,
9906 WNM_BSS_ACTION_FRAME_SIZE);
9907
9908 /* WNM-Notification */
9909 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9910 (uint8_t *) WNM_NOTIFICATION_FRAME,
9911 WNM_NOTIFICATION_FRAME_SIZE);
9912}
9913
9914void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9915{
9916 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9917 /* Register for all P2P action, public action etc frames */
9918 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9919
9920 ENTER();
9921
9922 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009923 * initialized. Once we will move to 2.6.37 kernel, in which we have
9924 * frame register ops, we will move this code as a part of that
9925 */
9926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009927 /* GAS Initial Request */
9928
9929 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9930 (uint8_t *) GAS_INITIAL_REQ,
9931 GAS_INITIAL_REQ_SIZE);
9932
9933 /* GAS Initial Response */
9934 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9935 (uint8_t *) GAS_INITIAL_RSP,
9936 GAS_INITIAL_RSP_SIZE);
9937
9938 /* GAS Comeback Request */
9939 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9940 (uint8_t *) GAS_COMEBACK_REQ,
9941 GAS_COMEBACK_REQ_SIZE);
9942
9943 /* GAS Comeback Response */
9944 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9945 (uint8_t *) GAS_COMEBACK_RSP,
9946 GAS_COMEBACK_RSP_SIZE);
9947
9948 /* P2P Public Action */
9949 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9950 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9951 P2P_PUBLIC_ACTION_FRAME_SIZE);
9952
9953 /* P2P Action */
9954 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9955 (uint8_t *) P2P_ACTION_FRAME,
9956 P2P_ACTION_FRAME_SIZE);
9957
9958 /* WNM-Notification */
9959 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9960 (uint8_t *) WNM_NOTIFICATION_FRAME,
9961 WNM_NOTIFICATION_FRAME_SIZE);
9962}
9963
9964#ifdef FEATURE_WLAN_WAPI
9965void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9966 const uint8_t *mac_addr, const uint8_t *key,
9967 int key_Len)
9968{
9969 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9970 tCsrRoamSetKey setKey;
9971 bool isConnected = true;
9972 int status = 0;
9973 uint32_t roamId = 0xFF;
9974 uint8_t *pKeyPtr = NULL;
9975 int n = 0;
9976
Jeff Johnson46b40792016-06-29 14:03:14 -07009977 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009978 hdd_device_mode_to_string(pAdapter->device_mode),
9979 pAdapter->device_mode);
9980
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309981 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009982 setKey.keyId = key_index; /* Store Key ID */
9983 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9984 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9985 setKey.paeRole = 0; /* the PAE role */
9986 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309987 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009988 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309989 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 }
9991 setKey.keyLength = key_Len;
9992 pKeyPtr = setKey.Key;
9993 memcpy(pKeyPtr, key, key_Len);
9994
Jeff Johnson46b40792016-06-29 14:03:14 -07009995 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009996 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009997 hdd_notice("WAPI KEY Data[%d]:%02x ",
9998 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009999
10000 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10001 if (isConnected) {
10002 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10003 pAdapter->sessionId, &setKey, &roamId);
10004 }
10005 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010006 hdd_err("sme_roam_set_key returned ERROR status= %d",
10007 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010008 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10009 }
10010}
10011#endif /* FEATURE_WLAN_WAPI */
10012
10013uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10014 uint8_t eid)
10015{
10016 int left = length;
10017 uint8_t *ptr = (uint8_t *)ies_ptr;
10018 uint8_t elem_id, elem_len;
10019
10020 while (left >= 2) {
10021 elem_id = ptr[0];
10022 elem_len = ptr[1];
10023 left -= 2;
10024 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010025 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010026 eid, elem_len, left);
10027 return NULL;
10028 }
10029 if (elem_id == eid) {
10030 return ptr;
10031 }
10032
10033 left -= elem_len;
10034 ptr += (elem_len + 2);
10035 }
10036 return NULL;
10037}
10038
10039/*
10040 * FUNCTION: wlan_hdd_validate_operation_channel
10041 * called by wlan_hdd_cfg80211_start_bss() and
10042 * wlan_hdd_set_channel()
10043 * This function validates whether given channel is part of valid
10044 * channel list.
10045 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010046QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010047 int channel)
10048{
10049
10050 uint32_t num_ch = 0;
10051 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10052 u32 indx = 0;
10053 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10054 uint8_t fValidChannel = false, count = 0;
10055 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10056
10057 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10058
10059 if (hdd_pConfig_ini->sapAllowAllChannel) {
10060 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010061 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010062 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010063 fValidChannel = true;
10064 break;
10065 }
10066 }
10067 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010068 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010069 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 }
10071 } else {
10072 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10073 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010074 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010075 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010076 }
10077 for (indx = 0; indx < num_ch; indx++) {
10078 if (channel == valid_ch[indx]) {
10079 break;
10080 }
10081 }
10082
10083 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010084 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010085 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010086 }
10087 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010088 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010089
10090}
10091
10092#ifdef DHCP_SERVER_OFFLOAD
10093static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10094{
10095 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10096 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10097 uint8_t numEntries = 0;
10098 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10099 uint8_t num;
10100 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010101 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010103 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010104 return;
10105 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010106 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10107 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10108 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10109 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10110 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10111 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010112 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010113 goto end;
10114 }
10115 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010116 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 goto end;
10118 }
10119 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010120 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010121 goto end;
10122 }
10123 for (num = 0; num < numEntries; num++) {
10124 temp = srv_ip[num];
10125 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10126 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010127 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010129 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010130 goto end;
10131 }
Jeff Johnson77848112016-06-29 14:52:06 -070010132 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010133end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010134 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 return;
10136}
10137#endif /* DHCP_SERVER_OFFLOAD */
10138
10139static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10140 struct net_device *dev,
10141 struct bss_parameters *params)
10142{
10143 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10144 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10145 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010146 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147
10148 ENTER();
10149
Anurag Chouhan6d760662016-02-20 16:05:43 +053010150 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010151 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010152 return -EINVAL;
10153 }
10154
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010155 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10156 hdd_err("invalid session id: %d", pAdapter->sessionId);
10157 return -EINVAL;
10158 }
10159
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010160 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10162 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010163 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010164 hdd_device_mode_to_string(pAdapter->device_mode),
10165 pAdapter->device_mode, params->ap_isolate);
10166
10167 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10168 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010169 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171
Krunal Sonib4326f22016-03-10 13:05:51 -080010172 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10173 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010174 return -EOPNOTSUPP;
10175 }
10176
10177 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010178 * want to update this parameter
10179 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010180 if (-1 != params->ap_isolate) {
10181 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10182 !!params->ap_isolate;
10183
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010184 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185 pAdapter->sessionId,
10186 pAdapter->sessionCtx.
10187 ap.
10188 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010189 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010190 ret = -EINVAL;
10191 }
10192 }
10193
10194 EXIT();
10195 return ret;
10196}
10197
Krunal Soni8c37e322016-02-03 16:08:37 -080010198/**
10199 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10200 * @ndev: pointer to net device provided by supplicant
10201 * @type: type of the interface, upper layer wanted to change
10202 *
10203 * Upper layer provides the new interface mode that needs to be changed
10204 * for given net device
10205 *
10206 * Return: success or failure in terms of integer value
10207 */
10208static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010209 enum nl80211_iftype type)
10210{
Krunal Soni8c37e322016-02-03 16:08:37 -080010211 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10212 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10213 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214 hdd_wext_state_t *wext;
10215 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010216 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010217
10218 ENTER();
10219
Krunal Soni8c37e322016-02-03 16:08:37 -080010220 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010221 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010222 return 0;
10223 }
10224
10225 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010226 hdd_stop_adapter(hdd_ctx, adapter, true);
10227 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010228 wdev->iftype = type;
10229 /*Check for sub-string p2p to confirm its a p2p interface */
10230 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010231 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010232 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010233 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010234 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010235 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010236 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010237 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010238 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010239 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010240 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010241 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10242 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010243 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10244 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010245 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010246 adapter->scan_info.scanAddIE.length;
10247 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010248 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010249 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10250 wext->roamProfile.phyMode =
10251 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10252 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253 EXIT();
10254 return status;
10255}
10256
10257static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10258 struct net_device *dev,
10259 struct bss_parameters *params)
10260{
10261 int ret;
10262
10263 cds_ssr_protect(__func__);
10264 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10265 cds_ssr_unprotect(__func__);
10266
10267 return ret;
10268}
10269
10270/* FUNCTION: wlan_hdd_change_country_code_cd
10271 * to wait for contry code completion
10272 */
10273void *wlan_hdd_change_country_code_cb(void *pAdapter)
10274{
10275 hdd_adapter_t *call_back_pAdapter = pAdapter;
10276 complete(&call_back_pAdapter->change_country_code);
10277 return NULL;
10278}
10279
Rajeev Kumar98edb772016-01-19 12:42:19 -080010280/**
10281 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10282 * @wiphy: Pointer to the wiphy structure
10283 * @ndev: Pointer to the net device
10284 * @type: Interface type
10285 * @flags: Flags for change interface
10286 * @params: Pointer to change interface parameters
10287 *
10288 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010289 */
10290static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10291 struct net_device *ndev,
10292 enum nl80211_iftype type,
10293 u32 *flags,
10294 struct vif_params *params)
10295{
10296 struct wireless_dev *wdev;
10297 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10298 hdd_context_t *pHddCtx;
10299 tCsrRoamProfile *pRoamProfile = NULL;
10300 eCsrRoamBssType LastBSSType;
10301 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010302 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010303 int status;
10304
10305 ENTER();
10306
Anurag Chouhan6d760662016-02-20 16:05:43 +053010307 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010308 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010309 return -EINVAL;
10310 }
10311
10312 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10313 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010314 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010316
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010317 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
10319 pAdapter->sessionId, type));
10320
Jeff Johnson77848112016-06-29 14:52:06 -070010321 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010322 pAdapter->device_mode, type);
10323
Arun Khandavallifae92942016-08-01 13:31:08 +053010324 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
10325 if (status) {
10326 hdd_err("Failed to start modules");
10327 return -EINVAL;
10328 }
10329
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010330 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010331 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
10332 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010333 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010334 return -EINVAL;
10335 }
10336
10337 pConfig = pHddCtx->config;
10338 wdev = ndev->ieee80211_ptr;
10339
10340 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010341 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010342
10343 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
10344
Krunal Sonib4326f22016-03-10 13:05:51 -080010345 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10346 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
10347 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
10348 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010349 hdd_wext_state_t *pWextState =
10350 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10351
10352 pRoamProfile = &pWextState->roamProfile;
10353 LastBSSType = pRoamProfile->BSSType;
10354
10355 switch (type) {
10356 case NL80211_IFTYPE_STATION:
10357 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080010358 case NL80211_IFTYPE_ADHOC:
10359 if (type == NL80211_IFTYPE_ADHOC) {
10360 wlan_hdd_tdls_exit(pAdapter);
10361 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070010362 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080010363 }
10364 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
10365 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010366 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010368 if (hdd_start_adapter(pAdapter)) {
10369 hdd_err("Failed to start adapter :%d",
10370 pAdapter->device_mode);
10371 return -EINVAL;
10372 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010373 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010374 case NL80211_IFTYPE_AP:
10375 case NL80211_IFTYPE_P2P_GO:
10376 {
Jeff Johnson77848112016-06-29 14:52:06 -070010377 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010378 (type ==
10379 NL80211_IFTYPE_AP) ? "SoftAP" :
10380 "P2pGo");
10381
10382 /* Cancel any remain on channel for GO mode */
10383 if (NL80211_IFTYPE_P2P_GO == type) {
10384 wlan_hdd_cancel_existing_remain_on_channel
10385 (pAdapter);
10386 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010387
Arun Khandavallifae92942016-08-01 13:31:08 +053010388 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010389 /* De-init the adapter */
10390 hdd_deinit_adapter(pHddCtx, pAdapter, true);
10391 memset(&pAdapter->sessionCtx, 0,
10392 sizeof(pAdapter->sessionCtx));
10393 pAdapter->device_mode =
10394 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080010395 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
10396 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010397
10398 /*
10399 * Fw will take care incase of concurrency
10400 */
10401
Krunal Sonib4326f22016-03-10 13:05:51 -080010402 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010404 /* To meet Android requirements create
10405 * a randomized MAC address of the
10406 * form 02:1A:11:Fx:xx:xx
10407 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010408 get_random_bytes(&ndev->dev_addr[3], 3);
10409 ndev->dev_addr[0] = 0x02;
10410 ndev->dev_addr[1] = 0x1A;
10411 ndev->dev_addr[2] = 0x11;
10412 ndev->dev_addr[3] |= 0xF0;
10413 memcpy(pAdapter->macAddressCurrent.
10414 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010415 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416 pr_info("wlan: Generated HotSpot BSSID "
10417 MAC_ADDRESS_STR "\n",
10418 MAC_ADDR_ARRAY(ndev->dev_addr));
10419 }
10420
10421 hdd_set_ap_ops(pAdapter->dev);
10422
Arun Khandavallifae92942016-08-01 13:31:08 +053010423 if (hdd_start_adapter(pAdapter)) {
10424 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010425 return -EINVAL;
10426 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010427 /* Interface type changed update in wiphy structure */
10428 if (wdev) {
10429 wdev->iftype = type;
10430 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010431 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010432 return -EINVAL;
10433 }
10434 goto done;
10435 }
10436
10437 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010438 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010439 type);
10440 return -EOPNOTSUPP;
10441 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010442 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10443 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010444 switch (type) {
10445 case NL80211_IFTYPE_STATION:
10446 case NL80211_IFTYPE_P2P_CLIENT:
10447 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080010448 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
10449 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010450 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010451 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010452 if (hdd_start_adapter(pAdapter)) {
10453 hdd_err("Failed to start adapter :%d",
10454 pAdapter->device_mode);
10455 return -EINVAL;
10456 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010457 goto done;
10458
10459 case NL80211_IFTYPE_AP:
10460 case NL80211_IFTYPE_P2P_GO:
10461 wdev->iftype = type;
10462 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010463 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010464 goto done;
10465
10466 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010467 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010468 type);
10469 return -EOPNOTSUPP;
10470 }
10471 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010472 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010473 pAdapter->device_mode);
10474 return -EOPNOTSUPP;
10475 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010476done:
10477 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010478 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010479
Jeff Johnson2ae6f712016-09-23 15:08:48 -070010480 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010481
10482 EXIT();
10483 return 0;
10484}
10485
Rajeev Kumar98edb772016-01-19 12:42:19 -080010486/**
10487 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10488 * @wiphy: Pointer to the wiphy structure
10489 * @ndev: Pointer to the net device
10490 * @type: Interface type
10491 * @flags: Flags for change interface
10492 * @params: Pointer to change interface parameters
10493 *
10494 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010495 */
10496static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10497 struct net_device *ndev,
10498 enum nl80211_iftype type,
10499 u32 *flags,
10500 struct vif_params *params)
10501{
10502 int ret;
10503
10504 cds_ssr_protect(__func__);
10505 ret =
10506 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
10507 cds_ssr_unprotect(__func__);
10508
10509 return ret;
10510}
10511
10512#ifdef FEATURE_WLAN_TDLS
10513static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
10514 int index, uint8_t match)
10515{
10516 int i;
10517 for (i = 0; i < index; i++) {
10518 if (arr[i] == match)
10519 return true;
10520 }
10521 return false;
10522}
10523#endif
10524
10525/**
10526 * __wlan_hdd_change_station() - change station
10527 * @wiphy: Pointer to the wiphy structure
10528 * @dev: Pointer to the net device.
10529 * @mac: bssid
10530 * @params: Pointer to station parameters
10531 *
10532 * Return: 0 for success, error number on failure.
10533 */
10534#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10535static int __wlan_hdd_change_station(struct wiphy *wiphy,
10536 struct net_device *dev,
10537 const uint8_t *mac,
10538 struct station_parameters *params)
10539#else
10540static int __wlan_hdd_change_station(struct wiphy *wiphy,
10541 struct net_device *dev,
10542 uint8_t *mac,
10543 struct station_parameters *params)
10544#endif
10545{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010546 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010547 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10548 hdd_context_t *pHddCtx;
10549 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053010550 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010551#ifdef FEATURE_WLAN_TDLS
10552 tCsrStaParams StaParams = { 0 };
10553 uint8_t isBufSta = 0;
10554 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053010555 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556#endif
10557 int ret;
10558
10559 ENTER();
10560
Anurag Chouhan6d760662016-02-20 16:05:43 +053010561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010562 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010563 return -EINVAL;
10564 }
10565
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010566 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567 TRACE_CODE_HDD_CHANGE_STATION,
10568 pAdapter->sessionId, params->listen_interval));
10569
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010570 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10571 hdd_err("invalid session id: %d", pAdapter->sessionId);
10572 return -EINVAL;
10573 }
10574
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010575 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10576 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010577 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010578 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010579
10580 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10581
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010582 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010583
Krunal Sonib4326f22016-03-10 13:05:51 -080010584 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10585 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010586 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
10587 status =
10588 hdd_softap_change_sta_state(pAdapter,
10589 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080010590 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010591
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010592 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010593 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010594 return -EINVAL;
10595 }
10596 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010597 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10598 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010599#ifdef FEATURE_WLAN_TDLS
10600 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070010601
10602 if (cds_is_sub_20_mhz_enabled()) {
10603 hdd_err("TDLS not allowed with sub 20 MHz");
10604 return -EINVAL;
10605 }
10606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010607 StaParams.capability = params->capability;
10608 StaParams.uapsd_queues = params->uapsd_queues;
10609 StaParams.max_sp = params->max_sp;
10610
10611 /* Convert (first channel , number of channels) tuple to
10612 * the total list of channels. This goes with the assumption
10613 * that if the first channel is < 14, then the next channels
10614 * are an incremental of 1 else an incremental of 4 till the number
10615 * of channels.
10616 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010617 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010618 if (0 != params->supported_channels_len) {
10619 int i = 0, j = 0, k = 0, no_of_channels = 0;
10620 int num_unique_channels;
10621 int next;
10622 for (i = 0;
10623 i < params->supported_channels_len
10624 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
10625 int wifi_chan_index;
10626 if (!wlan_hdd_is_duplicate_channel
10627 (StaParams.supported_channels, j,
10628 params->supported_channels[i])) {
10629 StaParams.
10630 supported_channels[j] =
10631 params->
10632 supported_channels[i];
10633 } else {
10634 continue;
10635 }
10636 wifi_chan_index =
10637 ((StaParams.supported_channels[j] <=
10638 HDD_CHANNEL_14) ? 1 : 4);
10639 no_of_channels =
10640 params->supported_channels[i + 1];
10641
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010642 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 -080010643 StaParams.
10644 supported_channels[j],
10645 wifi_chan_index,
10646 no_of_channels);
10647 for (k = 1; k <= no_of_channels &&
10648 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
10649 k++) {
10650 next =
10651 StaParams.
10652 supported_channels[j] +
10653 wifi_chan_index;
10654 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
10655 StaParams.
10656 supported_channels[j
10657 +
10658 1]
10659 = next;
10660 } else {
10661 continue;
10662 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010663 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664 j + 1,
10665 StaParams.
10666 supported_channels[j +
10667 1]);
10668 j += 1;
10669 }
10670 }
10671 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010672 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010673 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010674 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010675 StaParams.
10676 supported_channels[i]);
10677 }
10678 if (MAX_CHANNEL < num_unique_channels)
10679 num_unique_channels = MAX_CHANNEL;
10680 StaParams.supported_channels_len =
10681 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010682 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010683 StaParams.supported_channels_len);
10684 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010685 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010686 params->supported_oper_classes,
10687 params->supported_oper_classes_len);
10688 StaParams.supported_oper_classes_len =
10689 params->supported_oper_classes_len;
10690
10691 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010692 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010693 params->ext_capab,
10694 sizeof(StaParams.extn_capability));
10695
10696 if (NULL != params->ht_capa) {
10697 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010698 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699 sizeof(tSirHTCap));
10700 }
10701
10702 StaParams.supported_rates_len =
10703 params->supported_rates_len;
10704
10705 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
10706 * The supported_rates array , for all the structures propogating till Add Sta
10707 * to the firmware has to be modified , if the supplicant (ieee80211) is
10708 * modified to send more rates.
10709 */
10710
10711 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10712 */
10713 if (StaParams.supported_rates_len >
10714 SIR_MAC_MAX_SUPP_RATES)
10715 StaParams.supported_rates_len =
10716 SIR_MAC_MAX_SUPP_RATES;
10717
10718 if (0 != StaParams.supported_rates_len) {
10719 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010720 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010721 params->supported_rates,
10722 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010723 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010724 StaParams.supported_rates_len);
10725 for (i = 0; i < StaParams.supported_rates_len;
10726 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010727 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010728 StaParams.supported_rates[i]);
10729 }
10730
10731 if (NULL != params->vht_capa) {
10732 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010733 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734 params->vht_capa,
10735 sizeof(tSirVHTCap));
10736 }
10737
10738 if (0 != params->ext_capab_len) {
10739 /*Define A Macro : TODO Sunil */
10740 if ((1 << 4) & StaParams.extn_capability[3]) {
10741 isBufSta = 1;
10742 }
10743 /* TDLS Channel Switching Support */
10744 if ((1 << 6) & StaParams.extn_capability[3]) {
10745 isOffChannelSupported = 1;
10746 }
10747 }
10748
Nitesh Shah99934ac2016-09-05 15:54:08 +053010749 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010750 (params->ht_capa || params->vht_capa ||
10751 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010752 is_qos_wmm_sta = true;
10753
10754 hdd_notice("%s: TDLS Peer is QOS capable"
10755 " is_qos_wmm_sta= %d HTcapPresent = %d",
10756 __func__, is_qos_wmm_sta,
10757 StaParams.htcap_present);
10758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010760 &StaParams,
10761 isBufSta,
10762 isOffChannelSupported,
10763 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010764 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010765 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010766 return -EINVAL;
10767 }
10768
10769 status =
10770 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10771 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010772 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010773 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010774 return -EINVAL;
10775 }
10776 }
10777#endif
10778 }
10779 EXIT();
10780 return ret;
10781}
10782
10783/**
10784 * wlan_hdd_change_station() - cfg80211 change station handler function
10785 * @wiphy: Pointer to the wiphy structure
10786 * @dev: Pointer to the net device.
10787 * @mac: bssid
10788 * @params: Pointer to station parameters
10789 *
10790 * This is the cfg80211 change station handler function which invokes
10791 * the internal function @__wlan_hdd_change_station with
10792 * SSR protection.
10793 *
10794 * Return: 0 for success, error number on failure.
10795 */
10796#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10797static int wlan_hdd_change_station(struct wiphy *wiphy,
10798 struct net_device *dev,
10799 const u8 *mac,
10800 struct station_parameters *params)
10801#else
10802static int wlan_hdd_change_station(struct wiphy *wiphy,
10803 struct net_device *dev,
10804 u8 *mac,
10805 struct station_parameters *params)
10806#endif
10807{
10808 int ret;
10809
10810 cds_ssr_protect(__func__);
10811 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10812 cds_ssr_unprotect(__func__);
10813
10814 return ret;
10815}
10816
10817/*
10818 * FUNCTION: __wlan_hdd_cfg80211_add_key
10819 * This function is used to initialize the key information
10820 */
10821static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10822 struct net_device *ndev,
10823 u8 key_index, bool pairwise,
10824 const u8 *mac_addr,
10825 struct key_params *params)
10826{
10827 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10828 tCsrRoamSetKey setKey;
10829 int status;
10830 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010832 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010833 hdd_context_t *pHddCtx;
10834 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10835
10836 ENTER();
10837
Anurag Chouhan6d760662016-02-20 16:05:43 +053010838 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010839 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 return -EINVAL;
10841 }
10842
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010843 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10844 hdd_err("invalid session id: %d", pAdapter->sessionId);
10845 return -EINVAL;
10846 }
10847
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010848 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10850 pAdapter->sessionId, params->key_len));
10851 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10852 status = wlan_hdd_validate_context(pHddCtx);
10853
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010854 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010857 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010858 hdd_device_mode_to_string(pAdapter->device_mode),
10859 pAdapter->device_mode);
10860
10861 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010862 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010863
10864 return -EINVAL;
10865 }
10866
10867 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010868 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869
10870 return -EINVAL;
10871 }
10872
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010873 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010874
10875 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010876 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877 setKey.keyId = key_index;
10878 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010879 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880
10881 switch (params->cipher) {
10882 case WLAN_CIPHER_SUITE_WEP40:
10883 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10884 break;
10885
10886 case WLAN_CIPHER_SUITE_WEP104:
10887 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10888 break;
10889
10890 case WLAN_CIPHER_SUITE_TKIP:
10891 {
10892 u8 *pKey = &setKey.Key[0];
10893 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10894
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010895 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010896
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010897 /* Supplicant sends the 32bytes key in this order
10898 *
10899 * |--------------|----------|----------|
10900 * | Tk1 |TX-MIC | RX Mic |
10901 * |--------------|----------|----------|
10902 * <---16bytes---><--8bytes--><--8bytes-->
10903 *
10904 * Sme expects the 32 bytes key to be in the below order
10905 *
10906 * |--------------|----------|----------|
10907 * | Tk1 |RX-MIC | TX Mic |
10908 * |--------------|----------|----------|
10909 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 */
10911 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010912 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913
10914 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010915 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916
10917 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010918 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919
10920 break;
10921 }
10922
10923 case WLAN_CIPHER_SUITE_CCMP:
10924 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10925 break;
10926
10927#ifdef FEATURE_WLAN_WAPI
10928 case WLAN_CIPHER_SUITE_SMS4:
10929 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010930 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10932 mac_addr, params->key,
10933 params->key_len);
10934 return 0;
10935 }
10936#endif
10937
10938#ifdef FEATURE_WLAN_ESE
10939 case WLAN_CIPHER_SUITE_KRK:
10940 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10941 break;
10942#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10943 case WLAN_CIPHER_SUITE_BTK:
10944 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10945 break;
10946#endif
10947#endif
10948
10949#ifdef WLAN_FEATURE_11W
10950 case WLAN_CIPHER_SUITE_AES_CMAC:
10951 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10952 break;
10953#endif
10954
10955 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010956 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010957 return -EOPNOTSUPP;
10958 }
10959
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010960 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961
10962 if (!pairwise) {
10963 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010964 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010966 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 } else {
10968 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010969 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010970 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010971 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010972 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010973 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 /* if a key is already installed, block all subsequent ones */
10975 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010976 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010977 return 0;
10978 }
10979
10980 setKey.keyDirection = eSIR_TX_RX;
10981 /*Set the group key */
10982 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10983 pAdapter->sessionId, &setKey, &roamId);
10984
10985 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010986 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987 return -EINVAL;
10988 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010989 /* Save the keys here and call sme_roam_set_key for setting
10990 * the PTK after peer joins the IBSS network
10991 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010992 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 &setKey, sizeof(tCsrRoamSetKey));
10994
10995 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10996 return status;
10997 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010998 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10999 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011000 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11001 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011002 status = wlansap_set_key_sta(
11003 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011004 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011005 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 __LINE__, status);
11007 }
11008 }
11009
11010 /* Save the key in ap ctx for use on START_BASS and restart */
11011 if (pairwise ||
11012 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11013 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011014 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 sizeof(tCsrRoamSetKey));
11016 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011017 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011018 sizeof(tCsrRoamSetKey));
11019
Krunal Sonib4326f22016-03-10 13:05:51 -080011020 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11021 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011022 hdd_wext_state_t *pWextState =
11023 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11024 hdd_station_ctx_t *pHddStaCtx =
11025 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11026
11027 if (!pairwise) {
11028 /* set group key */
11029 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011030 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011031 __func__, __LINE__);
11032 hdd_perform_roam_set_key_complete(pAdapter);
11033 }
11034 }
11035
11036 pWextState->roamProfile.Keys.KeyLength[key_index] =
11037 (u8) params->key_len;
11038
11039 pWextState->roamProfile.Keys.defaultIndex = key_index;
11040
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011041 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011042 KeyMaterial[key_index][0], params->key,
11043 params->key_len);
11044
11045 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11046
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011047 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011048 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11049 setKey.keyDirection);
11050
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011051 /* The supplicant may attempt to set the PTK once
11052 * pre-authentication is done. Save the key in the
11053 * UMAC and include it in the ADD BSS request
11054 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011055 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011057 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011058 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011060 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011061 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011062 return -EINVAL;
11063 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011064
11065 /* issue set key request to SME */
11066 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11067 pAdapter->sessionId, &setKey, &roamId);
11068
11069 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011070 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011071 pHddStaCtx->roam_info.roamingState =
11072 HDD_ROAM_STATE_NONE;
11073 return -EINVAL;
11074 }
11075
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011076 /* in case of IBSS as there was no information
11077 * available about WEP keys during IBSS join, group
11078 * key intialized with NULL key, so re-initialize
11079 * group key with correct value
11080 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011081 if ((eCSR_BSS_TYPE_START_IBSS ==
11082 pWextState->roamProfile.BSSType)
11083 &&
11084 !((IW_AUTH_KEY_MGMT_802_1X ==
11085 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11086 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11087 pHddStaCtx->conn_info.authType)
11088 )
11089 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11090 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11091 )
11092 ) {
11093 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011094 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011096 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011097 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11098 setKey.keyDirection);
11099
11100 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11101 pAdapter->sessionId, &setKey,
11102 &roamId);
11103
11104 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011105 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011106 pHddStaCtx->roam_info.roamingState =
11107 HDD_ROAM_STATE_NONE;
11108 return -EINVAL;
11109 }
11110 }
11111 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011112 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011113 return 0;
11114}
11115
11116static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11117 struct net_device *ndev,
11118 u8 key_index, bool pairwise,
11119 const u8 *mac_addr,
11120 struct key_params *params)
11121{
11122 int ret;
11123 cds_ssr_protect(__func__);
11124 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11125 mac_addr, params);
11126 cds_ssr_unprotect(__func__);
11127
11128 return ret;
11129}
11130
11131/*
11132 * FUNCTION: __wlan_hdd_cfg80211_get_key
11133 * This function is used to get the key information
11134 */
11135static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11136 struct net_device *ndev,
11137 u8 key_index, bool pairwise,
11138 const u8 *mac_addr, void *cookie,
11139 void (*callback)(void *cookie,
11140 struct key_params *)
11141 )
11142{
11143 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11144 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11145 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11146 struct key_params params;
11147
11148 ENTER();
11149
Anurag Chouhan6d760662016-02-20 16:05:43 +053011150 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011151 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152 return -EINVAL;
11153 }
11154
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011155 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156 hdd_device_mode_to_string(pAdapter->device_mode),
11157 pAdapter->device_mode);
11158
11159 memset(&params, 0, sizeof(params));
11160
11161 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011162 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011163 key_index);
11164 return -EINVAL;
11165 }
11166
11167 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11168 case eCSR_ENCRYPT_TYPE_NONE:
11169 params.cipher = IW_AUTH_CIPHER_NONE;
11170 break;
11171
11172 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11173 case eCSR_ENCRYPT_TYPE_WEP40:
11174 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11175 break;
11176
11177 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11178 case eCSR_ENCRYPT_TYPE_WEP104:
11179 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11180 break;
11181
11182 case eCSR_ENCRYPT_TYPE_TKIP:
11183 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11184 break;
11185
11186 case eCSR_ENCRYPT_TYPE_AES:
11187 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11188 break;
11189
11190 default:
11191 params.cipher = IW_AUTH_CIPHER_NONE;
11192 break;
11193 }
11194
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011195 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 TRACE_CODE_HDD_CFG80211_GET_KEY,
11197 pAdapter->sessionId, params.cipher));
11198
11199 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11200 params.seq_len = 0;
11201 params.seq = NULL;
11202 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11203 callback(cookie, &params);
11204
11205 EXIT();
11206 return 0;
11207}
11208
11209static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11210 struct net_device *ndev,
11211 u8 key_index, bool pairwise,
11212 const u8 *mac_addr, void *cookie,
11213 void (*callback)(void *cookie,
11214 struct key_params *)
11215 )
11216{
11217 int ret;
11218
11219 cds_ssr_protect(__func__);
11220 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11221 mac_addr, cookie, callback);
11222 cds_ssr_unprotect(__func__);
11223
11224 return ret;
11225}
11226
11227/**
11228 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11229 * @wiphy: wiphy interface context
11230 * @ndev: pointer to net device
11231 * @key_index: Key index used in 802.11 frames
11232 * @unicast: true if it is unicast key
11233 * @multicast: true if it is multicast key
11234 *
11235 * This function is required for cfg80211_ops API.
11236 * It is used to delete the key information
11237 * Underlying hardware implementation does not have API to delete the
11238 * encryption key. It is automatically deleted when the peer is
11239 * removed. Hence this function currently does nothing.
11240 * Future implementation may interprete delete key operation to
11241 * replacing the key with a random junk value, effectively making it
11242 * useless.
11243 *
11244 * Return: status code, always 0.
11245 */
11246
11247static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11248 struct net_device *ndev,
11249 u8 key_index,
11250 bool pairwise, const u8 *mac_addr)
11251{
11252 EXIT();
11253 return 0;
11254}
11255
11256/**
11257 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11258 * @wiphy: Pointer to wiphy structure.
11259 * @dev: Pointer to net_device structure.
11260 * @key_index: key index
11261 * @pairwise: pairwise
11262 * @mac_addr: mac address
11263 *
11264 * This is the cfg80211 delete key handler function which invokes
11265 * the internal function @__wlan_hdd_cfg80211_del_key with
11266 * SSR protection.
11267 *
11268 * Return: 0 for success, error number on failure.
11269 */
11270static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11271 struct net_device *dev,
11272 u8 key_index,
11273 bool pairwise, const u8 *mac_addr)
11274{
11275 int ret;
11276
11277 cds_ssr_protect(__func__);
11278 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11279 pairwise, mac_addr);
11280 cds_ssr_unprotect(__func__);
11281
11282 return ret;
11283}
11284
11285/*
11286 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11287 * This function is used to set the default tx key index
11288 */
11289static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11290 struct net_device *ndev,
11291 u8 key_index,
11292 bool unicast, bool multicast)
11293{
11294 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11295 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11296 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11297 hdd_context_t *pHddCtx;
11298 int status;
11299
11300 ENTER();
11301
Anurag Chouhan6d760662016-02-20 16:05:43 +053011302 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011303 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304 return -EINVAL;
11305 }
11306
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011307 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11308 hdd_err("invalid session id: %d", pAdapter->sessionId);
11309 return -EINVAL;
11310 }
11311
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011312 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011313 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
11314 pAdapter->sessionId, key_index));
11315
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011316 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 hdd_device_mode_to_string(pAdapter->device_mode),
11318 pAdapter->device_mode, key_index);
11319
11320 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011321 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011322 return -EINVAL;
11323 }
11324
11325 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11326 status = wlan_hdd_validate_context(pHddCtx);
11327
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011328 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011330
Krunal Sonib4326f22016-03-10 13:05:51 -080011331 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11332 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11334 pHddStaCtx->conn_info.ucEncryptionType) &&
11335 (eCSR_ENCRYPT_TYPE_AES !=
11336 pHddStaCtx->conn_info.ucEncryptionType)) {
11337 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011338 * then update the default key index
11339 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011340
11341 tCsrRoamSetKey setKey;
11342 uint32_t roamId = 0xFF;
11343 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
11344
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011345 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346
11347 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011348 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011349 setKey.keyId = key_index;
11350 setKey.keyLength = Keys->KeyLength[key_index];
11351
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011352 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 &Keys->KeyMaterial[key_index][0],
11354 Keys->KeyLength[key_index]);
11355
11356 setKey.keyDirection = eSIR_TX_RX;
11357
Anurag Chouhanc5548422016-02-24 18:33:27 +053011358 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011359 &pHddStaCtx->conn_info.bssId);
11360
11361 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
11362 pWextState->roamProfile.EncryptionType.
11363 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011364 /* In the case of dynamic wep
11365 * supplicant hardcodes DWEP type to
11366 * eCSR_ENCRYPT_TYPE_WEP104 even
11367 * though ap is configured for WEP-40
11368 * encryption. In this canse the key
11369 * length is 5 but the encryption type
11370 * is 104 hence checking the key
11371 * lenght(5) and encryption type(104)
11372 * and switching encryption type to 40
11373 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011374 pWextState->roamProfile.EncryptionType.
11375 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11376 pWextState->roamProfile.mcEncryptionType.
11377 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11378 }
11379
11380 setKey.encType =
11381 pWextState->roamProfile.EncryptionType.
11382 encryptionType[0];
11383
11384 /* Issue set key request */
11385 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11386 pAdapter->sessionId, &setKey,
11387 &roamId);
11388
11389 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011390 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 status);
11392 return -EINVAL;
11393 }
11394 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011395 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 /* In SoftAp mode setting key direction for default mode */
11397 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11398 pWextState->roamProfile.EncryptionType.encryptionType[0])
11399 && (eCSR_ENCRYPT_TYPE_AES !=
11400 pWextState->roamProfile.EncryptionType.
11401 encryptionType[0])) {
11402 /* Saving key direction for default key index to TX default */
11403 hdd_ap_ctx_t *pAPCtx =
11404 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11405 pAPCtx->wepKey[key_index].keyDirection =
11406 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011407 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053011408 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011409 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011410 }
11411 }
11412
11413 EXIT();
11414 return status;
11415}
11416
11417static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11418 struct net_device *ndev,
11419 u8 key_index,
11420 bool unicast, bool multicast)
11421{
11422 int ret;
11423 cds_ssr_protect(__func__);
11424 ret =
11425 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
11426 multicast);
11427 cds_ssr_unprotect(__func__);
11428
11429 return ret;
11430}
11431
Abhishek Singhc9941602016-08-09 16:06:22 +053011432/*
Abhishek Singhc9941602016-08-09 16:06:22 +053011433 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
11434 * interface that BSS might have been lost.
11435 * @pAdapter: adaptor
11436 * @bssid: bssid which might have been lost
11437 *
11438 * Return: bss which is unlinked from kernel cache
11439 */
11440struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
11441 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442{
11443 struct net_device *dev = pAdapter->dev;
11444 struct wireless_dev *wdev = dev->ieee80211_ptr;
11445 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 struct cfg80211_bss *bss = NULL;
11447
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053011448 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053011449 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011450 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011451 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053011453 hdd_info("cfg80211_unlink_bss called for BSSID "
11454 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455 cfg80211_unlink_bss(wiphy, bss);
11456 }
11457 return bss;
11458}
11459
Abhishek Singhc9941602016-08-09 16:06:22 +053011460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461/**
11462 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
11463 * @pAdapter: Pointer to adapter
11464 * @bss_desc: Pointer to bss descriptor
11465 *
11466 * This function is used to inform the BSS details to nl80211 interface.
11467 *
11468 * Return: struct cfg80211_bss pointer
11469 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053011470struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
11471 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472{
11473 /*
11474 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
11475 * already exists in bss data base of cfg80211 for that particular BSS
11476 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
11477 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
11478 * As of now there is no possibility to get the mgmt(probe response)
11479 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
11480 * and passing to cfg80211_inform_bss_frame.
11481 */
11482 struct net_device *dev = pAdapter->dev;
11483 struct wireless_dev *wdev = dev->ieee80211_ptr;
11484 struct wiphy *wiphy = wdev->wiphy;
11485 int chan_no = bss_desc->channelId;
11486#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11487 qcom_ie_age *qie_age = NULL;
11488 int ie_length =
11489 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
11490#else
11491 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
11492#endif
11493 const char *ie =
11494 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
11495 unsigned int freq;
11496 struct ieee80211_channel *chan;
11497 struct ieee80211_mgmt *mgmt = NULL;
11498 struct cfg80211_bss *bss_status = NULL;
11499 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
11500 int rssi = 0;
11501 hdd_context_t *pHddCtx;
11502 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011503 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011504 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011505
11506 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11507 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011508 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011510
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011511 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011512 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011514 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011515 return NULL;
11516 }
11517
11518 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
11519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011521 * Instead it wants a monotonic increasing value
11522 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070011523 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011524 mgmt->u.probe_resp.timestamp =
11525 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526
11527 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
11528 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
11529
11530#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11531 /* GPS Requirement: need age ie per entry. Using vendor specific. */
11532 /* Assuming this is the last IE, copy at the end */
11533 ie_length -= sizeof(qcom_ie_age);
11534 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
11535 qie_age->element_id = QCOM_VENDOR_IE_ID;
11536 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
11537 qie_age->oui_1 = QCOM_OUI1;
11538 qie_age->oui_2 = QCOM_OUI2;
11539 qie_age->oui_3 = QCOM_OUI3;
11540 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053011541 /*
11542 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
11543 * all bss related timestamp is in units of ms. Due to this when scan
11544 * results are sent to lowi the scan age is high.To address this,
11545 * send age in units of 1/10 ms.
11546 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011547 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053011548 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011549 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070011550 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
11551 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070011552 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
11553 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554#endif
11555
11556 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
11557 if (bss_desc->fProbeRsp) {
11558 mgmt->frame_control |=
11559 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
11560 } else {
11561 mgmt->frame_control |=
11562 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
11563 }
11564
11565 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070011566 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 freq =
11568 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011569 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011570 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070011571 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011572 freq =
11573 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011574 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011575 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011576 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011577 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011578 return NULL;
11579 }
11580
11581 chan = __ieee80211_get_channel(wiphy, freq);
11582 /* When the band is changed on the fly using the GUI, three things are done
11583 * 1. scan abort
11584 * 2. flush scan results from cache
11585 * 3. update the band with the new band user specified (refer to the
11586 * hdd_set_band_helper function) as part of the scan abort, message will be
11587 * queued to PE and we proceed with flushing and changinh the band.
11588 * PE will stop the scanning further and report back the results what ever
11589 * it had till now by calling the call back function.
11590 * if the time between update band and scandone call back is sufficient
11591 * enough the band change reflects in SME, SME validates the channels
11592 * and discards the channels correponding to previous band and calls back
11593 * with zero bss results. but if the time between band update and scan done
11594 * callback is very small then band change will not reflect in SME and SME
11595 * reports to HDD all the channels correponding to previous band.this is due
11596 * to race condition.but those channels are invalid to the new band and so
11597 * this function __ieee80211_get_channel will return NULL.Each time we
11598 * report scan result with this pointer null warning kernel trace is printed.
11599 * if the scan results contain large number of APs continuosly kernel
11600 * warning trace is printed and it will lead to apps watch dog bark.
11601 * So drop the bss and continue to next bss.
11602 */
11603 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053011604 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
11605 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011606 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011607 return NULL;
11608 }
11609
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011610 /* Based on .ini configuration, raw rssi can be reported for bss.
11611 * Raw rssi is typically used for estimating power.
11612 */
11613
11614 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
11615 bss_desc->rssi;
11616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011617 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053011618 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011619
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053011620 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011621 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070011622 (int)(rssi / 100),
11623 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011624
11625 bss_status =
11626 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
11627 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053011628 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011629 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011630 return bss_status;
11631}
11632
11633/**
11634 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
11635 * @pAdapter: Pointer to adapter
11636 * @pRoamInfo: Pointer to roam info
11637 *
11638 * This function is used to update the BSS data base of CFG8011
11639 *
11640 * Return: struct cfg80211_bss pointer
11641 */
11642struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
11643 tCsrRoamInfo *pRoamInfo)
11644{
11645 tCsrRoamConnectedProfile roamProfile;
11646 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11647 struct cfg80211_bss *bss = NULL;
11648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
11650 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
11651
11652 if (NULL != roamProfile.pBssDesc) {
11653 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11654 roamProfile.pBssDesc);
11655
11656 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011657 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080011659 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011660 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011661 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011662 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663 return bss;
11664}
11665/**
11666 * wlan_hdd_cfg80211_update_bss() - update bss
11667 * @wiphy: Pointer to wiphy
11668 * @pAdapter: Pointer to adapter
11669 * @scan_time: scan request timestamp
11670 *
11671 * Return: zero if success, non-zero otherwise
11672 */
11673int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
11674 hdd_adapter_t *pAdapter,
11675 uint32_t scan_time)
11676{
11677 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11678 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011679 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680 tScanResultHandle pResult;
11681 struct cfg80211_bss *bss_status = NULL;
11682 hdd_context_t *pHddCtx;
11683 int ret;
11684
11685 ENTER();
11686
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011687 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11688 hdd_err("invalid session id: %d", pAdapter->sessionId);
11689 return -EINVAL;
11690 }
11691
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011692 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11694 NO_SESSION, pAdapter->sessionId));
11695
11696 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11697 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011698 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011700
11701 /* start getting scan results and populate cgf80211 BSS database */
11702 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11703
11704 /* no scan results */
11705 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011706 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011707 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011708 }
11709
11710 pScanResult = sme_scan_result_get_first(hHal, pResult);
11711
11712 while (pScanResult) {
11713 /*
11714 * - cfg80211_inform_bss() is not updating ie field of bss
11715 * entry if entry already exists in bss data base of cfg80211
11716 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11717 * to update thebss entry instead of cfg80211_inform_bss,
11718 * But this call expects mgmt packet as input. As of now
11719 * there is no possibility to get the mgmt(probe response)
11720 * frame from PE, converting bss_desc to
11721 * ieee80211_mgmt(probe response) and passing to c
11722 * fg80211_inform_bss_frame.
11723 * - Update BSS only if beacon timestamp is later than
11724 * scan request timestamp.
11725 */
11726 if ((scan_time == 0) ||
11727 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011728 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729 bss_status =
11730 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11731 &pScanResult->BssDescriptor);
11732
11733 if (NULL == bss_status) {
11734 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11735 } else {
11736 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011737 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011738 bss_status);
11739 }
11740 } else {
11741 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11742 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11743 }
11744 pScanResult = sme_scan_result_get_next(hHal, pResult);
11745 }
11746
11747 sme_scan_result_purge(hHal, pResult);
11748 /*
11749 * For SAP mode, scan is invoked by hostapd during SAP start
11750 * if hostapd is restarted, we need to flush previous scan
11751 * result so that it will reflect environment change
11752 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011753 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11755 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11756#endif
11757 )
11758 sme_scan_flush_result(hHal);
11759
11760 EXIT();
11761 return 0;
11762}
11763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011764/**
11765 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11766 * @pAdapter: Pointer to adapter
11767 * @pRoamInfo: Pointer to roam info
11768 * @index: Index
11769 * @preauth: Preauth flag
11770 *
11771 * This function is used to notify the supplicant of a new PMKSA candidate.
11772 *
11773 * Return: 0 for success, non-zero for failure
11774 */
11775int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11776 tCsrRoamInfo *pRoamInfo,
11777 int index, bool preauth)
11778{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011779 struct net_device *dev = pAdapter->dev;
11780 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11781
11782 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011783 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784
11785 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011786 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011787 return -EINVAL;
11788 }
11789
11790 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011791 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011792 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11793 cfg80211_pmksa_candidate_notify(dev, index,
11794 pRoamInfo->bssid.bytes,
11795 preauth, GFP_KERNEL);
11796 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797 return 0;
11798}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011799
11800#ifdef FEATURE_WLAN_LFR_METRICS
11801/**
11802 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11803 * @pAdapter: Pointer to adapter
11804 * @pRoamInfo: Pointer to roam info
11805 *
11806 * 802.11r/LFR metrics reporting function to report preauth initiation
11807 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011808 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 */
11810#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011811QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011812 tCsrRoamInfo *pRoamInfo)
11813{
11814 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11815 union iwreq_data wrqu;
11816
11817 ENTER();
11818
11819 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011820 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011821 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011822 }
11823
11824 /* create the event */
11825 memset(&wrqu, 0, sizeof(wrqu));
11826 memset(metrics_notification, 0, sizeof(metrics_notification));
11827
11828 wrqu.data.pointer = metrics_notification;
11829 wrqu.data.length = scnprintf(metrics_notification,
11830 sizeof(metrics_notification),
11831 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11832 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11833
11834 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11835 metrics_notification);
11836
11837 EXIT();
11838
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011839 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840}
11841
11842/**
11843 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11844 * @pAdapter: Pointer to adapter
11845 * @pRoamInfo: Pointer to roam info
11846 * @preauth_status: Preauth status
11847 *
11848 * 802.11r/LFR metrics reporting function to report handover initiation
11849 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011850 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011851 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011852QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11854 tCsrRoamInfo *pRoamInfo,
11855 bool preauth_status)
11856{
11857 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11858 union iwreq_data wrqu;
11859
11860 ENTER();
11861
11862 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011863 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011864 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865 }
11866
11867 /* create the event */
11868 memset(&wrqu, 0, sizeof(wrqu));
11869 memset(metrics_notification, 0, sizeof(metrics_notification));
11870
11871 scnprintf(metrics_notification, sizeof(metrics_notification),
11872 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11873 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11874
11875 if (1 == preauth_status)
11876 strlcat(metrics_notification, " true",
11877 sizeof(metrics_notification));
11878 else
11879 strlcat(metrics_notification, " false",
11880 sizeof(metrics_notification));
11881
11882 wrqu.data.pointer = metrics_notification;
11883 wrqu.data.length = strlen(metrics_notification);
11884
11885 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11886 metrics_notification);
11887
11888 EXIT();
11889
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011890 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011891}
11892
11893/**
11894 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11895 * @pAdapter: Pointer to adapter
11896 * @pRoamInfo: Pointer to roam info
11897 *
11898 * 802.11r/LFR metrics reporting function to report handover initiation
11899 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011900 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011901 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011902QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011903 tCsrRoamInfo *pRoamInfo)
11904{
11905 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11906 union iwreq_data wrqu;
11907
11908 ENTER();
11909
11910 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011911 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011912 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011913 }
11914
11915 /* create the event */
11916 memset(&wrqu, 0, sizeof(wrqu));
11917 memset(metrics_notification, 0, sizeof(metrics_notification));
11918
11919 wrqu.data.pointer = metrics_notification;
11920 wrqu.data.length = scnprintf(metrics_notification,
11921 sizeof(metrics_notification),
11922 "QCOM: LFR_PREAUTH_HANDOVER "
11923 MAC_ADDRESS_STR,
11924 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11925
11926 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11927 metrics_notification);
11928
11929 EXIT();
11930
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011931 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011932}
11933#endif
11934
11935/**
11936 * hdd_select_cbmode() - select channel bonding mode
11937 * @pAdapter: Pointer to adapter
11938 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011939 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011940 *
11941 * Return: none
11942 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011943void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11944 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011945{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011946 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011947 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011948 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011949
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011950 /*
11951 * CDS api expects secondary channel for calculating
11952 * the channel params
11953 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011954 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011955 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11956 if (operationChannel >= 1 && operationChannel <= 5)
11957 sec_ch = operationChannel + 4;
11958 else if (operationChannel >= 6 && operationChannel <= 13)
11959 sec_ch = operationChannel - 4;
11960 }
11961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011962 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011963 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011964
11965 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011966 eHddDot11Mode hdd_dot11_mode;
11967 uint8_t iniDot11Mode =
11968 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11969
11970 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11971 switch (iniDot11Mode) {
11972 case eHDD_DOT11_MODE_AUTO:
11973 case eHDD_DOT11_MODE_11ac:
11974 case eHDD_DOT11_MODE_11ac_ONLY:
11975 if (sme_is_feature_supported_by_fw(DOT11AC))
11976 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11977 else
11978 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11979 break;
11980 case eHDD_DOT11_MODE_11n:
11981 case eHDD_DOT11_MODE_11n_ONLY:
11982 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11983 break;
11984 default:
11985 hdd_dot11_mode = iniDot11Mode;
11986 break;
11987 }
11988 ch_info->channel_width = ch_params->ch_width;
11989 ch_info->phy_mode =
11990 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011991 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011992 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011993 hdd_info("ch_info width %d, phymode %d channel %d",
11994 ch_info->channel_width, ch_info->phy_mode,
11995 ch_info->channel);
11996 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997}
11998
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011999/**
12000 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12001 * @adapter: STA adapter
12002 * @roam_profile: STA roam profile
12003 *
12004 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12005 *
12006 * Return: false if sta-sap conc is not allowed, else return true
12007 */
12008static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12009 tCsrRoamProfile *roam_profile)
12010{
12011 hdd_context_t *hdd_ctx;
12012 hdd_adapter_t *ap_adapter;
12013 hdd_ap_ctx_t *hdd_ap_ctx;
12014 hdd_hostapd_state_t *hostapd_state;
12015 uint8_t channel = 0;
12016 QDF_STATUS status;
12017
12018 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12019 if (!hdd_ctx) {
12020 hdd_err("HDD context is NULL");
12021 return true;
12022 }
12023
12024 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12025 /* probably no sap running, no handling required */
12026 if (ap_adapter == NULL)
12027 return true;
12028
12029 /*
12030 * sap is not in started state, so it is fine to go ahead with sta.
12031 * if sap is currently doing CAC then don't allow sta to go further.
12032 */
12033 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12034 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12035 return true;
12036
12037 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12038 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12039 return false;
12040 }
12041
12042 /*
12043 * log and return error, if we allow STA to go through, we don't
12044 * know what is going to happen better stop sta connection
12045 */
12046 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12047 if (NULL == hdd_ap_ctx) {
12048 hdd_err("AP context not found");
12049 return false;
12050 }
12051
12052 /* sap is on non-dfs channel, nothing to handle */
12053 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12054 hdd_info("sap is on non-dfs channel, sta is allowed");
12055 return true;
12056 }
12057 /*
12058 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012059 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012060 */
12061 status = cds_get_channel_from_scan_result(adapter,
12062 roam_profile, &channel);
12063
Nitesh Shah59774522016-09-16 15:14:21 +053012064 /*
12065 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12066 * channels for roaming case.
12067 */
12068 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12069 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12070 return true;
12071 }
12072
12073 /*
12074 * If channel is 0 or DFS then better to call pcl and find out the
12075 * best channel. If channel is non-dfs 5 GHz then better move SAP
12076 * to STA's channel to make scc, so we have room for 3port MCC
12077 * scenario.
12078 */
12079 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012080 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12081 true);
12082
12083 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12084 qdf_event_reset(&hostapd_state->qdf_event);
12085 status = wlansap_set_channel_change_with_csa(
12086 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12087 hdd_ap_ctx->sapConfig.ch_width_orig);
12088
12089 if (QDF_STATUS_SUCCESS != status) {
12090 hdd_err("Set channel with CSA IE failed, can't allow STA");
12091 return false;
12092 }
12093
12094 /*
12095 * wait here for SAP to finish the channel switch. When channel
12096 * switch happens, SAP sends few beacons with CSA_IE. After
12097 * successfully Transmission of those beacons, it will move its
12098 * state from started to disconnected and move to new channel.
12099 * once it moves to new channel, sap again moves its state
12100 * machine from disconnected to started and set this event.
12101 * wait for 10 secs to finish this.
12102 */
12103 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12104 if (!QDF_IS_STATUS_SUCCESS(status)) {
12105 hdd_err("wait for qdf_event failed, STA not allowed!!");
12106 return false;
12107 }
12108
12109 return true;
12110}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012111
Krunal Soni31949422016-07-29 17:17:53 -070012112/**
12113 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012114 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012115 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012116 * @ssid_len: Length of ssid
12117 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012118 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012119 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012120 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121 *
12122 * This function is used to start the association process
12123 *
12124 * Return: 0 for success, non-zero for failure
12125 */
Krunal Soni31949422016-07-29 17:17:53 -070012126static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012128 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012129 u8 operatingChannel,
12130 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131{
12132 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012133 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012134 hdd_wext_state_t *pWextState;
12135 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012136 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 uint32_t roamId;
12138 tCsrRoamProfile *pRoamProfile;
12139 eCsrAuthType RSNAuthType;
12140 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012141 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012142
12143 ENTER();
12144
12145 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12146 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012147 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012148
12149 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012150 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012151 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152
12153 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012154 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 return -EINVAL;
12156 }
12157
12158 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012159 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12160 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012161
12162 if (pRoamProfile) {
12163 hdd_station_ctx_t *pHddStaCtx;
12164 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12165
12166 if (HDD_WMM_USER_MODE_NO_QOS ==
12167 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12168 /*QoS not enabled in cfg file */
12169 pRoamProfile->uapsd_mask = 0;
12170 } else {
12171 /*QoS enabled, update uapsd mask from cfg file */
12172 pRoamProfile->uapsd_mask =
12173 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12174 }
12175
12176 pRoamProfile->SSIDs.numOfSSIDs = 1;
12177 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012178 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012179 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012180 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181 ssid, ssid_len);
12182
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012183 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012184 /* cleanup bssid hint */
12185 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12186 QDF_MAC_ADDR_SIZE);
12187 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12188 QDF_MAC_ADDR_SIZE);
12189
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012190 if (bssid) {
12191 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012192 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012193 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012194 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012195 /*
12196 * Save BSSID in seperate variable as
12197 * pRoamProfile's BSSID is getting zeroed out in the
12198 * association process. In case of join failure
12199 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012200 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012201 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012202 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012203 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012204 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012205 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12206 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012207 /*
12208 * Save BSSID in a separate variable as
12209 * pRoamProfile's BSSID is getting zeroed out in the
12210 * association process. In case of join failure
12211 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012212 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012213 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012214 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012215 hdd_info("bssid_hint is given by upper layer %pM",
12216 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012217 }
12218
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012219 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 pRoamProfile->SSIDs.SSIDList->SSID.length,
12221 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12222 operatingChannel);
12223
12224 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12225 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012226 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012227 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12228 }
12229#ifdef FEATURE_WLAN_WAPI
12230 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012231 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012232 switch (pAdapter->wapi_info.wapiAuthMode) {
12233 case WAPI_AUTH_MODE_PSK:
12234 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012235 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012236 pAdapter->wapi_info.wapiAuthMode);
12237 pRoamProfile->AuthType.authType[0] =
12238 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12239 break;
12240 }
12241 case WAPI_AUTH_MODE_CERT:
12242 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012243 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012244 pAdapter->wapi_info.wapiAuthMode);
12245 pRoamProfile->AuthType.authType[0] =
12246 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12247 break;
12248 }
12249 } /* End of switch */
12250 if (pAdapter->wapi_info.wapiAuthMode ==
12251 WAPI_AUTH_MODE_PSK
12252 || pAdapter->wapi_info.wapiAuthMode ==
12253 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012254 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012255 pRoamProfile->AuthType.numEntries = 1;
12256 pRoamProfile->EncryptionType.numEntries = 1;
12257 pRoamProfile->EncryptionType.encryptionType[0] =
12258 eCSR_ENCRYPT_TYPE_WPI;
12259 pRoamProfile->mcEncryptionType.numEntries = 1;
12260 pRoamProfile->mcEncryptionType.
12261 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12262 }
12263 }
Krunal Soni31949422016-07-29 17:17:53 -070012264#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012265#ifdef WLAN_FEATURE_GTK_OFFLOAD
12266 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080012267 if ((QDF_STA_MODE == pAdapter->device_mode) ||
12268 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012269 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
12270 sizeof(tSirGtkOffloadParams));
12271 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12272 GTK_OFFLOAD_DISABLE;
12273 }
12274#endif
12275 pRoamProfile->csrPersona = pAdapter->device_mode;
12276
12277 if (operatingChannel) {
12278 pRoamProfile->ChannelInfo.ChannelList =
12279 &operatingChannel;
12280 pRoamProfile->ChannelInfo.numOfChannels = 1;
12281 } else {
12282 pRoamProfile->ChannelInfo.ChannelList = NULL;
12283 pRoamProfile->ChannelInfo.numOfChannels = 0;
12284 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012285 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012286 && operatingChannel) {
12287 /*
12288 * Need to post the IBSS power save parameters
12289 * to WMA. WMA will configure this parameters
12290 * to firmware if power save is enabled by the
12291 * firmware.
12292 */
12293 status = hdd_set_ibss_power_save_params(pAdapter);
12294
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012295 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012296 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 return -EINVAL;
12298 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012299 pRoamProfile->ch_params.ch_width =
12300 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053012301 /*
12302 * In IBSS mode while operating in 2.4 GHz,
12303 * the device supports only 20 MHz.
12304 */
12305 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
12306 pRoamProfile->ch_params.ch_width =
12307 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012308 hdd_select_cbmode(pAdapter, operatingChannel,
12309 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310 }
Abhishek Singh99bce862016-06-20 15:10:51 +053012311 /*
12312 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12313 * or pmf=2 is an explicit configuration in the supplicant
12314 * configuration, drop the connection request.
12315 */
12316 if (pWextState->roamProfile.MFPEnabled &&
12317 !(pWextState->roamProfile.MFPRequired ||
12318 pWextState->roamProfile.MFPCapable)) {
12319 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12320 pWextState->roamProfile.MFPEnabled,
12321 pWextState->roamProfile.MFPRequired,
12322 pWextState->roamProfile.MFPCapable);
12323 return -EINVAL;
12324 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012325
Krunal Soni3091bcc2016-06-23 12:28:21 -070012326 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327 hdd_err("Connection refused: conn in progress");
12328 return -EINVAL;
12329 }
12330
Krunal Soni31949422016-07-29 17:17:53 -070012331 /*
12332 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070012334 * enhancements, the supplicant is not issuing the scan command
12335 * now. So the unicast frames which are sent from the host are
12336 * not having the additional IEs. If it is P2P CLIENT and there
12337 * is no additional IE present in roamProfile, then use the
12338 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 */
12340
Krunal Sonib4326f22016-03-10 13:05:51 -080012341 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012342 (!pRoamProfile->pAddIEScan)) {
12343 pRoamProfile->pAddIEScan =
12344 &pAdapter->scan_info.scanAddIE.addIEdata[0];
12345 pRoamProfile->nAddIEScanLength =
12346 pAdapter->scan_info.scanAddIE.length;
12347 }
12348 /*
12349 * When policy manager is enabled from ini file, we shouldn't
12350 * check for other concurrency rules.
12351 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070012352 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080012353 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012354 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012355 pAdapter, pRoamProfile, &roamId))
12356 return 0;
12357 }
12358
Krunal Soni3091bcc2016-06-23 12:28:21 -070012359 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012360 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
12361 pRoamProfile))) {
12362 hdd_err("sap-sta conc will fail, can't allow sta");
12363 hdd_conn_set_connection_state(pAdapter,
12364 eConnectionState_NotConnected);
12365 return -ENOMEM;
12366 }
12367
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012368 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012369 if (!sme_config) {
12370 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012371 hdd_conn_set_connection_state(pAdapter,
12372 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373 return -ENOMEM;
12374 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012375 sme_get_config_param(pHddCtx->hHal, sme_config);
12376 /* These values are not sessionized. So, any change in these SME
12377 * configs on an older or parallel interface will affect the
12378 * cb mode. So, restoring the default INI params before starting
12379 * interfaces such as sta, cli etc.,
12380 */
12381 sme_config->csrConfig.channelBondingMode5GHz =
12382 pHddCtx->config->nChannelBondingMode5GHz;
12383 sme_config->csrConfig.channelBondingMode24GHz =
12384 pHddCtx->config->nChannelBondingMode24GHz;
12385 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012386 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053012387 /*
12388 * Change conn_state to connecting before sme_roam_connect(),
12389 * because sme_roam_connect() has a direct path to call
12390 * hdd_sme_roam_callback(), which will change the conn_state
12391 * If direct path, conn_state will be accordingly changed to
12392 * NotConnected or Associated by either
12393 * hdd_association_completion_handler() or
12394 * hdd_dis_connect_handler() in sme_RoamCallback()if
12395 * sme_RomConnect is to be queued,
12396 * Connecting state will remain until it is completed.
12397 *
12398 * If connection state is not changed, connection state will
12399 * remain in eConnectionState_NotConnected state.
12400 * In hdd_association_completion_handler, "hddDisconInProgress"
12401 * is set to true if conn state is
12402 * eConnectionState_NotConnected.
12403 * If "hddDisconInProgress" is set to true then cfg80211 layer
12404 * is not informed of connect result indication which
12405 * is an issue.
12406 */
12407 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053012408 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053012409 hdd_conn_set_connection_state(pAdapter,
12410 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012411
Komal Seelama89be8d2016-09-29 11:09:26 +053012412 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
12413 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080012414 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012415 pAdapter->sessionId, pRoamProfile,
12416 &roamId);
12417
Rajeev Kumard31e1542017-01-13 14:37:42 -080012418 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080012419 (QDF_STA_MODE == pAdapter->device_mode ||
12420 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012421 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080012422 "qdf_status %d. -> NotConnected",
12423 pAdapter->sessionId, qdf_status);
12424 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425 /* change back to NotAssociated */
12426 hdd_conn_set_connection_state(pAdapter,
12427 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053012428 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
12429 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012430 }
12431
12432 pRoamProfile->ChannelInfo.ChannelList = NULL;
12433 pRoamProfile->ChannelInfo.numOfChannels = 0;
12434
Nitesh Shah044fd672016-10-13 18:53:25 +053012435 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080012436 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053012437 cds_get_channel_from_scan_result(pAdapter,
12438 pRoamProfile, &channel);
12439 if (channel)
12440 cds_checkn_update_hw_mode_single_mac_mode
12441 (channel);
12442 }
12443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012445 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012446 return -EINVAL;
12447 }
12448 EXIT();
12449 return status;
12450}
12451
12452/**
12453 * wlan_hdd_cfg80211_set_auth_type() - set auth type
12454 * @pAdapter: Pointer to adapter
12455 * @auth_type: Auth type
12456 *
12457 * This function is used to set the authentication type (OPEN/SHARED).
12458 *
12459 * Return: 0 for success, non-zero for failure
12460 */
12461static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
12462 enum nl80211_auth_type auth_type)
12463{
12464 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12465 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12466
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012467 /*set authentication type */
12468 switch (auth_type) {
12469 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012470 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
12472 break;
12473
12474 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012476 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12478 break;
12479
12480 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012481 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012482 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
12483 break;
12484#ifdef FEATURE_WLAN_ESE
12485 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012486 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012487 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
12488 break;
12489#endif
12490
12491 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012492 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012493 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
12494 return -EINVAL;
12495 }
12496
12497 pWextState->roamProfile.AuthType.authType[0] =
12498 pHddStaCtx->conn_info.authType;
12499 return 0;
12500}
12501
12502/**
12503 * wlan_hdd_set_akm_suite() - set key management type
12504 * @pAdapter: Pointer to adapter
12505 * @key_mgmt: Key management type
12506 *
12507 * This function is used to set the key mgmt type(PSK/8021x).
12508 *
12509 * Return: 0 for success, non-zero for failure
12510 */
12511static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
12512{
12513 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12514
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012515#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
12516#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
12517 /*set key mgmt type */
12518 switch (key_mgmt) {
12519 case WLAN_AKM_SUITE_PSK:
12520 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012521 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012522 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012523 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
12524 break;
12525
12526 case WLAN_AKM_SUITE_8021X_SHA256:
12527 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012529 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12531 break;
12532#ifdef FEATURE_WLAN_ESE
12533#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
12534#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
12535 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012536 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012537 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
12538 break;
12539#endif
12540#ifndef WLAN_AKM_SUITE_OSEN
12541#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
12542#endif
12543 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012544 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12546 break;
12547
12548 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012549 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550 return -EINVAL;
12551
12552 }
12553 return 0;
12554}
12555
12556/**
12557 * wlan_hdd_cfg80211_set_cipher() - set encryption type
12558 * @pAdapter: Pointer to adapter
12559 * @cipher: Cipher type
12560 * @ucast: Unicast flag
12561 *
12562 * This function is used to set the encryption type
12563 * (NONE/WEP40/WEP104/TKIP/CCMP).
12564 *
12565 * Return: 0 for success, non-zero for failure
12566 */
12567static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
12568 u32 cipher, bool ucast)
12569{
12570 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12571 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12572 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012575 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012576 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12577 } else {
12578
12579 /*set encryption method */
12580 switch (cipher) {
12581 case IW_AUTH_CIPHER_NONE:
12582 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12583 break;
12584
12585 case WLAN_CIPHER_SUITE_WEP40:
12586 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
12587 break;
12588
12589 case WLAN_CIPHER_SUITE_WEP104:
12590 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
12591 break;
12592
12593 case WLAN_CIPHER_SUITE_TKIP:
12594 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
12595 break;
12596
12597 case WLAN_CIPHER_SUITE_CCMP:
12598 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12599 break;
12600#ifdef FEATURE_WLAN_WAPI
12601 case WLAN_CIPHER_SUITE_SMS4:
12602 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
12603 break;
12604#endif
12605
12606#ifdef FEATURE_WLAN_ESE
12607 case WLAN_CIPHER_SUITE_KRK:
12608 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
12609 break;
12610#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12611 case WLAN_CIPHER_SUITE_BTK:
12612 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
12613 break;
12614#endif
12615#endif
12616 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012617 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 return -EOPNOTSUPP;
12619 }
12620 }
12621
12622 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012623 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12625 pWextState->roamProfile.EncryptionType.numEntries = 1;
12626 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12627 encryptionType;
12628 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012629 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012630 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
12631 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
12632 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
12633 encryptionType;
12634 }
12635
12636 return 0;
12637}
12638
12639/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012640 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
12641 * @wext_state: Pointer to wext state
12642 * @gen_ie: Pointer to IE data
12643 * @len: length of IE data
12644 *
12645 * Return: 0 for success, non-zero for failure
12646 */
12647static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
12648 const uint8_t *gen_ie, uint16_t len)
12649{
12650 uint16_t cur_add_ie_len =
12651 wext_state->assocAddIE.length;
12652
12653 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12654 (wext_state->assocAddIE.length + len)) {
12655 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12656 QDF_ASSERT(0);
12657 return -ENOMEM;
12658 }
12659 memcpy(wext_state->assocAddIE.addIEdata +
12660 cur_add_ie_len, gen_ie, len);
12661 wext_state->assocAddIE.length += len;
12662
12663 wext_state->roamProfile.pAddIEAssoc =
12664 wext_state->assocAddIE.addIEdata;
12665 wext_state->roamProfile.nAddIEAssocLength =
12666 wext_state->assocAddIE.length;
12667 return 0;
12668}
12669
12670/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671 * wlan_hdd_cfg80211_set_ie() - set IEs
12672 * @pAdapter: Pointer to adapter
12673 * @ie: Pointer ot ie
12674 * @ie: IE length
12675 *
12676 * Return: 0 for success, non-zero for failure
12677 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012678static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 size_t ie_len)
12680{
12681 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12682 const uint8_t *genie = ie;
12683 uint16_t remLen = ie_len;
12684#ifdef FEATURE_WLAN_WAPI
12685 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12686 u16 *tmp;
12687 uint16_t akmsuiteCount;
12688 int *akmlist;
12689#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012690 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012691
12692 /* clear previous assocAddIE */
12693 pWextState->assocAddIE.length = 0;
12694 pWextState->roamProfile.bWPSAssociation = false;
12695 pWextState->roamProfile.bOSENAssociation = false;
12696
12697 while (remLen >= 2) {
12698 uint16_t eLen = 0;
12699 uint8_t elementId;
12700 elementId = *genie++;
12701 eLen = *genie++;
12702 remLen -= 2;
12703
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012704 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012705
12706 switch (elementId) {
12707 case DOT11F_EID_WPA:
12708 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 -070012709 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 return -EINVAL;
12711 } else if (0 ==
12712 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12713 uint16_t curAddIELen =
12714 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012715 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012716
12717 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12718 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012719 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012720 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721 return -ENOMEM;
12722 }
12723 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12724 memcpy(pWextState->assocAddIE.addIEdata +
12725 curAddIELen, genie - 2, eLen + 2);
12726 pWextState->assocAddIE.length += eLen + 2;
12727
12728 pWextState->roamProfile.bWPSAssociation = true;
12729 pWextState->roamProfile.pAddIEAssoc =
12730 pWextState->assocAddIE.addIEdata;
12731 pWextState->roamProfile.nAddIEAssocLength =
12732 pWextState->assocAddIE.length;
12733 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012734 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012735 memset(pWextState->WPARSNIE, 0,
12736 MAX_WPA_RSN_IE_LEN);
12737 memcpy(pWextState->WPARSNIE, genie - 2,
12738 (eLen + 2));
12739 pWextState->roamProfile.pWPAReqIE =
12740 pWextState->WPARSNIE;
12741 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12742 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12743 P2P_OUI_TYPE_SIZE))) {
12744 uint16_t curAddIELen =
12745 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012746 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747
12748 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12749 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012750 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012751 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012752 return -ENOMEM;
12753 }
12754 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12755 memcpy(pWextState->assocAddIE.addIEdata +
12756 curAddIELen, genie - 2, eLen + 2);
12757 pWextState->assocAddIE.length += eLen + 2;
12758
12759 pWextState->roamProfile.pAddIEAssoc =
12760 pWextState->assocAddIE.addIEdata;
12761 pWextState->roamProfile.nAddIEAssocLength =
12762 pWextState->assocAddIE.length;
12763 }
12764#ifdef WLAN_FEATURE_WFD
12765 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12766 WFD_OUI_TYPE_SIZE)) &&
12767 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012768 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769 pAdapter->device_mode)) {
12770 uint16_t curAddIELen =
12771 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012772 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773
12774 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12775 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012776 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012777 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012778 return -ENOMEM;
12779 }
12780 /* WFD IE is saved to Additional IE ; it should
12781 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012782 * WFD IE
12783 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784 memcpy(pWextState->assocAddIE.addIEdata +
12785 curAddIELen, genie - 2, eLen + 2);
12786 pWextState->assocAddIE.length += eLen + 2;
12787
12788 pWextState->roamProfile.pAddIEAssoc =
12789 pWextState->assocAddIE.addIEdata;
12790 pWextState->roamProfile.nAddIEAssocLength =
12791 pWextState->assocAddIE.length;
12792 }
12793#endif
12794 /* Appending HS 2.0 Indication Element in Assiciation Request */
12795 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12796 HS20_OUI_TYPE_SIZE))) {
12797 uint16_t curAddIELen =
12798 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012799 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012800
12801 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12802 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012803 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012804 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012805 return -ENOMEM;
12806 }
12807 memcpy(pWextState->assocAddIE.addIEdata +
12808 curAddIELen, genie - 2, eLen + 2);
12809 pWextState->assocAddIE.length += eLen + 2;
12810
12811 pWextState->roamProfile.pAddIEAssoc =
12812 pWextState->assocAddIE.addIEdata;
12813 pWextState->roamProfile.nAddIEAssocLength =
12814 pWextState->assocAddIE.length;
12815 }
12816 /* Appending OSEN Information Element in Assiciation Request */
12817 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12818 OSEN_OUI_TYPE_SIZE))) {
12819 uint16_t curAddIELen =
12820 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012821 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822
12823 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12824 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012825 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012826 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012827 return -ENOMEM;
12828 }
12829 memcpy(pWextState->assocAddIE.addIEdata +
12830 curAddIELen, genie - 2, eLen + 2);
12831 pWextState->assocAddIE.length += eLen + 2;
12832
12833 pWextState->roamProfile.bOSENAssociation = true;
12834 pWextState->roamProfile.pAddIEAssoc =
12835 pWextState->assocAddIE.addIEdata;
12836 pWextState->roamProfile.nAddIEAssocLength =
12837 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012838 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12839 MBO_OUI_TYPE_SIZE))){
12840 hdd_info("Set MBO IE(len %d)", eLen + 2);
12841 status = wlan_hdd_add_assoc_ie(pWextState,
12842 genie - 2, eLen + 2);
12843 if (status)
12844 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012845 } else {
12846 uint16_t add_ie_len =
12847 pWextState->assocAddIE.length;
12848
12849 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12850
12851 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12852 (pWextState->assocAddIE.length + eLen)) {
12853 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012854 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012855 return -ENOMEM;
12856 }
12857
12858 memcpy(pWextState->assocAddIE.addIEdata +
12859 add_ie_len, genie - 2, eLen + 2);
12860 pWextState->assocAddIE.length += eLen + 2;
12861
12862 pWextState->roamProfile.pAddIEAssoc =
12863 pWextState->assocAddIE.addIEdata;
12864 pWextState->roamProfile.nAddIEAssocLength =
12865 pWextState->assocAddIE.length;
12866 }
12867 break;
12868 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012869 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12871 memcpy(pWextState->WPARSNIE, genie - 2,
12872 (eLen + 2));
12873 pWextState->roamProfile.pRSNReqIE =
12874 pWextState->WPARSNIE;
12875 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12876 break;
12877 /*
12878 * Appending Extended Capabilities with Interworking bit set
12879 * in Assoc Req.
12880 *
12881 * In assoc req this EXT Cap will only be taken into account if
12882 * interworkingService bit is set to 1. Currently
12883 * driver is only interested in interworkingService capability
12884 * from supplicant. If in future any other EXT Cap info is
12885 * required from supplicat, it needs to be handled while
12886 * sending Assoc Req in LIM.
12887 */
12888 case DOT11F_EID_EXTCAP:
12889 {
12890 uint16_t curAddIELen =
12891 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012892 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012893
12894 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12895 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012896 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012897 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898 return -ENOMEM;
12899 }
12900 memcpy(pWextState->assocAddIE.addIEdata +
12901 curAddIELen, genie - 2, eLen + 2);
12902 pWextState->assocAddIE.length += eLen + 2;
12903
12904 pWextState->roamProfile.pAddIEAssoc =
12905 pWextState->assocAddIE.addIEdata;
12906 pWextState->roamProfile.nAddIEAssocLength =
12907 pWextState->assocAddIE.length;
12908 break;
12909 }
12910#ifdef FEATURE_WLAN_WAPI
12911 case WLAN_EID_WAPI:
12912 /* Setting WAPI Mode to ON=1 */
12913 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012914 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 tmp = (u16 *) ie;
12916 tmp = tmp + 2; /* Skip element Id and Len, Version */
12917 akmsuiteCount = WPA_GET_LE16(tmp);
12918 tmp = tmp + 1;
12919 akmlist = (int *)(tmp);
12920 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12921 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12922 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012923 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012924 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012925 return -EINVAL;
12926 }
12927
12928 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012929 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012930 pAdapter->wapi_info.wapiAuthMode =
12931 WAPI_AUTH_MODE_PSK;
12932 }
12933 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012934 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935 pAdapter->wapi_info.wapiAuthMode =
12936 WAPI_AUTH_MODE_CERT;
12937 }
12938 break;
12939#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012940 case DOT11F_EID_SUPPOPERATINGCLASSES:
12941 {
12942 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12943 status = wlan_hdd_add_assoc_ie(pWextState,
12944 genie - 2, eLen + 2);
12945 if (status)
12946 return status;
12947 break;
12948 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012950 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012951 /* when Unknown IE is received we break
12952 * and continue to the next IE in the buffer
12953 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012954 break;
12955 }
12956 genie += eLen;
12957 remLen -= eLen;
12958 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012959 return 0;
12960}
12961
12962/**
12963 * hdd_is_wpaie_present() - check for WPA ie
12964 * @ie: Pointer to ie
12965 * @ie_len: Ie length
12966 *
12967 * Parse the received IE to find the WPA IE
12968 *
12969 * Return: true if wpa ie is found else false
12970 */
12971static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12972{
12973 uint8_t eLen = 0;
12974 uint16_t remLen = ie_len;
12975 uint8_t elementId = 0;
12976
12977 while (remLen >= 2) {
12978 elementId = *ie++;
12979 eLen = *ie++;
12980 remLen -= 2;
12981 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012982 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012983 return false;
12984 }
12985 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12986 /* OUI - 0x00 0X50 0XF2
12987 * WPA Information Element - 0x01
12988 * WPA version - 0x01
12989 */
12990 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12991 return true;
12992 }
12993 ie += eLen;
12994 remLen -= eLen;
12995 }
12996 return false;
12997}
12998
12999/**
13000 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13001 * @pAdapter: Pointer to adapter
13002 * @req: Pointer to security parameters
13003 *
13004 * Return: 0 for success, non-zero for failure
13005 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013006static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13007 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008{
13009 int status = 0;
13010 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13011 ENTER();
13012
13013 /*set wpa version */
13014 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13015
13016 if (req->crypto.wpa_versions) {
13017 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13018 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13019 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13020 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13021 }
13022 }
13023
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013024 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013025
13026 /*set authentication type */
13027 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13028
13029 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013030 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013031 return status;
13032 }
13033
13034 /*set key mgmt type */
13035 if (req->crypto.n_akm_suites) {
13036 status =
13037 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13038 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013039 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 return status;
13041 }
13042 }
13043
13044 /*set pairwise cipher type */
13045 if (req->crypto.n_ciphers_pairwise) {
13046 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13047 req->crypto.
13048 ciphers_pairwise[0],
13049 true);
13050 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013051 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 return status;
13053 }
13054 } else {
13055 /*Reset previous cipher suite to none */
13056 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13057 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013058 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013059 return status;
13060 }
13061 }
13062
13063 /*set group cipher type */
13064 status =
13065 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13066 false);
13067
13068 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013069 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070 return status;
13071 }
13072#ifdef WLAN_FEATURE_11W
13073 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13074#endif
13075
13076 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13077 if (req->ie_len) {
13078 status =
13079 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13080 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013081 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082 return status;
13083 }
13084 }
13085
13086 /*incase of WEP set default key information */
13087 if (req->key && req->key_len) {
13088 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13089 || (WLAN_CIPHER_SUITE_WEP104 ==
13090 req->crypto.ciphers_pairwise[0])
13091 ) {
13092 if (IW_AUTH_KEY_MGMT_802_1X
13093 ==
13094 (pWextState->
13095 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013096 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013097 return -EOPNOTSUPP;
13098 } else {
13099 u8 key_len = req->key_len;
13100 u8 key_idx = req->key_idx;
13101
13102 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
13103 key_len)
13104 && (CSR_MAX_NUM_KEY > key_idx)
13105 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013106 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013107 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013108 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 Keys.
13110 KeyMaterial[key_idx][0],
13111 req->key, key_len);
13112 pWextState->roamProfile.Keys.
13113 KeyLength[key_idx] = (u8) key_len;
13114 pWextState->roamProfile.Keys.
13115 defaultIndex = (u8) key_idx;
13116 }
13117 }
13118 }
13119 }
13120
13121 return status;
13122}
13123
13124/**
13125 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
13126 * @pAdapter: Pointer to adapter
13127 *
13128 * This function is used to disconnect from previous connection
13129 *
13130 * Return: 0 for success, non-zero for failure
13131 */
13132static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
13133{
13134 unsigned long rc;
13135 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013136 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013137
13138 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13139
Jeff Johnson9edf9572016-10-03 15:24:49 -070013140 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013141 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13142 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13143 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 hdd_conn_set_connection_state(pAdapter,
13145 eConnectionState_Disconnecting);
13146 /* Issue disconnect to CSR */
13147 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013148
13149 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13150 pAdapter->sessionId,
13151 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13152 /*
13153 * Wait here instead of returning directly, this will block the
13154 * next connect command and allow processing of the scan for
13155 * ssid and the previous connect command in CSR. Else we might
13156 * hit some race conditions leading to SME and HDD out of sync.
13157 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013158 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013159 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13160 } else if (0 != status) {
13161 hdd_err("csrRoamDisconnect failure, returned %d",
13162 (int)status);
13163 pHddStaCtx->staDebugState = status;
13164 result = -EINVAL;
13165 goto disconnected;
13166 }
13167
13168 rc = wait_for_completion_timeout(
13169 &pAdapter->disconnect_comp_var,
13170 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013171 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013172 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13173 pAdapter->sessionId, pHddStaCtx->staDebugState);
13174 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 }
13176 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013177 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013178 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013179 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013181 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013182 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013183 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013184 }
13185 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013186disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013187 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13188 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189}
13190
13191/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013192 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13193 * @adapter: Pointer to the HDD adapter
13194 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013195 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013196 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013197 * This function will start reassociation if prev_bssid is set and bssid/
13198 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013199 *
Naveen Rawat07332902016-07-27 09:13:17 -070013200 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013201 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013202#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13203 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013204static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13205 struct cfg80211_connect_params *req,
13206 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013207{
Naveen Rawat07332902016-07-27 09:13:17 -070013208 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013209 const uint8_t *bssid = NULL;
13210 uint16_t channel = 0;
13211
13212 if (req->bssid)
13213 bssid = req->bssid;
13214 else if (req->bssid_hint)
13215 bssid = req->bssid_hint;
13216
13217 if (req->channel)
13218 channel = req->channel->hw_value;
13219 else if (req->channel_hint)
13220 channel = req->channel_hint->hw_value;
13221
13222 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013223 reassoc = true;
13224 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013225 channel, MAC_ADDR_ARRAY(bssid));
13226 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013227 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013228 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013229 }
Naveen Rawat07332902016-07-27 09:13:17 -070013230 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013231}
13232#else
Naveen Rawat07332902016-07-27 09:13:17 -070013233static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13234 struct cfg80211_connect_params *req,
13235 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013236{
Naveen Rawat07332902016-07-27 09:13:17 -070013237 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013238}
13239#endif
13240
13241/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013242 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13243 * @wiphy: Pointer to wiphy
13244 * @dev: Pointer to network device
13245 * @req: Pointer to cfg80211 connect request
13246 *
13247 * This function is used to start the association process
13248 *
13249 * Return: 0 for success, non-zero for failure
13250 */
13251static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13252 struct net_device *ndev,
13253 struct cfg80211_connect_params *req)
13254{
13255 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013256 u16 channel;
13257#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13258 const u8 *bssid_hint = req->bssid_hint;
13259#else
13260 const u8 *bssid_hint = NULL;
13261#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013262 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13263 hdd_context_t *pHddCtx;
13264
13265 ENTER();
13266
Anurag Chouhan6d760662016-02-20 16:05:43 +053013267 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013268 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 return -EINVAL;
13270 }
13271
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013272 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13273 hdd_err("invalid session id: %d", pAdapter->sessionId);
13274 return -EINVAL;
13275 }
13276
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013277 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278 TRACE_CODE_HDD_CFG80211_CONNECT,
13279 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013280 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013281 hdd_device_mode_to_string(pAdapter->device_mode),
13282 pAdapter->device_mode);
13283
Krunal Sonib4326f22016-03-10 13:05:51 -080013284 if (pAdapter->device_mode != QDF_STA_MODE &&
13285 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013286 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287 hdd_device_mode_to_string(pAdapter->device_mode),
13288 pAdapter->device_mode);
13289 return -EINVAL;
13290 }
13291
13292 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13293 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013294 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013295 return -EINVAL;
13296 }
13297
13298 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013299 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013300 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013301
Naveen Rawat07332902016-07-27 09:13:17 -070013302 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013303 return status;
13304
Agrawal Ashishf156e942016-08-04 14:54:47 +053013305 /* Try disconnecting if already in connected state */
13306 status = wlan_hdd_try_disconnect(pAdapter);
13307 if (0 > status) {
13308 hdd_err("Failed to disconnect the existing connection");
13309 return -EALREADY;
13310 }
13311
13312 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013313 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013314 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013315 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013316 pAdapter->device_mode),
13317 req->channel->hw_value, HW_MODE_20_MHZ)) {
13318 hdd_err("This concurrency combination is not allowed");
13319 return -ECONNREFUSED;
13320 }
13321 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013322 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013323 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013324 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
13325 hdd_err("This concurrency combination is not allowed");
13326 return -ECONNREFUSED;
13327 }
13328 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013330 /*initialise security parameters */
13331 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
13332
13333 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013334 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335 return status;
13336 }
13337
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013338 if (req->channel)
13339 channel = req->channel->hw_value;
13340 else
13341 channel = 0;
13342 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
13343 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013344 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013346 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 return status;
13348 }
13349 EXIT();
13350 return status;
13351}
13352
13353/**
13354 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
13355 * @wiphy: Pointer to wiphy
13356 * @dev: Pointer to network device
13357 * @req: Pointer to cfg80211 connect request
13358 *
13359 * Return: 0 for success, non-zero for failure
13360 */
13361static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13362 struct net_device *ndev,
13363 struct cfg80211_connect_params *req)
13364{
13365 int ret;
13366 cds_ssr_protect(__func__);
13367 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
13368 cds_ssr_unprotect(__func__);
13369
13370 return ret;
13371}
13372
13373/**
13374 * wlan_hdd_disconnect() - hdd disconnect api
13375 * @pAdapter: Pointer to adapter
13376 * @reason: Disconnect reason code
13377 *
13378 * This function is used to issue a disconnect request to SME
13379 *
13380 * Return: 0 for success, non-zero for failure
13381 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013382static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013383{
13384 int status, result = 0;
13385 unsigned long rc;
13386 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13387 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13388
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013389 ENTER();
13390
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391 status = wlan_hdd_validate_context(pHddCtx);
13392
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013393 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013395
13396 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013397 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
13399 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013400 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013401 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
13402 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13403
13404 /*issue disconnect */
13405
13406 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13407 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053013408 /*
13409 * Wait here instead of returning directly, this will block the next
13410 * connect command and allow processing of the scan for ssid and
13411 * the previous connect command in CSR. Else we might hit some
13412 * race conditions leading to SME and HDD out of sync.
13413 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013414 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013415 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013416 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013417 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 (int)status);
13419 pHddStaCtx->staDebugState = status;
13420 result = -EINVAL;
13421 goto disconnected;
13422 }
13423 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13424 msecs_to_jiffies
13425 (WLAN_WAIT_TIME_DISCONNECT));
13426
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013427 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013428 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 result = -ETIMEDOUT;
13430 }
13431disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13433#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
13434 /* Sending disconnect event to userspace for kernel version < 3.11
13435 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
13436 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013437 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053013438 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
13439 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013440#endif
13441
13442 return result;
13443}
13444
13445/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013446 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
13447 * @reason: ieee80211 reason code.
13448 *
13449 * This utility function helps log string conversion of reason code.
13450 *
13451 * Return: string conversion of reason code, if match found;
13452 * "Unknown" otherwise.
13453 */
13454static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
13455{
13456 switch (reason) {
13457 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
13458 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
13459 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
13460 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
13461 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
13462 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13463 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
13464 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
13465 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
13466 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
13467 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
13468 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
13469 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
13470 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
13471 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
13472 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
13473 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
13474 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
13475 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
13476 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
13477 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
13478 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
13479 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
13480 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
13481 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
13482 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
13483 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
13484 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
13485 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
13486 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
13487 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
13488 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
13489 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
13490 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
13491 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
13492 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
13493 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
13494 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
13495 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
13496 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
13497 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
13498 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
13499 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
13500 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
13501 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
13502 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
13503 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
13504 default:
13505 return "Unknown";
13506 }
13507}
13508
13509/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013510 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13511 * @wiphy: Pointer to wiphy
13512 * @dev: Pointer to network device
13513 * @reason: Disconnect reason code
13514 *
13515 * This function is used to issue a disconnect request to SME
13516 *
13517 * Return: 0 for success, non-zero for failure
13518 */
13519static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13520 struct net_device *dev, u16 reason)
13521{
13522 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13523 int status;
13524 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13525 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13526#ifdef FEATURE_WLAN_TDLS
13527 uint8_t staIdx;
13528#endif
13529
13530 ENTER();
13531
Anurag Chouhan6d760662016-02-20 16:05:43 +053013532 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013533 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534 return -EINVAL;
13535 }
13536
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013537 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13538 hdd_err("invalid session id: %d", pAdapter->sessionId);
13539 return -EINVAL;
13540 }
13541
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013542 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013543 TRACE_CODE_HDD_CFG80211_DISCONNECT,
13544 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013545 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546 hdd_device_mode_to_string(pAdapter->device_mode),
13547 pAdapter->device_mode, reason);
13548
13549 status = wlan_hdd_validate_context(pHddCtx);
13550
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080013551 if (hdd_is_roaming_in_progress()) {
13552 hdd_err("Roaming In Progress. Ignore!!!");
13553 return -EAGAIN;
13554 }
13555
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013556 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013557 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013558
13559 /* Issue disconnect request to SME, if station is in connected state */
13560 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
13561 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
13562 eCsrRoamDisconnectReason reasonCode =
13563 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13564 hdd_scaninfo_t *pScanInfo;
13565
13566 switch (reason) {
13567 case WLAN_REASON_MIC_FAILURE:
13568 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
13569 break;
13570
13571 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
13572 case WLAN_REASON_DISASSOC_AP_BUSY:
13573 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
13574 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
13575 break;
13576
13577 case WLAN_REASON_PREV_AUTH_NOT_VALID:
13578 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
13579 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
13580 break;
13581
13582 case WLAN_REASON_DEAUTH_LEAVING:
13583 reasonCode =
13584 pHddCtx->config->
13585 gEnableDeauthToDisassocMap ?
13586 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
13587 eCSR_DISCONNECT_REASON_DEAUTH;
13588 break;
13589 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
13590 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
13591 break;
13592 default:
13593 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
13594 break;
13595 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013596 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013597 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598 pScanInfo = &pAdapter->scan_info;
13599 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013600 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053013602 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 eCSR_SCAN_ABORT_DEFAULT);
13604 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053013605 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606#ifdef FEATURE_WLAN_TDLS
13607 /* First clean up the tdls peers if any */
13608 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
13609 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
13610 pAdapter->sessionId)
13611 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
13612 uint8_t *mac;
13613 mac =
13614 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013615 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
13616 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 pHddCtx->tdlsConnInfo[staIdx].staId,
13618 pAdapter->sessionId,
13619 MAC_ADDR_ARRAY(mac));
13620 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
13621 (pAdapter),
13622 pAdapter->sessionId, mac);
13623 }
13624 }
13625#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013626 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013627 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013628 hdd_info("Disconnect request from user space with reason: %s",
13629 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013630 status = wlan_hdd_disconnect(pAdapter, reasonCode);
13631 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013632 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013633 return -EINVAL;
13634 }
13635 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013636 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637 pHddStaCtx->conn_info.connState);
13638 }
13639
13640 return status;
13641}
13642
13643/**
13644 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13645 * @wiphy: Pointer to wiphy
13646 * @dev: Pointer to network device
13647 * @reason: Disconnect reason code
13648 *
13649 * Return: 0 for success, non-zero for failure
13650 */
13651static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13652 struct net_device *dev, u16 reason)
13653{
13654 int ret;
13655 cds_ssr_protect(__func__);
13656 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13657 cds_ssr_unprotect(__func__);
13658
13659 return ret;
13660}
13661
13662/**
13663 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13664 * @pAdapter: Pointer to adapter
13665 * @param: Pointer to IBSS parameters
13666 *
13667 * This function is used to initialize the security settings in IBSS mode
13668 *
13669 * Return: 0 for success, non-zero for failure
13670 */
13671static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13672 struct cfg80211_ibss_params
13673 *params)
13674{
13675 int status = 0;
13676 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13677 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13678 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13679
13680 ENTER();
13681
13682 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013683 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 pHddStaCtx->ibss_enc_key_installed = 0;
13685
13686 if (params->ie_len && (NULL != params->ie)) {
13687 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13688 params->ie_len, WLAN_EID_RSN)) {
13689 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13690 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13691 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13692 tDot11fIEWPA dot11WPAIE;
13693 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13694 u8 *ie;
13695
13696 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13697 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13698 params->ie_len,
13699 DOT11F_EID_WPA);
13700 if (NULL != ie) {
13701 pWextState->wpaVersion =
13702 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013703 /* Unpack the WPA IE
13704 * Skip past the EID byte and length byte
13705 * and four byte WiFi OUI
13706 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013707 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13708 &ie[2 + 4],
13709 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013710 /* Extract the multicast cipher, the
13711 * encType for unicast cipher for
13712 * wpa-none is none
13713 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013714 encryptionType =
13715 hdd_translate_wpa_to_csr_encryption_type
13716 (dot11WPAIE.multicast_cipher);
13717 }
13718 }
13719
13720 status =
13721 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13722 params->ie_len);
13723
13724 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013725 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 return status;
13727 }
13728 }
13729
13730 pWextState->roamProfile.AuthType.authType[0] =
13731 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13732
13733 if (params->privacy) {
13734 /* Security enabled IBSS, At this time there is no information
13735 * available about the security paramters, so initialise the
13736 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13737 * The correct security parameters will be updated later in
13738 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13739 * set inorder enable privacy bit in beacons
13740 */
13741
13742 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13743 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013744 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013745 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13746 pWextState->roamProfile.EncryptionType.numEntries = 1;
13747 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13748 encryptionType;
13749 return status;
13750}
13751
13752/**
13753 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13754 * @wiphy: Pointer to wiphy
13755 * @dev: Pointer to network device
13756 * @param: Pointer to IBSS join parameters
13757 *
13758 * This function is used to create/join an IBSS network
13759 *
13760 * Return: 0 for success, non-zero for failure
13761 */
13762static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13763 struct net_device *dev,
13764 struct cfg80211_ibss_params *params)
13765{
13766 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13767 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13768 tCsrRoamProfile *pRoamProfile;
13769 int status;
13770 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13771 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013772 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013773 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013774
13775 ENTER();
13776
Anurag Chouhan6d760662016-02-20 16:05:43 +053013777 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013778 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013779 return -EINVAL;
13780 }
13781
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013782 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13783 hdd_err("invalid session id: %d", pAdapter->sessionId);
13784 return -EINVAL;
13785 }
13786
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013787 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013788 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13789 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013790 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013791 hdd_device_mode_to_string(pAdapter->device_mode),
13792 pAdapter->device_mode);
13793
13794 status = wlan_hdd_validate_context(pHddCtx);
13795
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013796 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013797 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013798
13799 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013800 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013801 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13802 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13803 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13804 int indx;
13805
13806 /* Get channel number */
13807 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808 params->
13809 chandef.
13810 chan->
13811 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013812
13813 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13814 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013815 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013816 return -EOPNOTSUPP;
13817 }
13818
13819 for (indx = 0; indx < numChans; indx++) {
13820 if (channelNum == validChan[indx]) {
13821 break;
13822 }
13823 }
13824 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013825 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 return -EINVAL;
13827 }
13828 }
13829
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013830 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 HW_MODE_20_MHZ)) {
13832 hdd_err("This concurrency combination is not allowed");
13833 return -ECONNREFUSED;
13834 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835
Krunal Soni3091bcc2016-06-23 12:28:21 -070013836 status = qdf_reset_connection_update();
13837 if (!QDF_IS_STATUS_SUCCESS(status))
13838 hdd_err("ERR: clear event failed");
13839
13840 status = cds_current_connections_update(pAdapter->sessionId,
13841 channelNum,
13842 SIR_UPDATE_REASON_JOIN_IBSS);
13843 if (QDF_STATUS_E_FAILURE == status) {
13844 hdd_err("ERROR: connections update failed!!");
13845 return -EINVAL;
13846 }
13847
13848 if (QDF_STATUS_SUCCESS == status) {
13849 status = qdf_wait_for_connection_update();
13850 if (!QDF_IS_STATUS_SUCCESS(status)) {
13851 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013852 return -EINVAL;
13853 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013854 }
13855
13856 /*Try disconnecting if already in connected state */
13857 status = wlan_hdd_try_disconnect(pAdapter);
13858 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013859 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860 return -EALREADY;
13861 }
13862
13863 pRoamProfile = &pWextState->roamProfile;
13864
13865 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013866 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867 return -EINVAL;
13868 }
13869
13870 /* enable selected protection checks in IBSS mode */
13871 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13872
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013873 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013874 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13875 pHddCtx->config->
13876 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013877 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878 }
13879
13880 /* BSSID is provided by upper layers hence no need to AUTO generate */
13881 if (NULL != params->bssid) {
13882 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013883 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013884 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 return -EIO;
13886 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013887 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013888 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13889 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013890 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013891 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013892 return -EIO;
13893 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013894 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013895 }
13896 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13897 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13898 pRoamProfile->beaconInterval = params->beacon_interval;
13899 else {
13900 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013901 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013902 params->beacon_interval, pRoamProfile->beaconInterval);
13903 }
13904
13905 /* Set Channel */
13906 if (channelNum) {
13907 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013908 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013909 pRoamProfile->ChannelInfo.numOfChannels = 1;
13910 pHddStaCtx->conn_info.operationChannel = channelNum;
13911 pRoamProfile->ChannelInfo.ChannelList =
13912 &pHddStaCtx->conn_info.operationChannel;
13913 }
13914
13915 /* Initialize security parameters */
13916 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13917 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013918 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919 return status;
13920 }
13921
13922 /* Issue connect start */
13923 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13924 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013925 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013926 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013927 operationChannel,
13928 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013929
13930 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013931 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013932 return status;
13933 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013934 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013935 return 0;
13936}
13937
13938/**
13939 * wlan_hdd_cfg80211_join_ibss() - join ibss
13940 * @wiphy: Pointer to wiphy
13941 * @dev: Pointer to network device
13942 * @param: Pointer to IBSS join parameters
13943 *
13944 * This function is used to create/join an IBSS network
13945 *
13946 * Return: 0 for success, non-zero for failure
13947 */
13948static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13949 struct net_device *dev,
13950 struct cfg80211_ibss_params *params)
13951{
13952 int ret = 0;
13953
13954 cds_ssr_protect(__func__);
13955 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13956 cds_ssr_unprotect(__func__);
13957
13958 return ret;
13959}
13960
13961/**
13962 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13963 * @wiphy: Pointer to wiphy
13964 * @dev: Pointer to network device
13965 *
13966 * This function is used to leave an IBSS network
13967 *
13968 * Return: 0 for success, non-zero for failure
13969 */
13970static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13971 struct net_device *dev)
13972{
13973 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13974 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13975 tCsrRoamProfile *pRoamProfile;
13976 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13977 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013978 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013979 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013980 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981
13982 ENTER();
13983
Anurag Chouhan6d760662016-02-20 16:05:43 +053013984 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013985 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013986 return -EINVAL;
13987 }
13988
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013989 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13990 hdd_err("invalid session id: %d", pAdapter->sessionId);
13991 return -EINVAL;
13992 }
13993
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013994 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13996 pAdapter->sessionId,
13997 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13998 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013999 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014001
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014002 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003 hdd_device_mode_to_string(pAdapter->device_mode),
14004 pAdapter->device_mode);
14005 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014006 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014007 return -EIO;
14008 }
14009
14010 pRoamProfile = &pWextState->roamProfile;
14011
14012 /* Issue disconnect only if interface type is set to IBSS */
14013 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014014 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014015 return -EINVAL;
14016 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014017 /* Clearing add IE of beacon */
14018 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14019 sizeof(tSirMacAddr));
14020 updateIE.smeSessionId = pAdapter->sessionId;
14021 updateIE.ieBufferlength = 0;
14022 updateIE.pAdditionIEBuffer = NULL;
14023 updateIE.append = true;
14024 updateIE.notify = true;
14025 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14026 &updateIE,
14027 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014028 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014029 }
14030
14031 /* Reset WNI_CFG_PROBE_RSP Flags */
14032 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033
14034 /* Issue Disconnect request */
14035 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14036 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14037 pAdapter->sessionId,
14038 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014039 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014040 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014041 hal_status);
14042 return -EAGAIN;
14043 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014044
14045 /* wait for mc thread to cleanup and then return to upper stack
14046 * so by the time upper layer calls the change interface, we are
14047 * all set to proceed further
14048 */
14049 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14050 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14051 if (!rc) {
14052 hdd_err("Failed to disconnect, timed out");
14053 return -ETIMEDOUT;
14054 }
14055
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014056 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014057 return 0;
14058}
14059
14060/**
14061 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14062 * @wiphy: Pointer to wiphy
14063 * @dev: Pointer to network device
14064 *
14065 * This function is used to leave an IBSS network
14066 *
14067 * Return: 0 for success, non-zero for failure
14068 */
14069static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14070 struct net_device *dev)
14071{
14072 int ret = 0;
14073
14074 cds_ssr_protect(__func__);
14075 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14076 cds_ssr_unprotect(__func__);
14077
14078 return ret;
14079}
14080
14081/**
14082 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14083 * @wiphy: Pointer to wiphy
14084 * @changed: Parameters changed
14085 *
14086 * This function is used to set the phy parameters. RTS Threshold/FRAG
14087 * Threshold/Retry Count etc.
14088 *
14089 * Return: 0 for success, non-zero for failure
14090 */
14091static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14092 u32 changed)
14093{
14094 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14095 tHalHandle hHal = pHddCtx->hHal;
14096 int status;
14097
14098 ENTER();
14099
Anurag Chouhan6d760662016-02-20 16:05:43 +053014100 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014101 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014102 return -EINVAL;
14103 }
14104
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014105 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014106 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14107 NO_SESSION, wiphy->rts_threshold));
14108 status = wlan_hdd_validate_context(pHddCtx);
14109
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014110 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014111 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014112
14113 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14114 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14115 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14116
14117 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14118 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014119 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014120 rts_threshold);
14121 return -EINVAL;
14122 }
14123
14124 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14125 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014126 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 rts_threshold);
14128 return -EIO;
14129 }
14130
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014131 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014132 }
14133
14134 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14135 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14136 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14137 wiphy->frag_threshold;
14138
14139 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14140 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014141 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 frag_threshold);
14143 return -EINVAL;
14144 }
14145
14146 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14147 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014148 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014149 frag_threshold);
14150 return -EIO;
14151 }
14152
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014153 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014154 }
14155
14156 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14157 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14158 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14159 wiphy->retry_short : wiphy->retry_long;
14160
14161 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14162 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014163 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014164 return -EINVAL;
14165 }
14166
14167 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14168 if (0 != sme_cfg_set_int(hHal,
14169 WNI_CFG_LONG_RETRY_LIMIT,
14170 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014171 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014172 retry_value);
14173 return -EIO;
14174 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014175 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014176 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14177 if (0 != sme_cfg_set_int(hHal,
14178 WNI_CFG_SHORT_RETRY_LIMIT,
14179 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014180 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181 retry_value);
14182 return -EIO;
14183 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014184 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185 }
14186 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014187 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014188 return 0;
14189}
14190
14191/**
14192 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14193 * @wiphy: Pointer to wiphy
14194 * @changed: Parameters changed
14195 *
14196 * Return: 0 for success, non-zero for failure
14197 */
14198static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14199{
14200 int ret;
14201
14202 cds_ssr_protect(__func__);
14203 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14204 cds_ssr_unprotect(__func__);
14205
14206 return ret;
14207}
14208
14209/**
14210 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14211 * key
14212 * @wiphy: Pointer to wiphy
14213 * @dev: Pointer to network device
14214 * @key_index: Key index
14215 *
14216 * Return: 0
14217 */
14218static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14219 struct net_device *netdev,
14220 u8 key_index)
14221{
14222 ENTER();
14223 return 0;
14224}
14225
14226/**
14227 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14228 * wlan_hdd_set_default_mgmt_key
14229 * @wiphy: pointer to wiphy
14230 * @netdev: pointer to net_device structure
14231 * @key_index: key index
14232 *
14233 * Return: 0 on success, error number on failure
14234 */
14235static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14236 struct net_device *netdev,
14237 u8 key_index)
14238{
14239 int ret;
14240
14241 cds_ssr_protect(__func__);
14242 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14243 cds_ssr_unprotect(__func__);
14244
14245 return ret;
14246}
14247
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014248/**
14249 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14250 * @wiphy: Pointer to wiphy
14251 * @dev: Pointer to network device
14252 * @params: Pointer to tx queue parameters
14253 *
14254 * Return: 0
14255 */
14256static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14257 struct net_device *dev,
14258 struct ieee80211_txq_params *params)
14259{
14260 ENTER();
14261 return 0;
14262}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014263
14264/**
14265 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
14266 * @wiphy: pointer to wiphy
14267 * @netdev: pointer to net_device structure
14268 * @params: pointer to ieee80211_txq_params
14269 *
14270 * Return: 0 on success, error number on failure
14271 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014272static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14273 struct net_device *dev,
14274 struct ieee80211_txq_params *params)
14275{
14276 int ret;
14277
14278 cds_ssr_protect(__func__);
14279 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14280 cds_ssr_unprotect(__func__);
14281
14282 return ret;
14283}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014284
14285/**
14286 * __wlan_hdd_cfg80211_del_station() - delete station v2
14287 * @wiphy: Pointer to wiphy
14288 * @param: Pointer to delete station parameter
14289 *
14290 * Return: 0 for success, non-zero for failure
14291 */
14292static
14293int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14294 struct net_device *dev,
14295 struct tagCsrDelStaParams *pDelStaParams)
14296{
14297 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14298 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014299 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014300 hdd_hostapd_state_t *hapd_state;
14301 int status;
14302 uint8_t staId;
14303 uint8_t *mac;
14304
14305 ENTER();
14306
Anurag Chouhan6d760662016-02-20 16:05:43 +053014307 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014308 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014309 return -EINVAL;
14310 }
14311
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014312 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14313 hdd_err("invalid session id: %d", pAdapter->sessionId);
14314 return -EINVAL;
14315 }
14316
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014317 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318 TRACE_CODE_HDD_CFG80211_DEL_STA,
14319 pAdapter->sessionId, pAdapter->device_mode));
14320
14321 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14322 status = wlan_hdd_validate_context(pHddCtx);
14323
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014324 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014326
14327 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
14328
Krunal Sonib4326f22016-03-10 13:05:51 -080014329 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
14330 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331
14332 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14333 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014334 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 return 0;
14336 }
14337
Anurag Chouhanc5548422016-02-24 18:33:27 +053014338 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339 uint16_t i;
14340 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
14341 if ((pAdapter->aStaInfo[i].isUsed) &&
14342 (!pAdapter->aStaInfo[i].
14343 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014344 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014345 mac,
14346 pAdapter->aStaInfo[i].
14347 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014348 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014349 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14350 hdd_ipa_wlan_evt(pAdapter,
14351 pAdapter->
14352 aStaInfo[i].
14353 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014354 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014355 mac);
14356 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014357 hdd_notice("Delete STA with MAC::"
14358 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014359 MAC_ADDR_ARRAY(mac));
14360
14361 if (pHddCtx->dev_dfs_cac_status ==
14362 DFS_CAC_IN_PROGRESS)
14363 goto fn_end;
14364
Wei Song2f76f642016-11-18 16:32:53 +080014365 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014366 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053014367 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014368 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014369 hdd_softap_sta_deauth(pAdapter,
14370 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014371 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014372 pAdapter->aStaInfo[i].
14373 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014374 qdf_status =
14375 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014376 &hapd_state->
14377 qdf_sta_disassoc_event,
14378 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014379 if (!QDF_IS_STATUS_SUCCESS(
14380 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014381 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 }
14383 }
14384 }
14385 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014386 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014387 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014388 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014390 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014391 hdd_notice("Skip DEL STA as this is not used::"
14392 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014393 MAC_ADDR_ARRAY(mac));
14394 return -ENOENT;
14395 }
14396
14397 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14398 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014399 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014400 }
14401
14402 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
14403 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014404 hdd_notice("Skip DEL STA as deauth is in progress::"
14405 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014406 MAC_ADDR_ARRAY(mac));
14407 return -ENOENT;
14408 }
14409
14410 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
14411
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014412 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014413 MAC_ADDR_ARRAY(mac));
14414
14415 /* Case: SAP in ACS selected DFS ch and client connected
14416 * Now Radar detected. Then if random channel is another
14417 * DFS ch then new CAC is initiated and no TX allowed.
14418 * So do not send any mgmt frames as it will timeout
14419 * during CAC.
14420 */
14421
14422 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
14423 goto fn_end;
14424
Wei Song2f76f642016-11-18 16:32:53 +080014425 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053014426 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
14427 (pAdapter), pAdapter->sessionId,
14428 (uint8_t *)&pDelStaParams->peerMacAddr,
14429 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014430 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014431 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014432 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433 pAdapter->aStaInfo[staId].isDeauthInProgress =
14434 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014435 hdd_notice("STA removal failed for ::"
14436 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014437 MAC_ADDR_ARRAY(mac));
14438 return -ENOENT;
14439 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053014440 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014441 &hapd_state->
14442 qdf_sta_disassoc_event,
14443 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014444 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014445 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014446 }
14447 }
14448 }
14449
14450fn_end:
14451 EXIT();
14452 return 0;
14453}
14454
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014455#if defined(USE_CFG80211_DEL_STA_V2)
14456/**
14457 * wlan_hdd_del_station() - delete station wrapper
14458 * @adapter: pointer to the hdd adapter
14459 *
14460 * Return: None
14461 */
14462void wlan_hdd_del_station(hdd_adapter_t *adapter)
14463{
14464 struct station_del_parameters del_sta;
14465 del_sta.mac = NULL;
14466 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
14467 del_sta.reason_code = eCsrForcedDeauthSta;
14468
14469 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
14470 &del_sta);
14471}
14472#else
14473void wlan_hdd_del_station(hdd_adapter_t *adapter)
14474{
14475 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
14476}
14477#endif
14478
14479#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014480/**
14481 * wlan_hdd_cfg80211_del_station() - delete station v2
14482 * @wiphy: Pointer to wiphy
14483 * @param: Pointer to delete station parameter
14484 *
14485 * Return: 0 for success, non-zero for failure
14486 */
14487int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14488 struct net_device *dev,
14489 struct station_del_parameters *param)
14490#else
14491/**
14492 * wlan_hdd_cfg80211_del_station() - delete station
14493 * @wiphy: Pointer to wiphy
14494 * @mac: Pointer to station mac address
14495 *
14496 * Return: 0 for success, non-zero for failure
14497 */
14498#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14499int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14500 struct net_device *dev,
14501 const uint8_t *mac)
14502#else
14503int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14504 struct net_device *dev,
14505 uint8_t *mac)
14506#endif
14507#endif
14508{
14509 int ret;
14510 struct tagCsrDelStaParams delStaParams;
14511
14512 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014513#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014515 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014516 return -EINVAL;
14517 }
14518 wlansap_populate_del_sta_params(param->mac, param->reason_code,
14519 param->subtype, &delStaParams);
14520#else
14521 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14522 (SIR_MAC_MGMT_DEAUTH >> 4),
14523 &delStaParams);
14524#endif
14525 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
14526 cds_ssr_unprotect(__func__);
14527
14528 return ret;
14529}
14530
14531/**
14532 * __wlan_hdd_cfg80211_add_station() - add station
14533 * @wiphy: Pointer to wiphy
14534 * @mac: Pointer to station mac address
14535 * @pmksa: Pointer to add station parameter
14536 *
14537 * Return: 0 for success, non-zero for failure
14538 */
14539static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14540 struct net_device *dev,
14541 const uint8_t *mac,
14542 struct station_parameters *params)
14543{
14544 int status = -EPERM;
14545#ifdef FEATURE_WLAN_TDLS
14546 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14547 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14548 u32 mask, set;
14549
14550 ENTER();
14551
Anurag Chouhan6d760662016-02-20 16:05:43 +053014552 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014553 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 return -EINVAL;
14555 }
14556
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014557 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14558 hdd_err("invalid session id: %d", pAdapter->sessionId);
14559 return -EINVAL;
14560 }
14561
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014562 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563 TRACE_CODE_HDD_CFG80211_ADD_STA,
14564 pAdapter->sessionId, params->listen_interval));
14565
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014566 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014568
14569 mask = params->sta_flags_mask;
14570
14571 set = params->sta_flags_set;
14572
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014573 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014574 MAC_ADDR_ARRAY(mac));
14575
14576 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14577 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14578 status =
14579 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
14580 }
14581 }
14582#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014583 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584 return status;
14585}
14586
14587/**
14588 * wlan_hdd_cfg80211_add_station() - add station
14589 * @wiphy: Pointer to wiphy
14590 * @mac: Pointer to station mac address
14591 * @pmksa: Pointer to add station parameter
14592 *
14593 * Return: 0 for success, non-zero for failure
14594 */
14595#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14596static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14597 struct net_device *dev,
14598 const uint8_t *mac,
14599 struct station_parameters *params)
14600#else
14601static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14602 struct net_device *dev, uint8_t *mac,
14603 struct station_parameters *params)
14604#endif
14605{
14606 int ret;
14607
14608 cds_ssr_protect(__func__);
14609 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
14610 cds_ssr_unprotect(__func__);
14611
14612 return ret;
14613}
14614
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615/**
14616 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
14617 * @wiphy: Pointer to wiphy
14618 * @dev: Pointer to network device
14619 * @pmksa: Pointer to set pmksa parameter
14620 *
14621 * Return: 0 for success, non-zero for failure
14622 */
14623static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14624 struct net_device *dev,
14625 struct cfg80211_pmksa *pmksa)
14626{
14627 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14628 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14629 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014630 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014631 int status;
14632 tPmkidCacheInfo pmk_id;
14633
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014634 ENTER();
14635
Anurag Chouhan6d760662016-02-20 16:05:43 +053014636 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014637 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014638 return -EINVAL;
14639 }
14640
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014641 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14642 hdd_err("invalid session id: %d", pAdapter->sessionId);
14643 return -EINVAL;
14644 }
14645
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014646 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014647 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014648 return -EINVAL;
14649 }
14650
14651 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014652 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014653 pmksa->bssid, pmksa->pmkid);
14654 return -EINVAL;
14655 }
14656
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014657 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014658 MAC_ADDR_ARRAY(pmksa->bssid));
14659
14660 status = wlan_hdd_validate_context(pHddCtx);
14661
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014662 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014663 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014664
14665 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14666
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014667 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14668 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014669
14670 /* Add to the PMKSA ID Cache in CSR */
14671 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14672 &pmk_id, 1, false);
14673
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014674 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014675 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14676 pAdapter->sessionId, result));
14677
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014678 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014679 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014680}
14681
14682/**
14683 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14684 * @wiphy: Pointer to wiphy
14685 * @dev: Pointer to network device
14686 * @pmksa: Pointer to set pmksa parameter
14687 *
14688 * Return: 0 for success, non-zero for failure
14689 */
14690static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14691 struct net_device *dev,
14692 struct cfg80211_pmksa *pmksa)
14693{
14694 int ret;
14695
14696 cds_ssr_protect(__func__);
14697 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14698 cds_ssr_unprotect(__func__);
14699
14700 return ret;
14701}
14702
14703/**
14704 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14705 * @wiphy: Pointer to wiphy
14706 * @dev: Pointer to network device
14707 * @pmksa: Pointer to pmksa parameter
14708 *
14709 * Return: 0 for success, non-zero for failure
14710 */
14711static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14712 struct net_device *dev,
14713 struct cfg80211_pmksa *pmksa)
14714{
14715 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14716 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14717 tHalHandle halHandle;
14718 int status = 0;
14719
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014720 ENTER();
14721
Anurag Chouhan6d760662016-02-20 16:05:43 +053014722 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014723 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014724 return -EINVAL;
14725 }
14726
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014727 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14728 hdd_err("invalid session id: %d", pAdapter->sessionId);
14729 return -EINVAL;
14730 }
14731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014732 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014733 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734 return -EINVAL;
14735 }
14736
14737 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014738 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 return -EINVAL;
14740 }
14741
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014742 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014743 MAC_ADDR_ARRAY(pmksa->bssid));
14744
14745 status = wlan_hdd_validate_context(pHddCtx);
14746
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014747 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749
14750 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14751
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014752 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014753 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14754 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014755 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014756 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014757 sme_roam_del_pmkid_from_cache(halHandle,
14758 pAdapter->sessionId, pmksa->bssid,
14759 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014760 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014761 MAC_ADDR_ARRAY(pmksa->bssid));
14762 status = -EINVAL;
14763 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014764 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014765 return status;
14766}
14767
14768/**
14769 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14770 * @wiphy: Pointer to wiphy
14771 * @dev: Pointer to network device
14772 * @pmksa: Pointer to pmksa parameter
14773 *
14774 * Return: 0 for success, non-zero for failure
14775 */
14776static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14777 struct net_device *dev,
14778 struct cfg80211_pmksa *pmksa)
14779{
14780 int ret;
14781
14782 cds_ssr_protect(__func__);
14783 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14784 cds_ssr_unprotect(__func__);
14785
14786 return ret;
14787
14788}
14789
14790/**
14791 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14792 * @wiphy: Pointer to wiphy
14793 * @dev: Pointer to network device
14794 *
14795 * Return: 0 for success, non-zero for failure
14796 */
14797static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14798 struct net_device *dev)
14799{
14800 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14801 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14802 tHalHandle halHandle;
14803 int status = 0;
14804
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014805 ENTER();
14806
Anurag Chouhan6d760662016-02-20 16:05:43 +053014807 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014808 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 return -EINVAL;
14810 }
14811
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014812 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14813 hdd_err("invalid session id: %d", pAdapter->sessionId);
14814 return -EINVAL;
14815 }
14816
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014817 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818
14819 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14820 status = wlan_hdd_validate_context(pHddCtx);
14821
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014822 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014823 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014824
14825 /* Retrieve halHandle */
14826 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14827
14828 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014829 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14831 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014832 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014833 status = -EINVAL;
14834 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014835 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014836 return status;
14837}
14838
14839/**
14840 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14841 * @wiphy: Pointer to wiphy
14842 * @dev: Pointer to network device
14843 *
14844 * Return: 0 for success, non-zero for failure
14845 */
14846static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14847 struct net_device *dev)
14848{
14849 int ret;
14850
14851 cds_ssr_protect(__func__);
14852 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14853 cds_ssr_unprotect(__func__);
14854
14855 return ret;
14856}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014857
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014858#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014859/**
14860 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14861 * @wiphy: Pointer to wiphy
14862 * @dev: Pointer to network device
14863 * @ftie: Pointer to fast transition ie parameter
14864 *
14865 * Return: 0 for success, non-zero for failure
14866 */
14867static int
14868__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14869 struct net_device *dev,
14870 struct cfg80211_update_ft_ies_params *ftie)
14871{
14872 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14873 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14874 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14875 int status;
14876
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014877 ENTER();
14878
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879 status = wlan_hdd_validate_context(hdd_ctx);
14880 if (status)
14881 return status;
14882
Anurag Chouhan6d760662016-02-20 16:05:43 +053014883 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014884 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 return -EINVAL;
14886 }
14887
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014888 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14889 hdd_err("invalid session id: %d", pAdapter->sessionId);
14890 return -EINVAL;
14891 }
14892
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014893 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014894 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14895 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14896 /* Added for debug on reception of Re-assoc Req. */
14897 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014898 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014899 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014900 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014901 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014902 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014903 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014904
14905 /* Pass the received FT IEs to SME */
14906 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14907 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014908 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014909 return 0;
14910}
14911
14912/**
14913 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14914 * @wiphy: Pointer to wiphy
14915 * @dev: Pointer to network device
14916 * @ftie: Pointer to fast transition ie parameter
14917 *
14918 * Return: 0 for success, non-zero for failure
14919 */
14920static int
14921wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14922 struct net_device *dev,
14923 struct cfg80211_update_ft_ies_params *ftie)
14924{
14925 int ret;
14926
14927 cds_ssr_protect(__func__);
14928 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14929 cds_ssr_unprotect(__func__);
14930
14931 return ret;
14932}
14933#endif
14934
14935#ifdef WLAN_FEATURE_GTK_OFFLOAD
14936/**
14937 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14938 * @callbackContext: Callback context
14939 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14940 *
14941 * Callback rountine called upon receiving response for get offload info
14942 *
14943 * Return: none
14944 */
14945void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14946 tpSirGtkOffloadGetInfoRspParams
14947 pGtkOffloadGetInfoRsp)
14948{
14949 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14950 uint8_t tempReplayCounter[8];
14951 hdd_station_ctx_t *pHddStaCtx;
14952
14953 ENTER();
14954
14955 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014956 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957 return;
14958 }
14959
14960 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014961 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014962 return;
14963 }
14964
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014965 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014966 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014967 return;
14968 }
14969
14970 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14971 /* Update replay counter */
14972 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14973 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14974
14975 {
14976 /* changing from little to big endian since supplicant
14977 * works on big endian format
14978 */
14979 int i;
14980 uint8_t *p =
14981 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14982
14983 for (i = 0; i < 8; i++) {
14984 tempReplayCounter[7 - i] = (uint8_t) p[i];
14985 }
14986 }
14987
14988 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014989 cfg80211_gtk_rekey_notify(pAdapter->dev,
14990 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014991 tempReplayCounter, GFP_KERNEL);
14992}
14993
14994/**
14995 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14996 * @wiphy: Pointer to wiphy
14997 * @dev: Pointer to network device
14998 * @data: Pointer to rekey data
14999 *
15000 * This function is used to offload GTK rekeying job to the firmware.
15001 *
15002 * Return: 0 for success, non-zero for failure
15003 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015004static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015005int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15006 struct net_device *dev,
15007 struct cfg80211_gtk_rekey_data *data)
15008{
15009 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15010 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15011 hdd_station_ctx_t *pHddStaCtx;
15012 tHalHandle hHal;
15013 int result;
15014 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015015 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015016
15017 ENTER();
15018
Anurag Chouhan6d760662016-02-20 16:05:43 +053015019 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015020 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015021 return -EINVAL;
15022 }
15023
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015024 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15025 hdd_err("invalid session id: %d", pAdapter->sessionId);
15026 return -EINVAL;
15027 }
15028
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015029 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15031 pAdapter->sessionId, pAdapter->device_mode));
15032
15033 result = wlan_hdd_validate_context(pHddCtx);
15034
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015035 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015037
15038 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15039 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15040 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015041 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015042 return -EAGAIN;
15043 }
15044
15045 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
15046 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
15047 NL80211_KCK_LEN);
15048 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
15049 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053015050 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015051 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 {
15053 /* changing from big to little endian since driver
15054 * works on little endian format
15055 */
15056 uint8_t *p =
15057 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
15058 ullKeyReplayCounter;
15059 int i;
15060
15061 for (i = 0; i < 8; i++) {
15062 p[7 - i] = data->replay_ctr[i];
15063 }
15064 }
15065
15066 if (true == pHddCtx->hdd_wlan_suspended) {
15067 /* if wlan is suspended, enable GTK offload directly from here */
15068 memcpy(&hddGtkOffloadReqParams,
15069 &pHddStaCtx->gtkOffloadReqParams,
15070 sizeof(tSirGtkOffloadParams));
15071 status =
15072 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
15073 pAdapter->sessionId);
15074
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015075 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015076 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015077 status);
15078 return -EINVAL;
15079 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015080 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015081 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015082 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015083 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015084 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 return result;
15086}
15087
15088/**
15089 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15090 * @wiphy: Pointer to wiphy
15091 * @dev: Pointer to network device
15092 * @data: Pointer to rekey data
15093 *
15094 * This function is used to offload GTK rekeying job to the firmware.
15095 *
15096 * Return: 0 for success, non-zero for failure
15097 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015098static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015099int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15100 struct net_device *dev,
15101 struct cfg80211_gtk_rekey_data *data)
15102{
15103 int ret;
15104
15105 cds_ssr_protect(__func__);
15106 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15107 cds_ssr_unprotect(__func__);
15108
15109 return ret;
15110}
15111#endif /*WLAN_FEATURE_GTK_OFFLOAD */
15112
15113/**
15114 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15115 * @wiphy: Pointer to wiphy
15116 * @dev: Pointer to network device
15117 * @param: Pointer to access control parameter
15118 *
15119 * Return: 0 for success, non-zero for failure
15120 */
15121static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15122 struct net_device *dev,
15123 const struct cfg80211_acl_data *params)
15124{
15125 int i;
15126 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15127 hdd_hostapd_state_t *pHostapdState;
15128 tsap_Config_t *pConfig;
15129 v_CONTEXT_t p_cds_context = NULL;
15130 hdd_context_t *pHddCtx;
15131 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015132 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015133
15134 ENTER();
15135
Anurag Chouhan6d760662016-02-20 16:05:43 +053015136 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015137 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015138 return -EINVAL;
15139 }
15140
15141 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015142 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015143 return -EINVAL;
15144 }
15145
15146 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15147 status = wlan_hdd_validate_context(pHddCtx);
15148
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015149 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015150 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015151
15152 p_cds_context = pHddCtx->pcds_context;
15153 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15154
15155 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015156 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015157 return -EINVAL;
15158 }
15159
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015160 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015161 params->n_acl_entries);
15162
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015163 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015164 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15165 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015166 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015167 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15168
15169 /* default value */
15170 pConfig->num_accept_mac = 0;
15171 pConfig->num_deny_mac = 0;
15172
15173 /**
15174 * access control policy
15175 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15176 * listed in hostapd.deny file.
15177 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15178 * listed in hostapd.accept file.
15179 */
15180 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15181 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15182 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15183 params->acl_policy) {
15184 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15185 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015186 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 params->acl_policy);
15188 return -ENOTSUPP;
15189 }
15190
15191 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15192 pConfig->num_accept_mac = params->n_acl_entries;
15193 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015194 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15195 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015196 MAC_ADDR_ARRAY(
15197 params->mac_addrs[i].addr));
15198
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015199 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015200 params->mac_addrs[i].addr,
15201 sizeof(qcmacaddr));
15202 }
15203 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15204 pConfig->num_deny_mac = params->n_acl_entries;
15205 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015206 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15207 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208 MAC_ADDR_ARRAY(
15209 params->mac_addrs[i].addr));
15210
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015211 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015212 params->mac_addrs[i].addr,
15213 sizeof(qcmacaddr));
15214 }
15215 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015216 qdf_status = wlansap_set_mac_acl(
15217 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015218 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015219 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015220 return -EINVAL;
15221 }
15222 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015223 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015224 hdd_device_mode_to_string(pAdapter->device_mode),
15225 pAdapter->device_mode);
15226 return -EINVAL;
15227 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015228 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015229 return 0;
15230}
15231
15232/**
15233 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15234 * __wlan_hdd_cfg80211_set_mac_acl
15235 * @wiphy: pointer to wiphy structure
15236 * @dev: pointer to net_device
15237 * @params: pointer to cfg80211_acl_data
15238 *
15239 * Return; 0 on success, error number otherwise
15240 */
15241static int
15242wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15243 struct net_device *dev,
15244 const struct cfg80211_acl_data *params)
15245{
15246 int ret;
15247
15248 cds_ssr_protect(__func__);
15249 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15250 cds_ssr_unprotect(__func__);
15251
15252 return ret;
15253}
15254
15255#ifdef WLAN_NL80211_TESTMODE
15256#ifdef FEATURE_WLAN_LPHB
15257/**
15258 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15259 * @pHddCtx: Pointer to hdd context
15260 * @lphbInd: Pointer to low power heart beat indication parameter
15261 *
15262 * Return: none
15263 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015264static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15265 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015266{
15267 struct sk_buff *skb;
15268
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015269 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015271 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015272 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015273
15274 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015275 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015276 return;
15277 }
15278
15279 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15280 wiphy, sizeof(tSirLPHBInd),
15281 GFP_ATOMIC);
15282 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015283 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284 return;
15285 }
15286
15287 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015288 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015289 goto nla_put_failure;
15290 }
15291 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015292 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 goto nla_put_failure;
15294 }
15295 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015296 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015297 goto nla_put_failure;
15298 }
15299 cfg80211_testmode_event(skb, GFP_ATOMIC);
15300 return;
15301
15302nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015303 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 kfree_skb(skb);
15305
15306 return;
15307}
15308#endif /* FEATURE_WLAN_LPHB */
15309
15310/**
15311 * __wlan_hdd_cfg80211_testmode() - test mode
15312 * @wiphy: Pointer to wiphy
15313 * @data: Data pointer
15314 * @len: Data length
15315 *
15316 * Return: 0 for success, non-zero for failure
15317 */
15318static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15319 void *data, int len)
15320{
15321 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
15322 int err;
15323 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15324
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015325 ENTER();
15326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015327 err = wlan_hdd_validate_context(pHddCtx);
15328 if (err)
15329 return err;
15330
15331 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
15332 len, wlan_hdd_tm_policy);
15333 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015334 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015335 return err;
15336 }
15337
15338 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015339 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015340 return -EINVAL;
15341 }
15342
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015343 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015344 TRACE_CODE_HDD_CFG80211_TESTMODE,
15345 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
15347#ifdef FEATURE_WLAN_LPHB
15348 /* Low Power Heartbeat configuration request */
15349 case WLAN_HDD_TM_CMD_WLAN_HB:
15350 {
15351 int buf_len;
15352 void *buf;
15353 tSirLPHBReq *hb_params = NULL;
15354 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015355 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356
15357 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015358 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015359 return -EINVAL;
15360 }
15361
15362 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15363 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15364
15365 hb_params_temp = (tSirLPHBReq *) buf;
15366 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
15367 && (hb_params_temp->params.lphbTcpParamReq.
15368 timePeriodSec == 0))
15369 return -EINVAL;
15370
15371 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015372 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015373 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015374 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015375 return -ENOMEM;
15376 }
15377
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015378 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015379 smeStatus =
15380 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
15381 hb_params,
15382 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015383 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015384 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015385 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015386 }
15387 return 0;
15388 }
15389#endif /* FEATURE_WLAN_LPHB */
15390
15391#if defined(QCA_WIFI_FTM)
15392 case WLAN_HDD_TM_CMD_WLAN_FTM:
15393 {
15394 int buf_len;
15395 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015396 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015397 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015398 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015399 return -EINVAL;
15400 }
15401
15402 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15403 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15404
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015405 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015406
15407 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
15408
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015409 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015410 err = -EBUSY;
15411 break;
15412 }
15413#endif
15414
15415 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015416 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015417 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
15418 return -EOPNOTSUPP;
15419 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015420 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015421 return err;
15422}
15423
15424/**
15425 * wlan_hdd_cfg80211_testmode() - test mode
15426 * @wiphy: Pointer to wiphy
15427 * @dev: Pointer to network device
15428 * @data: Data pointer
15429 * @len: Data length
15430 *
15431 * Return: 0 for success, non-zero for failure
15432 */
15433static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15434#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
15435 struct wireless_dev *wdev,
15436#endif
15437 void *data, int len)
15438{
15439 int ret;
15440
15441 cds_ssr_protect(__func__);
15442 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
15443 cds_ssr_unprotect(__func__);
15444
15445 return ret;
15446}
15447
15448#if defined(QCA_WIFI_FTM)
15449/**
15450 * wlan_hdd_testmode_rx_event() - test mode rx event handler
15451 * @buf: Pointer to buffer
15452 * @buf_len: Buffer length
15453 *
15454 * Return: none
15455 */
15456void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
15457{
15458 struct sk_buff *skb;
15459 hdd_context_t *hdd_ctx;
15460
15461 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015462 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015463 return;
15464 }
15465
Anurag Chouhan6d760662016-02-20 16:05:43 +053015466 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015467 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015468 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 return;
15470 }
15471
15472 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
15473 buf_len, GFP_KERNEL);
15474 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015475 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015476 return;
15477 }
15478
15479 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
15480 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
15481 goto nla_put_failure;
15482
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015483 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015484
15485 cfg80211_testmode_event(skb, GFP_KERNEL);
15486 return;
15487
15488nla_put_failure:
15489 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015490 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491}
15492#endif
15493#endif /* CONFIG_NL80211_TESTMODE */
15494
15495#ifdef QCA_HT_2040_COEX
15496/**
15497 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15498 * @wiphy: Pointer to wiphy
15499 * @dev: Pointer to network device
15500 * @chandef: Pointer to channel definition parameter
15501 *
15502 * Return: 0 for success, non-zero for failure
15503 */
15504static int
15505__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15506 struct net_device *dev,
15507 struct cfg80211_chan_def *chandef)
15508{
15509 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15510 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015511 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015512 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053015513 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015514
Anurag Chouhan6d760662016-02-20 16:05:43 +053015515 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015516 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015517 return -EINVAL;
15518 }
15519
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015520 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15521 hdd_err("invalid session id: %d", pAdapter->sessionId);
15522 return -EINVAL;
15523 }
15524
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015525 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15526 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053015527 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015528 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015529
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015530 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531 sme_get_config_param(pHddCtx->hHal, &sme_config);
15532 switch (chandef->width) {
15533 case NL80211_CHAN_WIDTH_20:
15534 if (sme_config.csrConfig.channelBondingMode24GHz !=
15535 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15536 sme_config.csrConfig.channelBondingMode24GHz =
15537 eCSR_INI_SINGLE_CHANNEL_CENTERED;
15538 sme_update_config(pHddCtx->hHal, &sme_config);
15539 cbModeChange = true;
15540 }
15541 break;
15542
15543 case NL80211_CHAN_WIDTH_40:
15544 if (sme_config.csrConfig.channelBondingMode24GHz ==
15545 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15546 if (NL80211_CHAN_HT40MINUS ==
15547 cfg80211_get_chandef_type(chandef))
15548 sme_config.csrConfig.channelBondingMode24GHz =
15549 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
15550 else
15551 sme_config.csrConfig.channelBondingMode24GHz =
15552 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
15553 sme_update_config(pHddCtx->hHal, &sme_config);
15554 cbModeChange = true;
15555 }
15556 break;
15557
15558 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015559 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015560 return -EINVAL;
15561 }
15562
15563 if (!cbModeChange)
15564 return 0;
15565
Krunal Sonib4326f22016-03-10 13:05:51 -080015566 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015567 return 0;
15568
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015569 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015570 sme_config.csrConfig.channelBondingMode24GHz);
15571
15572 /* Change SAP ht2040 mode */
15573 status = hdd_set_sap_ht2040_mode(pAdapter,
15574 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015575 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015576 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 return -EINVAL;
15578 }
15579
15580 return 0;
15581}
15582
15583/**
15584 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15585 * @wiphy: Pointer to wiphy
15586 * @dev: Pointer to network device
15587 * @chandef: Pointer to channel definition parameter
15588 *
15589 * Return: 0 for success, non-zero for failure
15590 */
15591static int
15592wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15593 struct net_device *dev,
15594 struct cfg80211_chan_def *chandef)
15595{
15596 int ret;
15597
15598 cds_ssr_protect(__func__);
15599 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
15600 cds_ssr_unprotect(__func__);
15601
15602 return ret;
15603}
15604#endif
15605
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015606#ifdef CHANNEL_SWITCH_SUPPORTED
15607/**
15608 * __wlan_hdd_cfg80211_channel_switch()- function to switch
15609 * channel in SAP/GO
15610 * @wiphy: wiphy pointer
15611 * @dev: dev pointer.
15612 * @csa_params: Change channel params
15613 *
15614 * This function is called to switch channel in SAP/GO
15615 *
15616 * Return: 0 if success else return non zero
15617 */
15618static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15619 struct net_device *dev,
15620 struct cfg80211_csa_settings *csa_params)
15621{
15622 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15623 hdd_context_t *hdd_ctx;
15624 uint8_t channel;
15625 uint16_t freq;
15626 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080015627 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015628
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015629 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015630 csa_params->chandef.chan->center_freq);
15631
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015632 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
15633 hdd_err("invalid session id: %d", adapter->sessionId);
15634 return -EINVAL;
15635 }
15636
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015637 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15638 ret = wlan_hdd_validate_context(hdd_ctx);
15639
15640 if (0 != ret)
15641 return ret;
15642
Krunal Sonib4326f22016-03-10 13:05:51 -080015643 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
15644 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015645 return -ENOTSUPP;
15646
15647 freq = csa_params->chandef.chan->center_freq;
15648 channel = cds_freq_to_chan(freq);
15649
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053015650 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
15651
15652 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015653 return ret;
15654}
15655
15656/**
15657 * wlan_hdd_cfg80211_channel_switch()- function to switch
15658 * channel in SAP/GO
15659 * @wiphy: wiphy pointer
15660 * @dev: dev pointer.
15661 * @csa_params: Change channel params
15662 *
15663 * This function is called to switch channel in SAP/GO
15664 *
15665 * Return: 0 if success else return non zero
15666 */
15667static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15668 struct net_device *dev,
15669 struct cfg80211_csa_settings *csa_params)
15670{
15671 int ret;
15672
15673 cds_ssr_protect(__func__);
15674 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15675 cds_ssr_unprotect(__func__);
15676 return ret;
15677}
15678#endif
15679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015680/**
15681 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15682 * translation from NL to policy manager type
15683 * @type: Generic connection mode type defined in NL
15684 *
15685 *
15686 * This function provides the type translation
15687 *
15688 * Return: cds_con_mode enum
15689 */
15690enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15691 enum nl80211_iftype type)
15692{
15693 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15694 switch (type) {
15695 case NL80211_IFTYPE_STATION:
15696 mode = CDS_STA_MODE;
15697 break;
15698 case NL80211_IFTYPE_P2P_CLIENT:
15699 mode = CDS_P2P_CLIENT_MODE;
15700 break;
15701 case NL80211_IFTYPE_P2P_GO:
15702 mode = CDS_P2P_GO_MODE;
15703 break;
15704 case NL80211_IFTYPE_AP:
15705 mode = CDS_SAP_MODE;
15706 break;
15707 case NL80211_IFTYPE_ADHOC:
15708 mode = CDS_IBSS_MODE;
15709 break;
15710 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015711 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015712 type);
15713 }
15714 return mode;
15715}
15716
15717/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015718 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15719 * @wiphy: Handle to struct wiphy to get handle to module context.
15720 * @chandef: Contains information about the capture channel to be set.
15721 *
15722 * This interface is called if and only if monitor mode interface alone is
15723 * active.
15724 *
15725 * Return: 0 success or error code on failure.
15726 */
15727static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15728 struct cfg80211_chan_def *chandef)
15729{
15730 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15731 hdd_adapter_t *adapter;
15732 hdd_station_ctx_t *sta_ctx;
15733 struct hdd_mon_set_ch_info *ch_info;
15734 QDF_STATUS status;
15735 tHalHandle hal_hdl;
15736 struct qdf_mac_addr bssid;
15737 tCsrRoamProfile roam_profile;
15738 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015739 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015740 int ret;
15741 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15742
15743 ENTER();
15744
15745 ret = wlan_hdd_validate_context(hdd_ctx);
15746 if (ret)
15747 return ret;
15748
15749 hal_hdl = hdd_ctx->hHal;
15750
15751 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15752 if (!adapter)
15753 return -EIO;
15754
15755 hdd_info("%s: set monitor mode Channel %d and freq %d",
15756 adapter->dev->name, chan_num, chandef->chan->center_freq);
15757
15758 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15759 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015760 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15761 roam_profile.ChannelInfo.numOfChannels = 1;
15762 roam_profile.phyMode = ch_info->phy_mode;
15763 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015764 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015765
15766 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15767 QDF_MAC_ADDR_SIZE);
15768
15769 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015770 /*
15771 * CDS api expects secondary channel for calculating
15772 * the channel params
15773 */
15774 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15775 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15776 if (chan_num >= 1 && chan_num <= 5)
15777 sec_ch = chan_num + 4;
15778 else if (chan_num >= 6 && chan_num <= 13)
15779 sec_ch = chan_num - 4;
15780 }
15781 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015782 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15783 &roam_profile);
15784 if (status) {
15785 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15786 status);
15787 ret = qdf_status_to_os_return(status);
15788 return ret;
15789 }
15790 EXIT();
15791 return 0;
15792}
15793
15794/**
15795 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15796 * @wiphy: Handle to struct wiphy to get handle to module context.
15797 * @chandef: Contains information about the capture channel to be set.
15798 *
15799 * This interface is called if and only if monitor mode interface alone is
15800 * active.
15801 *
15802 * Return: 0 success or error code on failure.
15803 */
15804static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15805 struct cfg80211_chan_def *chandef)
15806{
15807 int ret;
15808
15809 cds_ssr_protect(__func__);
15810 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15811 cds_ssr_unprotect(__func__);
15812 return ret;
15813}
15814
15815/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015816 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15817 * @adapter: pointer to adapter
15818 *
15819 * Wrapper function to clear link layer stats.
15820 * return - void
15821 */
15822void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15823{
15824 tSirLLStatsClearReq link_layer_stats_clear_req;
15825 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15826
Mukul Sharma491021c2016-09-29 21:39:19 +053015827 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15828 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015829 link_layer_stats_clear_req.stopReq = 0;
15830 link_layer_stats_clear_req.reqId = 1;
15831 link_layer_stats_clear_req.staId = adapter->sessionId;
15832 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15833
15834 return;
15835}
15836
15837/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015838 * struct cfg80211_ops - cfg80211_ops
15839 *
15840 * @add_virtual_intf: Add virtual interface
15841 * @del_virtual_intf: Delete virtual interface
15842 * @change_virtual_intf: Change virtual interface
15843 * @change_station: Change station
15844 * @add_beacon: Add beacon in sap mode
15845 * @del_beacon: Delete beacon in sap mode
15846 * @set_beacon: Set beacon in sap mode
15847 * @start_ap: Start ap
15848 * @change_beacon: Change beacon
15849 * @stop_ap: Stop ap
15850 * @change_bss: Change bss
15851 * @add_key: Add key
15852 * @get_key: Get key
15853 * @del_key: Delete key
15854 * @set_default_key: Set default key
15855 * @set_channel: Set channel
15856 * @scan: Scan
15857 * @connect: Connect
15858 * @disconnect: Disconnect
15859 * @join_ibss = Join ibss
15860 * @leave_ibss = Leave ibss
15861 * @set_wiphy_params = Set wiphy params
15862 * @set_tx_power = Set tx power
15863 * @get_tx_power = get tx power
15864 * @remain_on_channel = Remain on channel
15865 * @cancel_remain_on_channel = Cancel remain on channel
15866 * @mgmt_tx = Tx management frame
15867 * @mgmt_tx_cancel_wait = Cancel management tx wait
15868 * @set_default_mgmt_key = Set default management key
15869 * @set_txq_params = Set tx queue parameters
15870 * @get_station = Get station
15871 * @set_power_mgmt = Set power management
15872 * @del_station = Delete station
15873 * @add_station = Add station
15874 * @set_pmksa = Set pmksa
15875 * @del_pmksa = Delete pmksa
15876 * @flush_pmksa = Flush pmksa
15877 * @update_ft_ies = Update FT IEs
15878 * @tdls_mgmt = Tdls management
15879 * @tdls_oper = Tdls operation
15880 * @set_rekey_data = Set rekey data
15881 * @sched_scan_start = Scheduled scan start
15882 * @sched_scan_stop = Scheduled scan stop
15883 * @resume = Resume wlan
15884 * @suspend = Suspend wlan
15885 * @set_mac_acl = Set mac acl
15886 * @testmode_cmd = Test mode command
15887 * @set_ap_chanwidth = Set AP channel bandwidth
15888 * @dump_survey = Dump survey
15889 * @key_mgmt_set_pmk = Set pmk key management
15890 */
15891static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15892 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15893 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15894 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15895 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015896 .start_ap = wlan_hdd_cfg80211_start_ap,
15897 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15898 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015899 .change_bss = wlan_hdd_cfg80211_change_bss,
15900 .add_key = wlan_hdd_cfg80211_add_key,
15901 .get_key = wlan_hdd_cfg80211_get_key,
15902 .del_key = wlan_hdd_cfg80211_del_key,
15903 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15904 .scan = wlan_hdd_cfg80211_scan,
15905 .connect = wlan_hdd_cfg80211_connect,
15906 .disconnect = wlan_hdd_cfg80211_disconnect,
15907 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15908 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15909 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15910 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15911 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15912 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15913 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15914 .mgmt_tx = wlan_hdd_mgmt_tx,
15915 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15916 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15917 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015918 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015919 .get_station = wlan_hdd_cfg80211_get_station,
15920 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15921 .del_station = wlan_hdd_cfg80211_del_station,
15922 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015923 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15924 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15925 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015926#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15928#endif
15929#ifdef FEATURE_WLAN_TDLS
15930 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15931 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15932#endif
15933#ifdef WLAN_FEATURE_GTK_OFFLOAD
15934 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15935#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15936#ifdef FEATURE_WLAN_SCAN_PNO
15937 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15938 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15939#endif /*FEATURE_WLAN_SCAN_PNO */
15940 .resume = wlan_hdd_cfg80211_resume_wlan,
15941 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15942 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15943#ifdef WLAN_NL80211_TESTMODE
15944 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15945#endif
15946#ifdef QCA_HT_2040_COEX
15947 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15948#endif
15949 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015950#ifdef CHANNEL_SWITCH_SUPPORTED
15951 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15952#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015953 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015954#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15955 defined(CFG80211_ABORT_SCAN)
15956 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15957#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015958};