blob: 9380060d288d98c80ccf63442e6720e910f89bcc [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/**
1393 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1394 * @wiphy: Linux wiphy struct pointer
1395 * @wdev: Linux wireless device struct pointer
1396 * @data: ACS information from hostapd
1397 * @data_len: ACS information length
1398 *
1399 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1400 * and starts ACS procedure.
1401 *
1402 * Return: ACS procedure start status
1403 */
1404
1405static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1406 struct wireless_dev *wdev,
1407 const void *data, int data_len)
1408{
1409 struct net_device *ndev = wdev->netdev;
1410 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1411 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1412 tsap_Config_t *sap_config;
1413 struct sk_buff *temp_skbuff;
1414 int status = -EINVAL, i = 0;
1415 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1416 bool ht_enabled, ht40_enabled, vht_enabled;
1417 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301418 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001419
1420 /* ***Note*** Donot set SME config related to ACS operation here because
1421 * ACS operation is not synchronouse and ACS for Second AP may come when
1422 * ACS operation for first AP is going on. So only do_acs is split to
1423 * seperate start_acs routine. Also SME-PMAC struct that is used to
1424 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1425 * config shall be set only from start_acs.
1426 */
1427
1428 /* nla_policy Policy template. Policy not applied as some attributes are
1429 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1430 *
1431 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1432 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1433 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1434 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1435 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1436 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1437 */
1438
Jeff Johnson1f61b612016-02-12 16:28:33 -08001439 ENTER_DEV(ndev);
1440
Anurag Chouhan6d760662016-02-20 16:05:43 +05301441 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442 hdd_err("Command not allowed in FTM mode");
1443 return -EPERM;
1444 }
1445
1446 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001447 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 return -EPERM;
1449 }
1450
1451 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301452 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001453 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301454
Naveen Rawat64e477e2016-05-20 10:34:56 -07001455 if (cds_is_sub_20_mhz_enabled()) {
1456 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1457 status = -EINVAL;
1458 goto out;
1459 }
1460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301462 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001463
1464 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1465 NULL);
1466 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001467 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 goto out;
1469 }
1470
1471 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001472 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001473 goto out;
1474 }
1475 sap_config->acs_cfg.hw_mode = nla_get_u8(
1476 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1477
1478 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1479 ht_enabled =
1480 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1481 else
1482 ht_enabled = 0;
1483
1484 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1485 ht40_enabled =
1486 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1487 else
1488 ht40_enabled = 0;
1489
1490 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1491 vht_enabled =
1492 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1493 else
1494 vht_enabled = 0;
1495
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301496 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1497 vht_enabled = 0;
1498 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1499 }
1500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1502 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1503 } else {
1504 if (ht_enabled && ht40_enabled)
1505 ch_width = 40;
1506 else
1507 ch_width = 20;
1508 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301509
1510 /* this may be possible, when sap_force_11n_for_11ac is set */
1511 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1512 if (ht_enabled && ht40_enabled)
1513 ch_width = 40;
1514 else
1515 ch_width = 20;
1516 }
1517
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 if (ch_width == 80)
1519 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1520 else if (ch_width == 40)
1521 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1522 else
1523 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1524
1525 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1526 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1527 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1528 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1529 * since it contains the frequency values of the channels in
1530 * the channel list.
1531 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1532 * is present
1533 */
1534 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1535 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1536 sap_config->acs_cfg.ch_list_count = nla_len(
1537 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1538 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301539 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540 sizeof(uint8_t) *
1541 sap_config->acs_cfg.ch_list_count);
1542 if (sap_config->acs_cfg.ch_list == NULL)
1543 goto out;
1544
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301545 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001546 sap_config->acs_cfg.ch_list_count);
1547 }
1548 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1549 uint32_t *freq =
1550 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1551 sap_config->acs_cfg.ch_list_count = nla_len(
1552 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1553 sizeof(uint32_t);
1554 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301555 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 sap_config->acs_cfg.ch_list_count);
1557 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001558 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 status = -ENOMEM;
1560 goto out;
1561 }
1562
1563 /* convert frequency to channel */
1564 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1565 sap_config->acs_cfg.ch_list[i] =
1566 ieee80211_frequency_to_channel(freq[i]);
1567 }
1568 }
1569
1570 hdd_debug("get pcl for DO_ACS vendor command");
1571
1572 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001573 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301574 sap_config->acs_cfg.pcl_channels,
1575 &sap_config->acs_cfg.pcl_ch_count,
1576 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301577 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001578 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301581 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1582 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001583 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 vht_enabled = 1;
1585 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1586 sap_config->acs_cfg.ch_width =
1587 hdd_ctx->config->vhtChannelWidth;
1588 /* No VHT80 in 2.4G so perform ACS accordingly */
1589 if (sap_config->acs_cfg.end_ch <= 14 &&
1590 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1591 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1592 }
1593
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301594 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1595
Jeff Johnson020db452016-06-29 14:37:26 -07001596 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 -08001597 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1598 ch_width, ht_enabled, vht_enabled,
1599 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1600
1601 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001602 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001603 sap_config->acs_cfg.ch_list_count);
1604 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001605 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606 }
1607 sap_config->acs_cfg.acs_mode = true;
1608 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001609 /* ***Note*** Completion variable usage is not allowed
1610 * here since ACS scan operation may take max 2.2 sec
1611 * for 5G band:
1612 * 9 Active channel X 40 ms active scan time +
1613 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1615 * for this long. So we split up the scanning part.
1616 */
1617 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001618 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001619 status = 0;
1620 } else {
1621 status = wlan_hdd_cfg80211_start_acs(adapter);
1622 }
1623
1624out:
1625 if (0 == status) {
1626 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1627 NLMSG_HDRLEN);
1628 if (temp_skbuff != NULL)
1629 return cfg80211_vendor_cmd_reply(temp_skbuff);
1630 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001631 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001632 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1633
1634 return status;
1635}
1636
Jeff Johnsonf3826e12017-01-12 09:49:40 -08001637/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1639 * @wiphy: Linux wiphy struct pointer
1640 * @wdev: Linux wireless device struct pointer
1641 * @data: ACS information from hostapd
1642 * @data_len: ACS information len
1643 *
1644 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1645 * and starts ACS procedure.
1646 *
1647 * Return: ACS procedure start status
1648 */
1649
1650static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1651 struct wireless_dev *wdev,
1652 const void *data, int data_len)
1653{
1654 int ret;
1655
1656 cds_ssr_protect(__func__);
1657 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1658 cds_ssr_unprotect(__func__);
1659
1660 return ret;
1661}
1662
1663/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001664 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1665 * @adapter: Pointer to adapter struct
1666 *
1667 * This function handle cleanup of what was done in DO_ACS, including free
1668 * memory.
1669 *
1670 * Return: void
1671 */
1672
1673void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1674{
1675 if (adapter == NULL)
1676 return;
1677 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1678 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1679 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1680 }
1681}
1682
1683/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1685 * @work: Linux workqueue struct pointer for ACS work
1686 *
1687 * This function starts the ACS procedure which was marked pending when an ACS
1688 * procedure was in progress for a concurrent SAP interface.
1689 *
1690 * Return: None
1691 */
1692
1693static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1694{
1695 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1696 acs_pending_work.work);
1697 wlan_hdd_cfg80211_start_acs(adapter);
1698}
1699
1700/**
1701 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1702 * @adapter: Pointer to SAP adapter struct
1703 * @pri_channel: SAP ACS procedure selected Primary channel
1704 * @sec_channel: SAP ACS procedure selected secondary channel
1705 *
1706 * This is a callback function from SAP module on ACS procedure is completed.
1707 * This function send the ACS selected channel information to hostapd
1708 *
1709 * Return: None
1710 */
1711
1712void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1713{
1714 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1715 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1716 struct sk_buff *vendor_event;
1717 int ret_val;
1718 hdd_adapter_t *con_sap_adapter;
1719 uint16_t ch_width;
1720
1721 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001722 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001723 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1724 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1725 GFP_KERNEL);
1726
1727 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001728 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001729 return;
1730 }
1731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732 ret_val = nla_put_u8(vendor_event,
1733 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1734 sap_cfg->acs_cfg.pri_ch);
1735 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001736 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737 kfree_skb(vendor_event);
1738 return;
1739 }
1740
1741 ret_val = nla_put_u8(vendor_event,
1742 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1743 sap_cfg->acs_cfg.ht_sec_ch);
1744 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001745 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001746 kfree_skb(vendor_event);
1747 return;
1748 }
1749
1750 ret_val = nla_put_u8(vendor_event,
1751 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1752 sap_cfg->acs_cfg.vht_seg0_center_ch);
1753 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001754 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001755 kfree_skb(vendor_event);
1756 return;
1757 }
1758
1759 ret_val = nla_put_u8(vendor_event,
1760 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1761 sap_cfg->acs_cfg.vht_seg1_center_ch);
1762 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001763 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001764 kfree_skb(vendor_event);
1765 return;
1766 }
1767
1768 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1769 ch_width = 80;
1770 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1771 ch_width = 40;
1772 else
1773 ch_width = 20;
1774
1775 ret_val = nla_put_u16(vendor_event,
1776 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1777 ch_width);
1778 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001779 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780 kfree_skb(vendor_event);
1781 return;
1782 }
1783 if (sap_cfg->acs_cfg.pri_ch > 14)
1784 ret_val = nla_put_u8(vendor_event,
1785 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1786 QCA_ACS_MODE_IEEE80211A);
1787 else
1788 ret_val = nla_put_u8(vendor_event,
1789 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1790 QCA_ACS_MODE_IEEE80211G);
1791
1792 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001793 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794 kfree_skb(vendor_event);
1795 return;
1796 }
1797
Jeff Johnson46b40792016-06-29 14:03:14 -07001798 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 -08001799 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1800 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1801 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1802
1803 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1804 /* ***Note*** As already mentioned Completion variable usage is not
1805 * allowed here since ACS scan operation may take max 2.2 sec.
1806 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1807 * operation.
1808 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1809 * when Primary AP ACS is complete and secondary AP ACS is started here
1810 * immediately, Primary AP start_bss may come inbetween ACS operation
1811 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1812 * delay. This path and below constraint will be removed on sessionizing
1813 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1814 * As per design constraint user space control application must take
1815 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1816 * this code path. Sec AP hostapd should be started after Primary AP
1817 * start beaconing which can be confirmed by getchannel iwpriv command
1818 */
1819
1820 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1821 if (con_sap_adapter &&
1822 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1824 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 /* Lets give 500ms for OBSS + START_BSS to complete */
1826 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1827 msecs_to_jiffies(500));
1828 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1829 }
1830
1831 return;
1832}
1833
1834static int
1835__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1836 struct wireless_dev *wdev,
1837 const void *data,
1838 int data_len)
1839{
1840 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1841 struct sk_buff *skb = NULL;
1842 uint32_t fset = 0;
1843 int ret;
1844
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001845 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301846
Anurag Chouhan6d760662016-02-20 16:05:43 +05301847 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848 hdd_err("Command not allowed in FTM mode");
1849 return -EPERM;
1850 }
1851
1852 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301853 if (ret)
1854 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001855
1856 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001857 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 fset |= WIFI_FEATURE_INFRA;
1859 }
1860 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001861 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 fset |= WIFI_FEATURE_INFRA_5G;
1863 }
1864#ifdef WLAN_FEATURE_P2P
1865 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1866 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001867 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 fset |= WIFI_FEATURE_P2P;
1869 }
1870#endif
1871 fset |= WIFI_FEATURE_SOFT_AP;
1872
1873 /* HOTSPOT is a supplicant feature, enable it by default */
1874 fset |= WIFI_FEATURE_HOTSPOT;
1875
1876#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301877 if (pHddCtx->config->extscan_enabled &&
1878 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001879 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1881 }
1882#endif
1883 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001884 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 fset |= WIFI_FEATURE_NAN;
1886 }
1887 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001888 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889 fset |= WIFI_FEATURE_D2D_RTT;
1890 fset |= WIFI_FEATURE_D2AP_RTT;
1891 }
1892#ifdef FEATURE_WLAN_SCAN_PNO
1893 if (pHddCtx->config->configPNOScanSupport &&
1894 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001895 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 fset |= WIFI_FEATURE_PNO;
1897 }
1898#endif
1899 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1900#ifdef FEATURE_WLAN_TDLS
1901 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1902 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001903 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001904 fset |= WIFI_FEATURE_TDLS;
1905 }
1906 if (sme_is_feature_supported_by_fw(TDLS) &&
1907 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1908 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001909 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1911 }
1912#endif
1913#ifdef WLAN_AP_STA_CONCURRENCY
1914 fset |= WIFI_FEATURE_AP_STA;
1915#endif
1916 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001917 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918
1919 if (hdd_link_layer_stats_supported())
1920 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1921
1922 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1923 NLMSG_HDRLEN);
1924 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001925 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926 return -EINVAL;
1927 }
Jeff Johnson020db452016-06-29 14:37:26 -07001928 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001930 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931 goto nla_put_failure;
1932 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301933 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301934 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935nla_put_failure:
1936 kfree_skb(skb);
1937 return -EINVAL;
1938}
1939
1940/**
1941 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1942 * @wiphy: pointer to wireless wiphy structure.
1943 * @wdev: pointer to wireless_dev structure.
1944 * @data: Pointer to the data to be passed via vendor interface
1945 * @data_len:Length of the data to be passed
1946 *
1947 * Return: Return the Success or Failure code.
1948 */
1949static int
1950wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1951 struct wireless_dev *wdev,
1952 const void *data, int data_len)
1953{
1954 int ret = 0;
1955
1956 cds_ssr_protect(__func__);
1957 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1958 data, data_len);
1959 cds_ssr_unprotect(__func__);
1960
1961 return ret;
1962}
1963
1964/**
1965 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1966 * @wiphy: pointer to wireless wiphy structure.
1967 * @wdev: pointer to wireless_dev structure.
1968 * @data: Pointer to the data to be passed via vendor interface
1969 * @data_len:Length of the data to be passed
1970 *
1971 * Set the MAC address that is to be used for scanning.
1972 *
1973 * Return: Return the Success or Failure code.
1974 */
1975static int
1976__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1977 struct wireless_dev *wdev,
1978 const void *data,
1979 int data_len)
1980{
1981 tpSirScanMacOui pReqMsg = NULL;
1982 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1983 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301984 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 int ret;
1986
Jeff Johnson1f61b612016-02-12 16:28:33 -08001987 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988
Anurag Chouhan6d760662016-02-20 16:05:43 +05301989 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001990 hdd_err("Command not allowed in FTM mode");
1991 return -EPERM;
1992 }
1993
1994 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301995 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997
1998 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001999 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 return -ENOTSUPP;
2001 }
2002
2003 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2004 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002005 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 return -EINVAL;
2007 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302008 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002010 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 return -ENOMEM;
2012 }
2013 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002014 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 goto fail;
2016 }
2017 nla_memcpy(&pReqMsg->oui[0],
2018 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2019 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002020 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 pReqMsg->oui[1], pReqMsg->oui[2]);
2022 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302023 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002024 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 goto fail;
2026 }
2027 return 0;
2028fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302029 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002030 return -EINVAL;
2031}
2032
2033/**
2034 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2035 * @wiphy: pointer to wireless wiphy structure.
2036 * @wdev: pointer to wireless_dev structure.
2037 * @data: Pointer to the data to be passed via vendor interface
2038 * @data_len:Length of the data to be passed
2039 *
2040 * Set the MAC address that is to be used for scanning. This is an
2041 * SSR-protecting wrapper function.
2042 *
2043 * Return: Return the Success or Failure code.
2044 */
2045static int
2046wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2047 struct wireless_dev *wdev,
2048 const void *data,
2049 int data_len)
2050{
2051 int ret;
2052
2053 cds_ssr_protect(__func__);
2054 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2055 data, data_len);
2056 cds_ssr_unprotect(__func__);
2057
2058 return ret;
2059}
2060
2061/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302062 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2063 * @wiphy: pointer phy adapter
2064 * @wdev: pointer to wireless device structure
2065 * @data: pointer to data buffer
2066 * @data_len: length of data
2067 *
2068 * This routine will give concurrency matrix
2069 *
2070 * Return: int status code
2071 */
2072static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2073 struct wireless_dev *wdev,
2074 const void *data,
2075 int data_len)
2076{
2077 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2078 uint8_t i, feature_sets, max_feature_sets;
2079 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2080 struct sk_buff *reply_skb;
2081 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2082 int ret;
2083
2084 ENTER_DEV(wdev->netdev);
2085
2086 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2087 hdd_err("Command not allowed in FTM mode");
2088 return -EPERM;
2089 }
2090
2091 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302092 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302093 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302094
2095 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2096 data, data_len, NULL)) {
2097 hdd_err("Invalid ATTR");
2098 return -EINVAL;
2099 }
2100
2101 /* Parse and fetch max feature set */
2102 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2103 hdd_err("Attr max feature set size failed");
2104 return -EINVAL;
2105 }
2106 max_feature_sets = nla_get_u32(tb[
2107 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2108 hdd_info("Max feature set size: %d", max_feature_sets);
2109
2110 /* Fill feature combination matrix */
2111 feature_sets = 0;
2112 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002113 WIFI_FEATURE_P2P;
2114 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2115 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302116 /* Add more feature combinations here */
2117
2118 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002119 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302120 hdd_info("Feature set matrix");
2121 for (i = 0; i < feature_sets; i++)
2122 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2123
2124 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2125 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2126 if (!reply_skb) {
2127 hdd_err("Feature set matrix: buffer alloc fail");
2128 return -ENOMEM;
2129 }
2130
2131 if (nla_put_u32(reply_skb,
2132 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2133 feature_sets) ||
2134 nla_put(reply_skb,
2135 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2136 sizeof(u32) * feature_sets,
2137 feature_set_matrix)) {
2138 hdd_err("nla put fail");
2139 kfree_skb(reply_skb);
2140 return -EINVAL;
2141 }
2142 return cfg80211_vendor_cmd_reply(reply_skb);
2143}
2144
2145/**
2146 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2147 * @wiphy: pointer to wireless wiphy structure.
2148 * @wdev: pointer to wireless_dev structure.
2149 * @data: Pointer to the data to be passed via vendor interface
2150 * @data_len:Length of the data to be passed
2151 *
2152 * Retrieves the concurrency feature set matrix
2153 *
2154 * Return: 0 on success, negative errno on failure
2155 */
2156static int
2157wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2158 struct wireless_dev *wdev,
2159 const void *data,
2160 int data_len)
2161{
2162 int ret;
2163
2164 cds_ssr_protect(__func__);
2165 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2166 data, data_len);
2167 cds_ssr_unprotect(__func__);
2168
2169 return ret;
2170}
2171
2172/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2174 * @feature_flags: pointer to the byte array of features.
2175 * @feature: Feature to be turned ON in the byte array.
2176 *
2177 * Return: None
2178 *
2179 * This is called to turn ON or SET the feature flag for the requested feature.
2180 **/
2181#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002182static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2183 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184{
2185 uint32_t index;
2186 uint8_t bit_mask;
2187
2188 index = feature / NUM_BITS_IN_BYTE;
2189 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2190 feature_flags[index] |= bit_mask;
2191}
2192
2193/**
2194 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2195 * @wiphy: pointer to wireless wiphy structure.
2196 * @wdev: pointer to wireless_dev structure.
2197 * @data: Pointer to the data to be passed via vendor interface
2198 * @data_len:Length of the data to be passed
2199 *
2200 * This is called when wlan driver needs to send supported feature set to
2201 * supplicant upon a request/query from the supplicant.
2202 *
2203 * Return: Return the Success or Failure code.
2204 **/
2205#define MAX_CONCURRENT_CHAN_ON_24G 2
2206#define MAX_CONCURRENT_CHAN_ON_5G 2
2207static int
2208__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2209 struct wireless_dev *wdev,
2210 const void *data, int data_len)
2211{
2212 struct sk_buff *skb = NULL;
2213 uint32_t dbs_capability = 0;
2214 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302215 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216 int ret_val;
2217
2218 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2219 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2220
Jeff Johnson1f61b612016-02-12 16:28:33 -08002221 ENTER_DEV(wdev->netdev);
2222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002223 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2224 if (ret_val)
2225 return ret_val;
2226
Anurag Chouhan6d760662016-02-20 16:05:43 +05302227 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228 hdd_err("Command not allowed in FTM mode");
2229 return -EPERM;
2230 }
2231
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002232 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002233 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 wlan_hdd_cfg80211_set_feature(feature_flags,
2235 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2236 }
2237
2238 wlan_hdd_cfg80211_set_feature(feature_flags,
2239 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2240 if (wma_is_scan_simultaneous_capable())
2241 wlan_hdd_cfg80211_set_feature(feature_flags,
2242 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002243
2244 if (wma_is_p2p_lo_capable())
2245 wlan_hdd_cfg80211_set_feature(feature_flags,
2246 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2247
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002248 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2249 NLMSG_HDRLEN);
2250
2251 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002252 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253 return -ENOMEM;
2254 }
2255
2256 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2257 sizeof(feature_flags), feature_flags))
2258 goto nla_put_failure;
2259
2260 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302261 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 if (one_by_one_dbs)
2263 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2264
2265 if (two_by_two_dbs)
2266 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2267
2268 if (!one_by_one_dbs && !two_by_two_dbs)
2269 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2270 } else {
2271 hdd_err("wma_get_dbs_hw_mode failed");
2272 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2273 }
2274
2275 hdd_info("dbs_capability is %d", dbs_capability);
2276
2277 if (nla_put_u32(skb,
2278 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2279 MAX_CONCURRENT_CHAN_ON_24G))
2280 goto nla_put_failure;
2281
2282 if (nla_put_u32(skb,
2283 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2284 MAX_CONCURRENT_CHAN_ON_5G))
2285 goto nla_put_failure;
2286
2287 return cfg80211_vendor_cmd_reply(skb);
2288
2289nla_put_failure:
2290 kfree_skb(skb);
2291 return -EINVAL;
2292}
2293
2294/**
2295 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2296 * @wiphy: pointer to wireless wiphy structure.
2297 * @wdev: pointer to wireless_dev structure.
2298 * @data: Pointer to the data to be passed via vendor interface
2299 * @data_len:Length of the data to be passed
2300 *
2301 * This is called when wlan driver needs to send supported feature set to
2302 * supplicant upon a request/query from the supplicant.
2303 *
2304 * Return: Return the Success or Failure code.
2305 */
2306static int
2307wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2308 struct wireless_dev *wdev,
2309 const void *data, int data_len)
2310{
2311 int ret;
2312
2313 cds_ssr_protect(__func__);
2314 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2315 data, data_len);
2316 cds_ssr_unprotect(__func__);
2317
2318 return ret;
2319}
2320
2321
2322/**
2323 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2324 * @wiphy: The wiphy structure
2325 * @wdev: The wireless device
2326 * @data: Data passed by framework
2327 * @data_len: Parameters to be configured passed as data
2328 *
2329 * The roaming related parameters are configured by the framework
2330 * using this interface.
2331 *
2332 * Return: Return either success or failure code.
2333 */
2334static int
2335__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2336 struct wireless_dev *wdev, const void *data, int data_len)
2337{
2338 struct net_device *dev = wdev->netdev;
2339 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2340 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2341 uint8_t session_id;
2342 struct roam_ext_params roam_params;
2343 uint32_t cmd_type, req_id;
2344 struct nlattr *curr_attr;
2345 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2346 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2347 int rem, i;
2348 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002349 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 int ret;
2351
Jeff Johnson1f61b612016-02-12 16:28:33 -08002352 ENTER_DEV(dev);
2353
Anurag Chouhan6d760662016-02-20 16:05:43 +05302354 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355 hdd_err("Command not allowed in FTM mode");
2356 return -EPERM;
2357 }
2358
2359 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302360 if (ret)
2361 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362
2363 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2364 data, data_len,
2365 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002366 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 return -EINVAL;
2368 }
2369 /* Parse and fetch Command Type*/
2370 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002371 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372 goto fail;
2373 }
2374 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302375 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2377 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002378 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 goto fail;
2380 }
2381 req_id = nla_get_u32(
2382 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002383 hdd_debug("Req Id (%d)", req_id);
2384 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 switch (cmd_type) {
2386 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2387 i = 0;
2388 nla_for_each_nested(curr_attr,
2389 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2390 rem) {
2391 if (nla_parse(tb2,
2392 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2393 nla_data(curr_attr), nla_len(curr_attr),
2394 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002395 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 goto fail;
2397 }
2398 /* Parse and Fetch allowed SSID list*/
2399 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002400 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 goto fail;
2402 }
2403 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2404 /*
2405 * Upper Layers include a null termination character.
2406 * Check for the actual permissible length of SSID and
2407 * also ensure not to copy the NULL termination
2408 * character to the driver buffer.
2409 */
2410 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2411 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2412 nla_memcpy(
2413 roam_params.ssid_allowed_list[i].ssId,
2414 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2415 buf_len - 1);
2416 roam_params.ssid_allowed_list[i].length =
2417 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002418 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 roam_params.ssid_allowed_list[i].length,
2420 roam_params.ssid_allowed_list[i].ssId,
2421 roam_params.ssid_allowed_list[i].length);
2422 i++;
2423 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002424 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 }
2426 }
2427 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002428 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 roam_params.num_ssid_allowed_list);
2430 sme_update_roam_params(pHddCtx->hHal, session_id,
2431 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2432 break;
2433 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2434 /* Parse and fetch 5G Boost Threshold */
2435 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002436 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 goto fail;
2438 }
2439 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2440 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002441 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 roam_params.raise_rssi_thresh_5g);
2443 /* Parse and fetch 5G Penalty Threshold */
2444 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002445 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 goto fail;
2447 }
2448 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2449 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002450 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 roam_params.drop_rssi_thresh_5g);
2452 /* Parse and fetch 5G Boost Factor */
2453 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 goto fail;
2456 }
2457 roam_params.raise_factor_5g = nla_get_u32(
2458 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002459 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 roam_params.raise_factor_5g);
2461 /* Parse and fetch 5G Penalty factor */
2462 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 goto fail;
2465 }
2466 roam_params.drop_factor_5g = nla_get_u32(
2467 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002468 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 roam_params.drop_factor_5g);
2470 /* Parse and fetch 5G Max Boost */
2471 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002472 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 goto fail;
2474 }
2475 roam_params.max_raise_rssi_5g = nla_get_u32(
2476 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002477 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 roam_params.max_raise_rssi_5g);
2479 /* Parse and fetch Rssi Diff */
2480 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002481 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 goto fail;
2483 }
2484 roam_params.rssi_diff = nla_get_s32(
2485 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002486 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 roam_params.rssi_diff);
2488 /* Parse and fetch Alert Rssi Threshold */
2489 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002490 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 goto fail;
2492 }
2493 roam_params.alert_rssi_threshold = nla_get_u32(
2494 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002495 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 roam_params.alert_rssi_threshold);
2497 sme_update_roam_params(pHddCtx->hHal, session_id,
2498 roam_params,
2499 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2500 break;
2501 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2502 /* Parse and fetch Activate Good Rssi Roam */
2503 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002504 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002505 goto fail;
2506 }
2507 roam_params.good_rssi_roam = nla_get_s32(
2508 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002509 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510 roam_params.good_rssi_roam);
2511 sme_update_roam_params(pHddCtx->hHal, session_id,
2512 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2513 break;
2514 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2515 /* Parse and fetch number of preferred BSSID */
2516 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002517 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002518 goto fail;
2519 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002520 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002522 if (count > MAX_BSSID_FAVORED) {
2523 hdd_err("Preferred BSSID count %u exceeds max %u",
2524 count, MAX_BSSID_FAVORED);
2525 goto fail;
2526 }
2527 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528 i = 0;
2529 nla_for_each_nested(curr_attr,
2530 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2531 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002532
2533 if (i == count) {
2534 hdd_warn("Ignoring excess Preferred BSSID");
2535 break;
2536 }
2537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 if (nla_parse(tb2,
2539 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2540 nla_data(curr_attr), nla_len(curr_attr),
2541 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002542 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 goto fail;
2544 }
2545 /* Parse and fetch MAC address */
2546 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002547 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 goto fail;
2549 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002550 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302552 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002553 hdd_debug(MAC_ADDRESS_STR,
2554 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555 /* Parse and fetch preference factor*/
2556 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002557 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 goto fail;
2559 }
2560 roam_params.bssid_favored_factor[i] = nla_get_u32(
2561 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002562 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 roam_params.bssid_favored_factor[i]);
2564 i++;
2565 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002566 if (i < count)
2567 hdd_warn("Num Preferred BSSID %u less than expected %u",
2568 i, count);
2569 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 sme_update_roam_params(pHddCtx->hHal, session_id,
2571 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2572 break;
2573 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2574 /* Parse and fetch number of blacklist BSSID */
2575 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002576 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 goto fail;
2578 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002579 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002581 if (count > MAX_BSSID_AVOID_LIST) {
2582 hdd_err("Blacklist BSSID count %u exceeds max %u",
2583 count, MAX_BSSID_AVOID_LIST);
2584 goto fail;
2585 }
2586 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587 i = 0;
2588 nla_for_each_nested(curr_attr,
2589 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2590 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002591
2592 if (i == count) {
2593 hdd_warn("Ignoring excess Blacklist BSSID");
2594 break;
2595 }
2596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597 if (nla_parse(tb2,
2598 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2599 nla_data(curr_attr), nla_len(curr_attr),
2600 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002601 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 goto fail;
2603 }
2604 /* Parse and fetch MAC address */
2605 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002606 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 goto fail;
2608 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002609 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002610 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302611 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002612 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002614 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615 i++;
2616 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002617 if (i < count)
2618 hdd_warn("Num Blacklist BSSID %u less than expected %u",
2619 i, count);
2620 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002621 sme_update_roam_params(pHddCtx->hHal, session_id,
2622 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2623 break;
2624 }
2625 return 0;
2626fail:
2627 return -EINVAL;
2628}
2629
2630/**
2631 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2632 * @wiphy: pointer to wireless wiphy structure.
2633 * @wdev: pointer to wireless_dev structure.
2634 * @data: Pointer to the data to be passed via vendor interface
2635 * @data_len:Length of the data to be passed
2636 *
2637 * Return: Return the Success or Failure code.
2638 */
2639static int
2640wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2641 struct wireless_dev *wdev,
2642 const void *data,
2643 int data_len)
2644{
2645 int ret;
2646
2647 cds_ssr_protect(__func__);
2648 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2649 data, data_len);
2650 cds_ssr_unprotect(__func__);
2651
2652 return ret;
2653}
2654
2655static const struct nla_policy
2656wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2657 +1] = {
2658 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2659};
2660
2661/**
2662 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2663 * @hdd_ctx: HDD context
2664 * @device_mode: device mode
2665 * Return: bool
2666 */
2667static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002668 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669{
2670 hdd_adapter_t *adapter;
2671 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2672 hdd_ap_ctx_t *ap_ctx;
2673 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302674 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302676 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 &adapter_node);
2678
2679 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302680 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 adapter = adapter_node->pAdapter;
2682
2683 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002684 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 ap_ctx =
2686 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2687
2688 /*
2689 * if there is SAP already running on DFS channel,
2690 * do not disable scan on dfs channels. Note that
2691 * with SAP on DFS, there cannot be conurrency on
2692 * single radio. But then we can have multiple
2693 * radios !!
2694 */
2695 if (CHANNEL_STATE_DFS ==
2696 cds_get_channel_state(
2697 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002698 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 return true;
2700 }
2701 }
2702
2703 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002704 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 sta_ctx =
2706 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2707
2708 /*
2709 * if STA is already connected on DFS channel,
2710 * do not disable scan on dfs channels
2711 */
2712 if (hdd_conn_is_connected(sta_ctx) &&
2713 (CHANNEL_STATE_DFS ==
2714 cds_get_channel_state(
2715 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002716 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717 return true;
2718 }
2719 }
2720
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302721 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002722 adapter_node,
2723 &next);
2724 adapter_node = next;
2725 }
2726
2727 return false;
2728}
2729
2730/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002731 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2732 * @hdd_ctx: HDD context within host driver
2733 * @adapter: Adapter pointer
2734 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2735 *
2736 * Loops through devices to see who is operating on DFS channels
2737 * and then disables/enables DFS channels by calling SME API.
2738 * Fails the disable request if any device is active on a DFS channel.
2739 *
2740 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002741 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002742
2743int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2744 hdd_adapter_t *adapter,
2745 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002746{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302748 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750
2751 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2752 if (no_dfs_flag) {
2753 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002754 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755
2756 if (true == status)
2757 return -EOPNOTSUPP;
2758
2759 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002760 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761
2762 if (true == status)
2763 return -EOPNOTSUPP;
2764 }
2765
2766 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2767
2768 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2769
2770 /*
2771 * call the SME API to tunnel down the new channel list
2772 * to the firmware
2773 */
2774 status = sme_handle_dfs_chan_scan(
2775 h_hal, hdd_ctx->config->enableDFSChnlScan);
2776
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302777 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002778 ret_val = 0;
2779
2780 /*
2781 * Clear the SME scan cache also. Note that the
2782 * clearing of scan results is independent of session;
2783 * so no need to iterate over
2784 * all sessions
2785 */
2786 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302787 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002788 ret_val = -EPERM;
2789 }
2790
2791 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002792 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 ret_val = 0;
2794 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002795 return ret_val;
2796}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002798/**
2799 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2800 * @wiphy: corestack handler
2801 * @wdev: wireless device
2802 * @data: data
2803 * @data_len: data length
2804 * Return: success(0) or reason code for failure
2805 */
2806static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2807 struct wireless_dev *wdev,
2808 const void *data,
2809 int data_len)
2810{
2811 struct net_device *dev = wdev->netdev;
2812 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2813 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2814 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2815 int ret_val;
2816 uint32_t no_dfs_flag = 0;
2817
Jeff Johnson1f61b612016-02-12 16:28:33 -08002818 ENTER_DEV(dev);
2819
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002820 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302821 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002822 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002823
2824 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2825 data, data_len,
2826 wlan_hdd_set_no_dfs_flag_config_policy)) {
2827 hdd_err("invalid attr");
2828 return -EINVAL;
2829 }
2830
2831 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2832 hdd_err("attr dfs flag failed");
2833 return -EINVAL;
2834 }
2835
2836 no_dfs_flag = nla_get_u32(
2837 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2838
Jeff Johnson020db452016-06-29 14:37:26 -07002839 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002840
2841 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002842 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002843 return -EINVAL;
2844 }
2845
2846 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2847 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 return ret_val;
2849}
2850
2851/**
2852 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2853 *
2854 * @wiphy: wiphy device pointer
2855 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002856 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857 * @data_len: Buffer length
2858 *
2859 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2860 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2861 *
2862 * Return: EOK or other error codes.
2863 */
2864
2865static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2866 struct wireless_dev *wdev,
2867 const void *data,
2868 int data_len)
2869{
2870 int ret;
2871
2872 cds_ssr_protect(__func__);
2873 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2874 data, data_len);
2875 cds_ssr_unprotect(__func__);
2876
2877 return ret;
2878}
2879
Manikandan Mohan80dea792016-04-28 16:36:48 -07002880static const struct nla_policy
2881wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2882 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2883};
2884
2885/**
2886 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2887 * @wiphy: wiphy device pointer
2888 * @wdev: wireless device pointer
2889 * @data: Vendor command data buffer
2890 * @data_len: Buffer length
2891 *
2892 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2893 * setup WISA Mode features.
2894 *
2895 * Return: Success(0) or reason code for failure
2896 */
2897static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2898 struct wireless_dev *wdev, const void *data, int data_len)
2899{
2900 struct net_device *dev = wdev->netdev;
2901 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2902 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2903 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2904 struct sir_wisa_params wisa;
2905 int ret_val;
2906 QDF_STATUS status;
2907 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07002908 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2909 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002910
2911 ENTER_DEV(dev);
2912 ret_val = wlan_hdd_validate_context(hdd_ctx);
2913 if (ret_val)
2914 goto err;
2915
2916 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2917 hdd_err("Command not allowed in FTM mode");
2918 return -EPERM;
2919 }
2920
2921 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2922 wlan_hdd_wisa_cmd_policy)) {
2923 hdd_err("Invalid WISA cmd attributes");
2924 ret_val = -EINVAL;
2925 goto err;
2926 }
2927 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2928 hdd_err("Invalid WISA mode");
2929 ret_val = -EINVAL;
2930 goto err;
2931 }
2932
2933 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2934 hdd_info("WISA Mode: %d", wisa_mode);
2935 wisa.mode = wisa_mode;
2936 wisa.vdev_id = adapter->sessionId;
2937 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002938 if (!QDF_IS_STATUS_SUCCESS(status)) {
2939 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002940 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002941 }
2942 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07002943 cdp_set_wisa_mode(soc,
2944 cdp_get_vdev_from_vdev_id(soc, pdev,
2945 adapter->sessionId),
2946 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002947err:
2948 EXIT();
2949 return ret_val;
2950}
2951
2952/**
2953 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2954 * @wiphy: corestack handler
2955 * @wdev: wireless device
2956 * @data: data
2957 * @data_len: data length
2958 *
2959 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2960 * setup WISA mode features.
2961 *
2962 * Return: Success(0) or reason code for failure
2963 */
2964static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2965 struct wireless_dev *wdev,
2966 const void *data,
2967 int data_len)
2968{
2969 int ret;
2970
2971 cds_ssr_protect(__func__);
2972 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2973 cds_ssr_unprotect(__func__);
2974
2975 return ret;
2976}
2977
Anurag Chouhan96919482016-07-13 16:36:57 +05302978/*
2979 * define short names for the global vendor params
2980 * used by __wlan_hdd_cfg80211_get_station_cmd()
2981 */
2982#define STATION_INVALID \
2983 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2984#define STATION_INFO \
2985 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2986#define STATION_ASSOC_FAIL_REASON \
2987 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2988#define STATION_MAX \
2989 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2990
2991static const struct nla_policy
2992hdd_get_station_policy[STATION_MAX + 1] = {
2993 [STATION_INFO] = {.type = NLA_FLAG},
2994 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2995};
2996
2997/**
2998 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2999 * @hdd_ctx: HDD context within host driver
3000 * @wdev: wireless device
3001 *
3002 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3003 * Validate cmd attributes and send the station info to upper layers.
3004 *
3005 * Return: Success(0) or reason code for failure
3006 */
3007static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3008 hdd_adapter_t *adapter)
3009{
3010 struct sk_buff *skb = NULL;
3011 uint32_t nl_buf_len;
3012 hdd_station_ctx_t *hdd_sta_ctx;
3013
3014 nl_buf_len = NLMSG_HDRLEN;
3015 nl_buf_len += sizeof(uint32_t);
3016 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3017
3018 if (!skb) {
3019 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3020 return -ENOMEM;
3021 }
3022
3023 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3024
3025 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3026 hdd_sta_ctx->conn_info.assoc_status_code)) {
3027 hdd_err("put fail");
3028 goto fail;
3029 }
3030 return cfg80211_vendor_cmd_reply(skb);
3031fail:
3032 if (skb)
3033 kfree_skb(skb);
3034 return -EINVAL;
3035}
3036
3037/**
3038 * hdd_map_auth_type() - transform auth type specific to
3039 * vendor command
3040 * @auth_type: csr auth type
3041 *
3042 * Return: Success(0) or reason code for failure
3043 */
3044static int hdd_convert_auth_type(uint32_t auth_type)
3045{
3046 uint32_t ret_val;
3047
3048 switch (auth_type) {
3049 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3050 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3051 break;
3052 case eCSR_AUTH_TYPE_SHARED_KEY:
3053 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3054 break;
3055 case eCSR_AUTH_TYPE_WPA:
3056 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3057 break;
3058 case eCSR_AUTH_TYPE_WPA_PSK:
3059 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3060 break;
3061 case eCSR_AUTH_TYPE_AUTOSWITCH:
3062 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3063 break;
3064 case eCSR_AUTH_TYPE_WPA_NONE:
3065 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3066 break;
3067 case eCSR_AUTH_TYPE_RSN:
3068 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3069 break;
3070 case eCSR_AUTH_TYPE_RSN_PSK:
3071 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3072 break;
3073 case eCSR_AUTH_TYPE_FT_RSN:
3074 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3075 break;
3076 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3077 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3078 break;
3079 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3080 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3081 break;
3082 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3083 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3084 break;
3085 case eCSR_AUTH_TYPE_CCKM_WPA:
3086 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3087 break;
3088 case eCSR_AUTH_TYPE_CCKM_RSN:
3089 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3090 break;
3091 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3092 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3093 break;
3094 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3095 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3096 break;
3097 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3098 case eCSR_AUTH_TYPE_FAILED:
3099 case eCSR_AUTH_TYPE_NONE:
3100 default:
3101 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3102 break;
3103 }
3104 return ret_val;
3105}
3106
3107/**
3108 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3109 * vendor command
3110 * @dot11mode: dot11mode
3111 *
3112 * Return: Success(0) or reason code for failure
3113 */
3114static int hdd_convert_dot11mode(uint32_t dot11mode)
3115{
3116 uint32_t ret_val;
3117
3118 switch (dot11mode) {
3119 case eCSR_CFG_DOT11_MODE_11A:
3120 ret_val = QCA_WLAN_802_11_MODE_11A;
3121 break;
3122 case eCSR_CFG_DOT11_MODE_11B:
3123 ret_val = QCA_WLAN_802_11_MODE_11B;
3124 break;
3125 case eCSR_CFG_DOT11_MODE_11G:
3126 ret_val = QCA_WLAN_802_11_MODE_11G;
3127 break;
3128 case eCSR_CFG_DOT11_MODE_11N:
3129 ret_val = QCA_WLAN_802_11_MODE_11N;
3130 break;
3131 case eCSR_CFG_DOT11_MODE_11AC:
3132 ret_val = QCA_WLAN_802_11_MODE_11AC;
3133 break;
3134 case eCSR_CFG_DOT11_MODE_AUTO:
3135 case eCSR_CFG_DOT11_MODE_ABG:
3136 default:
3137 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3138 }
3139 return ret_val;
3140}
3141
3142/**
3143 * hdd_add_tx_bitrate() - add tx bitrate attribute
3144 * @skb: pointer to sk buff
3145 * @hdd_sta_ctx: pointer to hdd station context
3146 * @idx: attribute index
3147 *
3148 * Return: Success(0) or reason code for failure
3149 */
3150static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3151 hdd_station_ctx_t *hdd_sta_ctx,
3152 int idx)
3153{
3154 struct nlattr *nla_attr;
3155 uint32_t bitrate, bitrate_compat;
3156
3157 nla_attr = nla_nest_start(skb, idx);
3158 if (!nla_attr)
3159 goto fail;
3160 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3161 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3162
3163 /* report 16-bit bitrate only if we can */
3164 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3165 if (bitrate > 0 &&
3166 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3167 hdd_err("put fail");
3168 goto fail;
3169 }
3170 if (bitrate_compat > 0 &&
3171 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3172 hdd_err("put fail");
3173 goto fail;
3174 }
3175 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3176 hdd_sta_ctx->conn_info.txrate.nss)) {
3177 hdd_err("put fail");
3178 goto fail;
3179 }
3180 nla_nest_end(skb, nla_attr);
3181 return 0;
3182fail:
3183 return -EINVAL;
3184}
3185
3186/**
3187 * hdd_add_sta_info() - add station info attribute
3188 * @skb: pointer to sk buff
3189 * @hdd_sta_ctx: pointer to hdd station context
3190 * @idx: attribute index
3191 *
3192 * Return: Success(0) or reason code for failure
3193 */
3194static int32_t hdd_add_sta_info(struct sk_buff *skb,
3195 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3196{
3197 struct nlattr *nla_attr;
3198
3199 nla_attr = nla_nest_start(skb, idx);
3200 if (!nla_attr)
3201 goto fail;
3202 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3203 (hdd_sta_ctx->conn_info.signal + 100))) {
3204 hdd_err("put fail");
3205 goto fail;
3206 }
3207 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3208 goto fail;
3209 nla_nest_end(skb, nla_attr);
3210 return 0;
3211fail:
3212 return -EINVAL;
3213}
3214
3215/**
3216 * hdd_add_survey_info() - add survey info attribute
3217 * @skb: pointer to sk buff
3218 * @hdd_sta_ctx: pointer to hdd station context
3219 * @idx: attribute index
3220 *
3221 * Return: Success(0) or reason code for failure
3222 */
3223static int32_t hdd_add_survey_info(struct sk_buff *skb,
3224 hdd_station_ctx_t *hdd_sta_ctx,
3225 int idx)
3226{
3227 struct nlattr *nla_attr;
3228
3229 nla_attr = nla_nest_start(skb, idx);
3230 if (!nla_attr)
3231 goto fail;
3232 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3233 hdd_sta_ctx->conn_info.freq) ||
3234 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3235 (hdd_sta_ctx->conn_info.noise + 100))) {
3236 hdd_err("put fail");
3237 goto fail;
3238 }
3239 nla_nest_end(skb, nla_attr);
3240 return 0;
3241fail:
3242 return -EINVAL;
3243}
3244
3245/**
3246 * hdd_add_link_standard_info() - add link info attribute
3247 * @skb: pointer to sk buff
3248 * @hdd_sta_ctx: pointer to hdd station context
3249 * @idx: attribute index
3250 *
3251 * Return: Success(0) or reason code for failure
3252 */
3253static int32_t
3254hdd_add_link_standard_info(struct sk_buff *skb,
3255 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3256{
3257 struct nlattr *nla_attr;
3258
3259 nla_attr = nla_nest_start(skb, idx);
3260 if (!nla_attr)
3261 goto fail;
3262 if (nla_put(skb,
3263 NL80211_ATTR_SSID,
3264 hdd_sta_ctx->conn_info.SSID.SSID.length,
3265 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3266 hdd_err("put fail");
3267 goto fail;
3268 }
3269 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3270 goto fail;
3271 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3272 goto fail;
3273 nla_nest_end(skb, nla_attr);
3274 return 0;
3275fail:
3276 return -EINVAL;
3277}
3278
3279/**
3280 * hdd_add_ap_standard_info() - add ap info attribute
3281 * @skb: pointer to sk buff
3282 * @hdd_sta_ctx: pointer to hdd station context
3283 * @idx: attribute index
3284 *
3285 * Return: Success(0) or reason code for failure
3286 */
3287static int32_t
3288hdd_add_ap_standard_info(struct sk_buff *skb,
3289 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3290{
3291 struct nlattr *nla_attr;
3292
3293 nla_attr = nla_nest_start(skb, idx);
3294 if (!nla_attr)
3295 goto fail;
3296 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3297 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3298 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3299 &hdd_sta_ctx->conn_info.vht_caps)) {
3300 hdd_err("put fail");
3301 goto fail;
3302 }
3303 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3304 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3305 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3306 &hdd_sta_ctx->conn_info.ht_caps)) {
3307 hdd_err("put fail");
3308 goto fail;
3309 }
3310 nla_nest_end(skb, nla_attr);
3311 return 0;
3312fail:
3313 return -EINVAL;
3314}
3315
3316/**
3317 * hdd_get_station_info() - send BSS information to supplicant
3318 * @hdd_ctx: pointer to hdd context
3319 * @adapter: pointer to adapter
3320 *
3321 * Return: 0 if success else error status
3322 */
3323static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3324 hdd_adapter_t *adapter)
3325{
3326 struct sk_buff *skb = NULL;
3327 uint8_t *tmp_hs20 = NULL;
3328 uint32_t nl_buf_len;
3329 hdd_station_ctx_t *hdd_sta_ctx;
3330
3331 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3332
3333 nl_buf_len = NLMSG_HDRLEN;
3334 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3335 sizeof(hdd_sta_ctx->conn_info.freq) +
3336 sizeof(hdd_sta_ctx->conn_info.noise) +
3337 sizeof(hdd_sta_ctx->conn_info.signal) +
3338 (sizeof(uint32_t) * 2) +
3339 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3340 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3341 sizeof(hdd_sta_ctx->conn_info.authType) +
3342 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3343 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3344 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3345 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3346 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3347 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3348 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3349 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3350 1);
3351 }
3352 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3353 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3354 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3355 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3356
3357
3358 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3359 if (!skb) {
3360 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3361 return -ENOMEM;
3362 }
3363
3364 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3365 LINK_INFO_STANDARD_NL80211_ATTR)) {
3366 hdd_err("put fail");
3367 goto fail;
3368 }
3369 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3370 AP_INFO_STANDARD_NL80211_ATTR)) {
3371 hdd_err("put fail");
3372 goto fail;
3373 }
3374 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3375 hdd_sta_ctx->conn_info.roam_count) ||
3376 nla_put_u32(skb, INFO_AKM,
3377 hdd_convert_auth_type(
3378 hdd_sta_ctx->conn_info.authType)) ||
3379 nla_put_u32(skb, WLAN802_11_MODE,
3380 hdd_convert_dot11mode(
3381 hdd_sta_ctx->conn_info.dot11Mode))) {
3382 hdd_err("put fail");
3383 goto fail;
3384 }
3385 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3386 if (nla_put(skb, HT_OPERATION,
3387 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3388 &hdd_sta_ctx->conn_info.ht_operation)) {
3389 hdd_err("put fail");
3390 goto fail;
3391 }
3392 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3393 if (nla_put(skb, VHT_OPERATION,
3394 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3395 &hdd_sta_ctx->conn_info.vht_operation)) {
3396 hdd_err("put fail");
3397 goto fail;
3398 }
3399 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3400 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3401 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3402 tmp_hs20 + 1)) {
3403 hdd_err("put fail");
3404 goto fail;
3405 }
3406
3407 return cfg80211_vendor_cmd_reply(skb);
3408fail:
3409 if (skb)
3410 kfree_skb(skb);
3411 return -EINVAL;
3412}
3413
3414/**
3415 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3416 * @wiphy: corestack handler
3417 * @wdev: wireless device
3418 * @data: data
3419 * @data_len: data length
3420 *
3421 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3422 * Validate cmd attributes and send the station info to upper layers.
3423 *
3424 * Return: Success(0) or reason code for failure
3425 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303426static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303427__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3428 struct wireless_dev *wdev,
3429 const void *data,
3430 int data_len)
3431{
3432 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3433 struct net_device *dev = wdev->netdev;
3434 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3435 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3436 int32_t status;
3437
3438 ENTER_DEV(dev);
3439 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3440 hdd_err("Command not allowed in FTM mode");
3441 status = -EPERM;
3442 goto out;
3443 }
3444
3445 status = wlan_hdd_validate_context(hdd_ctx);
3446 if (0 != status)
3447 goto out;
3448
3449
3450 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3451 data, data_len, NULL);
3452 if (status) {
3453 hdd_err("Invalid ATTR");
3454 goto out;
3455 }
3456
3457 /* Parse and fetch Command Type*/
3458 if (tb[STATION_INFO]) {
3459 status = hdd_get_station_info(hdd_ctx, adapter);
3460 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3461 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3462 } else {
3463 hdd_err("get station info cmd type failed");
3464 status = -EINVAL;
3465 goto out;
3466 }
3467 EXIT();
3468out:
3469 return status;
3470}
3471
3472/**
3473 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3474 * @wiphy: corestack handler
3475 * @wdev: wireless device
3476 * @data: data
3477 * @data_len: data length
3478 *
3479 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3480 * Validate cmd attributes and send the station info to upper layers.
3481 *
3482 * Return: Success(0) or reason code for failure
3483 */
3484static int32_t
3485hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3486 struct wireless_dev *wdev,
3487 const void *data,
3488 int data_len)
3489{
3490 int ret;
3491
3492 cds_ssr_protect(__func__);
3493 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3494 cds_ssr_unprotect(__func__);
3495
3496 return ret;
3497}
3498
3499/*
3500 * undef short names defined for get station command
3501 * used by __wlan_hdd_cfg80211_get_station_cmd()
3502 */
3503#undef STATION_INVALID
3504#undef STATION_INFO
3505#undef STATION_ASSOC_FAIL_REASON
3506#undef STATION_MAX
3507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3509/**
3510 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3511 * @wiphy: pointer to wireless wiphy structure.
3512 * @wdev: pointer to wireless_dev structure.
3513 * @data: Pointer to the Key data
3514 * @data_len:Length of the data passed
3515 *
3516 * This is called when wlan driver needs to save the keys received via
3517 * vendor specific command.
3518 *
3519 * Return: Return the Success or Failure code.
3520 */
3521static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3522 struct wireless_dev *wdev,
3523 const void *data, int data_len)
3524{
3525 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3526 struct net_device *dev = wdev->netdev;
3527 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3528 hdd_context_t *hdd_ctx_ptr;
3529 int status;
3530
Jeff Johnson1f61b612016-02-12 16:28:33 -08003531 ENTER_DEV(dev);
3532
Anurag Chouhan6d760662016-02-20 16:05:43 +05303533 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534 hdd_err("Command not allowed in FTM mode");
3535 return -EPERM;
3536 }
3537
3538 if ((data == NULL) || (data_len == 0) ||
3539 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003540 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 return -EINVAL;
3542 }
3543
3544 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3545 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003546 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003547 return -EINVAL;
3548 }
3549
3550 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303551 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003553 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3554 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003555 true,
3556 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303557 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3558 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3560 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3561 return 0;
3562}
3563
3564/**
3565 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3566 * @wiphy: pointer to wireless wiphy structure.
3567 * @wdev: pointer to wireless_dev structure.
3568 * @data: Pointer to the Key data
3569 * @data_len:Length of the data passed
3570 *
3571 * This is called when wlan driver needs to save the keys received via
3572 * vendor specific command.
3573 *
3574 * Return: Return the Success or Failure code.
3575 */
3576static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3577 struct wireless_dev *wdev,
3578 const void *data, int data_len)
3579{
3580 int ret;
3581
3582 cds_ssr_protect(__func__);
3583 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3584 cds_ssr_unprotect(__func__);
3585
3586 return ret;
3587}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003588#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589
3590static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3591 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3592 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3593 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003594 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595};
3596
3597/**
3598 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3599 * @wiphy: pointer to wireless wiphy structure.
3600 * @wdev: pointer to wireless_dev structure.
3601 * @data: Pointer to the data to be passed via vendor interface
3602 * @data_len:Length of the data to be passed
3603 *
3604 * This is called when wlan driver needs to send wifi driver related info
3605 * (driver/fw version) to the user space application upon request.
3606 *
3607 * Return: Return the Success or Failure code.
3608 */
3609static int
3610__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3611 struct wireless_dev *wdev,
3612 const void *data, int data_len)
3613{
3614 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3615 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003616 tSirVersionString driver_version;
3617 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003619 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003620 struct sk_buff *reply_skb;
3621 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622
Jeff Johnson1f61b612016-02-12 16:28:33 -08003623 ENTER_DEV(wdev->netdev);
3624
Anurag Chouhan6d760662016-02-20 16:05:43 +05303625 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 hdd_err("Command not allowed in FTM mode");
3627 return -EPERM;
3628 }
3629
3630 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303631 if (status)
3632 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633
3634 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3635 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003636 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637 return -EINVAL;
3638 }
3639
3640 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003641 hdd_err("Rcvd req for Driver version");
3642 strlcpy(driver_version, QWLAN_VERSIONSTR,
3643 sizeof(driver_version));
3644 skb_len += strlen(driver_version) + 1;
3645 count++;
3646 }
3647
3648 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3649 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3651 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003652 snprintf(firmware_version, sizeof(firmware_version),
3653 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3654 skb_len += strlen(firmware_version) + 1;
3655 count++;
3656 }
3657
3658 if (count == 0) {
3659 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003660 return -EINVAL;
3661 }
3662
Ryan Hsu7ac88852016-04-28 10:20:34 -07003663 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3664 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3665
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003667 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003668 return -ENOMEM;
3669 }
3670
Ryan Hsu7ac88852016-04-28 10:20:34 -07003671 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3672 if (nla_put_string(reply_skb,
3673 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3674 driver_version))
3675 goto error_nla_fail;
3676 }
3677
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303678 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003679 if (nla_put_string(reply_skb,
3680 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3681 firmware_version))
3682 goto error_nla_fail;
3683 }
3684
3685 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3686 if (nla_put_u32(reply_skb,
3687 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3688 hdd_ctx->radio_index))
3689 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 }
3691
3692 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003693
3694error_nla_fail:
3695 hdd_err("nla put fail");
3696 kfree_skb(reply_skb);
3697 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698}
3699
3700/**
3701 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3702 * @wiphy: pointer to wireless wiphy structure.
3703 * @wdev: pointer to wireless_dev structure.
3704 * @data: Pointer to the data to be passed via vendor interface
3705 * @data_len:Length of the data to be passed
3706 *
3707 * This is called when wlan driver needs to send wifi driver related info
3708 * (driver/fw version) to the user space application upon request.
3709 *
3710 * Return: Return the Success or Failure code.
3711 */
3712static int
3713wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3714 struct wireless_dev *wdev,
3715 const void *data, int data_len)
3716{
3717 int ret;
3718
3719 cds_ssr_protect(__func__);
3720 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3721 cds_ssr_unprotect(__func__);
3722
3723 return ret;
3724}
3725
3726/**
3727 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3728 * @wiphy: pointer to wireless wiphy structure.
3729 * @wdev: pointer to wireless_dev structure.
3730 * @data: Pointer to the data to be passed via vendor interface
3731 * @data_len:Length of the data to be passed
3732 *
3733 * This is called by userspace to know the supported logger features
3734 *
3735 * Return: Return the Success or Failure code.
3736 */
3737static int
3738__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3739 struct wireless_dev *wdev,
3740 const void *data, int data_len)
3741{
3742 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3743 int status;
3744 uint32_t features;
3745 struct sk_buff *reply_skb = NULL;
3746
Jeff Johnson1f61b612016-02-12 16:28:33 -08003747 ENTER_DEV(wdev->netdev);
3748
Anurag Chouhan6d760662016-02-20 16:05:43 +05303749 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750 hdd_err("Command not allowed in FTM mode");
3751 return -EPERM;
3752 }
3753
3754 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303755 if (status)
3756 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757
3758 features = 0;
3759
3760 if (hdd_is_memdump_supported())
3761 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3762 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3763 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3764 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3765
3766 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3767 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3768 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003769 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770 return -ENOMEM;
3771 }
3772
Jeff Johnson020db452016-06-29 14:37:26 -07003773 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3775 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003776 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777 kfree_skb(reply_skb);
3778 return -EINVAL;
3779 }
3780
3781 return cfg80211_vendor_cmd_reply(reply_skb);
3782}
3783
3784/**
3785 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3786 * @wiphy: pointer to wireless wiphy structure.
3787 * @wdev: pointer to wireless_dev structure.
3788 * @data: Pointer to the data to be passed via vendor interface
3789 * @data_len:Length of the data to be passed
3790 *
3791 * This is called by userspace to know the supported logger features
3792 *
3793 * Return: Return the Success or Failure code.
3794 */
3795static int
3796wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3797 struct wireless_dev *wdev,
3798 const void *data, int data_len)
3799{
3800 int ret;
3801
3802 cds_ssr_protect(__func__);
3803 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3804 data, data_len);
3805 cds_ssr_unprotect(__func__);
3806
3807 return ret;
3808}
3809
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003810#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811/**
3812 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05303813 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814 * @bssid: pointer to bssid of roamed AP.
3815 * @req_rsn_ie: Pointer to request RSN IE
3816 * @req_rsn_len: Length of the request RSN IE
3817 * @rsp_rsn_ie: Pointer to response RSN IE
3818 * @rsp_rsn_len: Length of the response RSN IE
3819 * @roam_info_ptr: Pointer to the roaming related information
3820 *
3821 * This is called when wlan driver needs to send the roaming and
3822 * authorization information after roaming.
3823 *
3824 * The information that would be sent is the request RSN IE, response
3825 * RSN IE and BSSID of the newly roamed AP.
3826 *
3827 * If the Authorized status is authenticated, then additional parameters
3828 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3829 * supplicant.
3830 *
3831 * The supplicant upon receiving this event would ignore the legacy
3832 * cfg80211_roamed call and use the entire information from this event.
3833 * The cfg80211_roamed should still co-exist since the kernel will
3834 * make use of the parameters even if the supplicant ignores it.
3835 *
3836 * Return: Return the Success or Failure code.
3837 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05303838int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3840 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3841{
Prakash Dhavali989127d2016-11-29 14:56:44 +05303842 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003844 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 ENTER();
3846
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303847 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003848 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003850 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003851 !roam_info_ptr->roamSynchInProgress)
3852 return 0;
3853
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003854 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05303855 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3857 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3858 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003859 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3861 GFP_KERNEL);
3862
3863 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003864 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865 return -EINVAL;
3866 }
3867
3868 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3869 ETH_ALEN, bssid) ||
3870 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3871 req_rsn_len, req_rsn_ie) ||
3872 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3873 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003874 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003875 goto nla_put_failure;
3876 }
Jeff Johnson020db452016-06-29 14:37:26 -07003877 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 if (roam_info_ptr->synchAuthStatus ==
3879 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003880 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003881 if (nla_put_u8(skb,
3882 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3883 hdd_err("nla put fail");
3884 goto nla_put_failure;
3885 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003886 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3887 /* if FT or CCKM connection: dont send replay counter */
3888 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3889 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3890 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3891 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3892 nla_put(skb,
3893 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3894 SIR_REPLAY_CTR_LEN,
3895 roam_info_ptr->replay_ctr)) {
3896 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003897 hdd_err("failed to send replay counter.");
3898 goto nla_put_failure;
3899 }
3900 if (nla_put(skb,
3901 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3902 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3903 nla_put(skb,
3904 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3905 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3906 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 goto nla_put_failure;
3908 }
3909 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003910 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003911 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3912 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003913 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003914 goto nla_put_failure;
3915 }
3916 }
3917
Jeff Johnson020db452016-06-29 14:37:26 -07003918 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003919 roam_info_ptr->subnet_change_status);
3920
3921 /*
3922 * Add subnet change status if subnet has changed
3923 * 0 = unchanged
3924 * 1 = changed
3925 * 2 = unknown
3926 */
3927 if (roam_info_ptr->subnet_change_status) {
3928 if (nla_put_u8(skb,
3929 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3930 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003931 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003932 goto nla_put_failure;
3933 }
3934 }
3935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936 cfg80211_vendor_event(skb, GFP_KERNEL);
3937 return 0;
3938
3939nla_put_failure:
3940 kfree_skb(skb);
3941 return -EINVAL;
3942}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003943#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944
3945static const struct nla_policy
3946wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3947
3948 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3949 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3950 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303951 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303952 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3953 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003954 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3955 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3956 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3957 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3958 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303959 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960};
3961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303963 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3964 *
3965 * @adapter: Pointer to HDD adapter
3966 * @ie_data: Pointer to Scan IEs buffer
3967 * @ie_len: Length of Scan IEs
3968 *
3969 * Return: 0 on success; error number otherwise
3970 */
3971static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3972 uint8_t *ie_data, uint8_t ie_len)
3973{
3974 hdd_scaninfo_t *scan_info = NULL;
3975 scan_info = &adapter->scan_info;
3976
3977 if (scan_info->default_scan_ies) {
3978 qdf_mem_free(scan_info->default_scan_ies);
3979 scan_info->default_scan_ies = NULL;
3980 }
3981
3982 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3983 if (!scan_info->default_scan_ies)
3984 return -ENOMEM;
3985
3986 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3987 scan_info->default_scan_ies_len = ie_len;
3988 return 0;
3989}
3990
3991/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3993 * vendor command
3994 *
3995 * @wiphy: wiphy device pointer
3996 * @wdev: wireless device pointer
3997 * @data: Vendor command data buffer
3998 * @data_len: Buffer length
3999 *
4000 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4001 *
4002 * Return: Error code.
4003 */
4004static int
4005__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4006 struct wireless_dev *wdev,
4007 const void *data,
4008 int data_len)
4009{
4010 struct net_device *dev = wdev->netdev;
4011 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4012 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4013 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4014 int ret_val = 0;
4015 u32 modulated_dtim;
4016 u16 stats_avg_factor;
4017 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304018 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004019 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004020 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304021 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304022 int attr_len;
4023 int access_policy = 0;
4024 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4025 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304026 uint16_t scan_ie_len = 0;
4027 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304028 struct sir_set_tx_rx_aggregation_size request;
4029 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004030 uint8_t retry, delay;
4031 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304032 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304033
Jeff Johnson1f61b612016-02-12 16:28:33 -08004034 ENTER_DEV(dev);
4035
Anurag Chouhan6d760662016-02-20 16:05:43 +05304036 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 hdd_err("Command not allowed in FTM mode");
4038 return -EPERM;
4039 }
4040
4041 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304042 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004044
4045 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4046 data, data_len,
4047 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004048 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 return -EINVAL;
4050 }
4051
Krunal Sonie3531942016-04-12 17:43:53 -07004052 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4053 ftm_capab = nla_get_u32(tb[
4054 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4055 hdd_ctx->config->fine_time_meas_cap =
4056 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4057 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304058 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004059 hdd_ctx->config->fine_time_meas_cap);
4060 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4061 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4062 hdd_ctx->config->fine_time_meas_cap);
4063 }
4064
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4066 modulated_dtim = nla_get_u32(
4067 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4068
4069 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4070 adapter->sessionId,
4071 modulated_dtim);
4072
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304073 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004074 ret_val = -EPERM;
4075 }
4076
Kapil Gupta6213c012016-09-02 19:39:09 +05304077 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4078 qpower = nla_get_u8(
4079 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4080 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4081 ret_val = -EINVAL;
4082 }
4083
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4085 stats_avg_factor = nla_get_u16(
4086 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4087 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4088 adapter->sessionId,
4089 stats_avg_factor);
4090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304091 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 ret_val = -EPERM;
4093 }
4094
4095
4096 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4097 guard_time = nla_get_u32(
4098 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4099 status = sme_configure_guard_time(hdd_ctx->hHal,
4100 adapter->sessionId,
4101 guard_time);
4102
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304103 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 ret_val = -EPERM;
4105 }
4106
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304107 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4108 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4109 attr_len = nla_len(
4110 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4111 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4112 hdd_info("Invalid value. attr_len %d",
4113 attr_len);
4114 return -EINVAL;
4115 }
4116
4117 nla_memcpy(&vendor_ie,
4118 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4119 attr_len);
4120 vendor_ie_present = true;
4121 hdd_info("Access policy vendor ie present.attr_len %d",
4122 attr_len);
4123 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4124 &vendor_ie[0], attr_len);
4125 }
4126
4127 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4128 access_policy = (int) nla_get_u32(
4129 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4130 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4131 (access_policy >
4132 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4133 hdd_info("Invalid value. access_policy %d",
4134 access_policy);
4135 return -EINVAL;
4136 }
4137 access_policy_present = true;
4138 hdd_info("Access policy present. access_policy %d",
4139 access_policy);
4140 }
4141
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004142 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4143 retry = nla_get_u8(tb[
4144 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4145 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4146 CFG_NON_AGG_RETRY_MAX : retry;
4147 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4148 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4149 retry, PDEV_CMD);
4150 }
4151
4152 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4153 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4154 retry = retry > CFG_AGG_RETRY_MAX ?
4155 CFG_AGG_RETRY_MAX : retry;
4156
4157 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4158 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4159 CFG_AGG_RETRY_MIN : retry;
4160 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4161 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4162 retry, PDEV_CMD);
4163 }
4164
4165 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4166 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4167 retry = retry > CFG_MGMT_RETRY_MAX ?
4168 CFG_MGMT_RETRY_MAX : retry;
4169 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4170 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4171 retry, PDEV_CMD);
4172 }
4173
4174 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4175 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4176 retry = retry > CFG_CTRL_RETRY_MAX ?
4177 CFG_CTRL_RETRY_MAX : retry;
4178 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4179 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4180 retry, PDEV_CMD);
4181 }
4182
4183 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4184 delay = nla_get_u8(tb[
4185 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4186 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4187 CFG_PROPAGATION_DELAY_MAX : delay;
4188 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4189 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4190 delay, PDEV_CMD);
4191 }
4192
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304193 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4194 tx_fail_count = nla_get_u32(
4195 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4196 if (tx_fail_count) {
4197 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4198 adapter->sessionId, tx_fail_count);
4199 if (QDF_STATUS_SUCCESS != status) {
4200 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4201 status);
4202 return -EINVAL;
4203 }
4204 }
4205 }
4206
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304207 if (vendor_ie_present && access_policy_present) {
4208 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4209 access_policy =
4210 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304211 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304212 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304213 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304214
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304215 hdd_info("calling sme_update_access_policy_vendor_ie");
4216 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4217 adapter->sessionId, &vendor_ie[0],
4218 access_policy);
4219 if (QDF_STATUS_SUCCESS != status) {
4220 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304221 return -EINVAL;
4222 }
4223 }
4224
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304225 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4226 set_value = nla_get_u8(
4227 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4228 hdd_info("set_value: %d", set_value);
4229 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4230 }
4231
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304232 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4233 scan_ie_len = nla_len(
4234 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4235 hdd_info("Received default scan IE of len %d session %d device mode %d",
4236 scan_ie_len, adapter->sessionId,
4237 adapter->device_mode);
4238 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4239 scan_ie = (uint8_t *) nla_data(tb
4240 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304241
4242 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4243 scan_ie_len))
4244 hdd_err("Failed to save default scan IEs");
4245
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304246 if (adapter->device_mode == QDF_STA_MODE) {
4247 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4248 adapter->sessionId, scan_ie,
4249 scan_ie_len);
4250 if (QDF_STATUS_SUCCESS != status)
4251 ret_val = -EPERM;
4252 }
4253 } else
4254 ret_val = -EPERM;
4255 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304256
4257 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4258 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4259 /* if one is specified, both must be specified */
4260 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4261 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4262 hdd_err("Both TX and RX MPDU Aggregation required");
4263 return -EINVAL;
4264 }
4265
4266 request.tx_aggregation_size = nla_get_u8(
4267 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4268 request.rx_aggregation_size = nla_get_u8(
4269 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4270 request.vdev_id = adapter->sessionId;
4271
4272 if (request.tx_aggregation_size >=
4273 CFG_TX_AGGREGATION_SIZE_MIN &&
4274 request.tx_aggregation_size <=
4275 CFG_TX_AGGREGATION_SIZE_MAX &&
4276 request.rx_aggregation_size >=
4277 CFG_RX_AGGREGATION_SIZE_MIN &&
4278 request.rx_aggregation_size <=
4279 CFG_RX_AGGREGATION_SIZE_MAX) {
4280 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4281 if (qdf_status != QDF_STATUS_SUCCESS) {
4282 hdd_err("failed to set aggr sizes err %d",
4283 qdf_status);
4284 ret_val = -EPERM;
4285 }
4286 } else {
4287 hdd_err("TX %d RX %d MPDU aggr size not in range",
4288 request.tx_aggregation_size,
4289 request.rx_aggregation_size);
4290 ret_val = -EINVAL;
4291 }
4292 }
4293
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304294 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4295 uint8_t ignore_assoc_disallowed;
4296
4297 ignore_assoc_disallowed
4298 = nla_get_u8(tb[
4299 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4300 hdd_info("Set ignore_assoc_disallowed value - %d",
4301 ignore_assoc_disallowed);
4302 if ((ignore_assoc_disallowed <
4303 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4304 (ignore_assoc_disallowed >
4305 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4306 return -EPERM;
4307
4308 sme_update_session_param(hdd_ctx->hHal,
4309 adapter->sessionId,
4310 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4311 ignore_assoc_disallowed);
4312 }
4313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004314 return ret_val;
4315}
4316
4317/**
4318 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4319 * vendor command
4320 *
4321 * @wiphy: wiphy device pointer
4322 * @wdev: wireless device pointer
4323 * @data: Vendor command data buffer
4324 * @data_len: Buffer length
4325 *
4326 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4327 *
4328 * Return: EOK or other error codes.
4329 */
4330static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4331 struct wireless_dev *wdev,
4332 const void *data,
4333 int data_len)
4334{
4335 int ret;
4336
4337 cds_ssr_protect(__func__);
4338 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4339 data, data_len);
4340 cds_ssr_unprotect(__func__);
4341
4342 return ret;
4343}
4344
4345static const struct
4346nla_policy
4347qca_wlan_vendor_wifi_logger_start_policy
4348[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4349 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4350 = {.type = NLA_U32 },
4351 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4352 = {.type = NLA_U32 },
4353 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4354 = {.type = NLA_U32 },
4355};
4356
4357/**
4358 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4359 * or disable the collection of packet statistics from the firmware
4360 * @wiphy: WIPHY structure pointer
4361 * @wdev: Wireless device structure pointer
4362 * @data: Pointer to the data received
4363 * @data_len: Length of the data received
4364 *
4365 * This function enables or disables the collection of packet statistics from
4366 * the firmware
4367 *
4368 * Return: 0 on success and errno on failure
4369 */
4370static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4371 struct wireless_dev *wdev,
4372 const void *data,
4373 int data_len)
4374{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304375 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4377 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4378 struct sir_wifi_start_log start_log;
4379
Jeff Johnson1f61b612016-02-12 16:28:33 -08004380 ENTER_DEV(wdev->netdev);
4381
Anurag Chouhan6d760662016-02-20 16:05:43 +05304382 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 hdd_err("Command not allowed in FTM mode");
4384 return -EPERM;
4385 }
4386
4387 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304388 if (status)
4389 return status;
4390
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391
4392 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4393 data, data_len,
4394 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004395 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396 return -EINVAL;
4397 }
4398
4399 /* Parse and fetch ring id */
4400 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004401 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004402 return -EINVAL;
4403 }
4404 start_log.ring_id = nla_get_u32(
4405 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004406 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407
4408 /* Parse and fetch verbose level */
4409 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004410 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004411 return -EINVAL;
4412 }
4413 start_log.verbose_level = nla_get_u32(
4414 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004415 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004416
4417 /* Parse and fetch flag */
4418 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004419 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004420 return -EINVAL;
4421 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304422 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304424 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304426 /* size is buff size which can be set using iwpriv command*/
4427 start_log.size = 0;
4428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004429 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4430
4431 if (start_log.ring_id == RING_ID_WAKELOCK) {
4432 /* Start/stop wakelock events */
4433 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4434 cds_set_wakelock_logging(true);
4435 else
4436 cds_set_wakelock_logging(false);
4437 return 0;
4438 }
4439
4440 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304441 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004442 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443 status);
4444 return -EINVAL;
4445 }
4446 return 0;
4447}
4448
4449/**
4450 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4451 * or disable the collection of packet statistics from the firmware
4452 * @wiphy: WIPHY structure pointer
4453 * @wdev: Wireless device structure pointer
4454 * @data: Pointer to the data received
4455 * @data_len: Length of the data received
4456 *
4457 * This function is used to enable or disable the collection of packet
4458 * statistics from the firmware
4459 *
4460 * Return: 0 on success and errno on failure
4461 */
4462static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4463 struct wireless_dev *wdev,
4464 const void *data,
4465 int data_len)
4466{
4467 int ret = 0;
4468
4469 cds_ssr_protect(__func__);
4470 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4471 wdev, data, data_len);
4472 cds_ssr_unprotect(__func__);
4473
4474 return ret;
4475}
4476
4477static const struct
4478nla_policy
4479qca_wlan_vendor_wifi_logger_get_ring_data_policy
4480[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4481 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4482 = {.type = NLA_U32 },
4483};
4484
4485/**
4486 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4487 * @wiphy: WIPHY structure pointer
4488 * @wdev: Wireless device structure pointer
4489 * @data: Pointer to the data received
4490 * @data_len: Length of the data received
4491 *
4492 * This function is used to flush or retrieve the per packet statistics from
4493 * the driver
4494 *
4495 * Return: 0 on success and errno on failure
4496 */
4497static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4498 struct wireless_dev *wdev,
4499 const void *data,
4500 int data_len)
4501{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304502 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 uint32_t ring_id;
4504 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4505 struct nlattr *tb
4506 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4507
Jeff Johnson1f61b612016-02-12 16:28:33 -08004508 ENTER_DEV(wdev->netdev);
4509
Anurag Chouhan6d760662016-02-20 16:05:43 +05304510 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004511 hdd_err("Command not allowed in FTM mode");
4512 return -EPERM;
4513 }
4514
4515 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304516 if (status)
4517 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004518
4519 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4520 data, data_len,
4521 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004522 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 return -EINVAL;
4524 }
4525
4526 /* Parse and fetch ring id */
4527 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004528 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 return -EINVAL;
4530 }
4531
4532 ring_id = nla_get_u32(
4533 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4534
4535 if (ring_id == RING_ID_PER_PACKET_STATS) {
4536 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004537 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304538 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4539 /*
4540 * As part of DRIVER ring ID, flush both driver and fw logs.
4541 * For other Ring ID's driver doesn't have any rings to flush
4542 */
4543 hdd_notice("Bug report triggered by framework");
4544
4545 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4546 WLAN_LOG_INDICATOR_FRAMEWORK,
4547 WLAN_LOG_REASON_CODE_UNUSED,
4548 true, false);
4549 if (QDF_STATUS_SUCCESS != status) {
4550 hdd_err("Failed to trigger bug report");
4551 return -EINVAL;
4552 }
4553 } else {
4554 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4555 WLAN_LOG_INDICATOR_FRAMEWORK,
4556 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 return 0;
4559}
4560
4561/**
4562 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4563 * @wiphy: WIPHY structure pointer
4564 * @wdev: Wireless device structure pointer
4565 * @data: Pointer to the data received
4566 * @data_len: Length of the data received
4567 *
4568 * This function is used to flush or retrieve the per packet statistics from
4569 * the driver
4570 *
4571 * Return: 0 on success and errno on failure
4572 */
4573static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4574 struct wireless_dev *wdev,
4575 const void *data,
4576 int data_len)
4577{
4578 int ret = 0;
4579
4580 cds_ssr_protect(__func__);
4581 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4582 wdev, data, data_len);
4583 cds_ssr_unprotect(__func__);
4584
4585 return ret;
4586}
4587
4588#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4589/**
4590 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4591 * @hdd_ctx: HDD context
4592 * @request_id: [input] request id
4593 * @pattern_id: [output] pattern id
4594 *
4595 * This function loops through request id to pattern id array
4596 * if the slot is available, store the request id and return pattern id
4597 * if entry exists, return the pattern id
4598 *
4599 * Return: 0 on success and errno on failure
4600 */
4601static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4602 uint32_t request_id,
4603 uint8_t *pattern_id)
4604{
4605 uint32_t i;
4606
4607 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4608 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4609 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4610 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4611 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4612 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4613 return 0;
4614 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4615 request_id) {
4616 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4617 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4618 return 0;
4619 }
4620 }
4621 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4622 return -EINVAL;
4623}
4624
4625/**
4626 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4627 * @hdd_ctx: HDD context
4628 * @request_id: [input] request id
4629 * @pattern_id: [output] pattern id
4630 *
4631 * This function loops through request id to pattern id array
4632 * reset request id to 0 (slot available again) and
4633 * return pattern id
4634 *
4635 * Return: 0 on success and errno on failure
4636 */
4637static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4638 uint32_t request_id,
4639 uint8_t *pattern_id)
4640{
4641 uint32_t i;
4642
4643 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4644 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4645 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4646 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4647 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4648 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4649 return 0;
4650 }
4651 }
4652 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4653 return -EINVAL;
4654}
4655
4656
4657/*
4658 * define short names for the global vendor params
4659 * used by __wlan_hdd_cfg80211_offloaded_packets()
4660 */
4661#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4662#define PARAM_REQUEST_ID \
4663 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4664#define PARAM_CONTROL \
4665 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4666#define PARAM_IP_PACKET \
4667 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4668#define PARAM_SRC_MAC_ADDR \
4669 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4670#define PARAM_DST_MAC_ADDR \
4671 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4672#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4673
4674/**
4675 * wlan_hdd_add_tx_ptrn() - add tx pattern
4676 * @adapter: adapter pointer
4677 * @hdd_ctx: hdd context
4678 * @tb: nl attributes
4679 *
4680 * This function reads the NL attributes and forms a AddTxPtrn message
4681 * posts it to SME.
4682 *
4683 */
4684static int
4685wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4686 struct nlattr **tb)
4687{
4688 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304689 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 uint32_t request_id, ret, len;
4691 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304692 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 uint16_t eth_type = htons(ETH_P_IP);
4694
4695 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004696 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 return -ENOTSUPP;
4698 }
4699
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304700 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004702 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 return -ENOMEM;
4704 }
4705
4706 /* Parse and fetch request Id */
4707 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004708 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004709 goto fail;
4710 }
4711
4712 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4713 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004714 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715 return -EINVAL;
4716 }
Jeff Johnson77848112016-06-29 14:52:06 -07004717 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718
4719 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004720 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 goto fail;
4722 }
4723 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004724 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004726 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 goto fail;
4728 }
4729
4730 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004731 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004732 goto fail;
4733 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004734 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304735 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004736 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004737 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738
Anurag Chouhanc5548422016-02-24 18:33:27 +05304739 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004740 &adapter->macAddressCurrent)) {
4741 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 goto fail;
4743 }
4744
4745 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004746 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004747 goto fail;
4748 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304749 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004750 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004751 MAC_ADDR_ARRAY(dst_addr.bytes));
4752
4753 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004754 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 goto fail;
4756 }
4757 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004758 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004759
4760 if (add_req->ucPtrnSize < 0 ||
4761 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4762 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004763 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 add_req->ucPtrnSize);
4765 goto fail;
4766 }
4767
4768 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304769 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304770 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304771 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304772 QDF_MAC_ADDR_SIZE);
4773 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304774 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775 len += 2;
4776
4777 /*
4778 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4779 * ------------------------------------------------------------
4780 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4781 * ------------------------------------------------------------
4782 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304783 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004784 nla_data(tb[PARAM_IP_PACKET]),
4785 add_req->ucPtrnSize);
4786 add_req->ucPtrnSize += len;
4787
4788 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4789 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004790 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004791 goto fail;
4792 }
4793 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004794 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004795
4796 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304797 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004798 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004799 goto fail;
4800 }
4801
4802 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304803 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 return 0;
4805
4806fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304807 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808 return -EINVAL;
4809}
4810
4811/**
4812 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4813 * @adapter: adapter pointer
4814 * @hdd_ctx: hdd context
4815 * @tb: nl attributes
4816 *
4817 * This function reads the NL attributes and forms a DelTxPtrn message
4818 * posts it to SME.
4819 *
4820 */
4821static int
4822wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4823 struct nlattr **tb)
4824{
4825 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304826 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004827 uint32_t request_id, ret;
4828 uint8_t pattern_id = 0;
4829
4830 /* Parse and fetch request Id */
4831 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004832 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833 return -EINVAL;
4834 }
4835 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4836 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004837 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 return -EINVAL;
4839 }
4840
4841 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4842 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004843 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004844 return -EINVAL;
4845 }
4846
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304847 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004849 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004850 return -ENOMEM;
4851 }
4852
Anurag Chouhanc5548422016-02-24 18:33:27 +05304853 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004854 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004855 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004856 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004857 request_id, del_req->ucPtrnId);
4858
4859 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304860 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004861 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 goto fail;
4863 }
4864
4865 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304866 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 return 0;
4868
4869fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304870 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871 return -EINVAL;
4872}
4873
4874
4875/**
4876 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4877 * @wiphy: Pointer to wireless phy
4878 * @wdev: Pointer to wireless device
4879 * @data: Pointer to data
4880 * @data_len: Data length
4881 *
4882 * Return: 0 on success, negative errno on failure
4883 */
4884static int
4885__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4886 struct wireless_dev *wdev,
4887 const void *data,
4888 int data_len)
4889{
4890 struct net_device *dev = wdev->netdev;
4891 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4892 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4893 struct nlattr *tb[PARAM_MAX + 1];
4894 uint8_t control;
4895 int ret;
4896 static const struct nla_policy policy[PARAM_MAX + 1] = {
4897 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4898 [PARAM_CONTROL] = { .type = NLA_U32 },
4899 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304900 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304902 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903 [PARAM_PERIOD] = { .type = NLA_U32 },
4904 };
4905
Jeff Johnson1f61b612016-02-12 16:28:33 -08004906 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907
Anurag Chouhan6d760662016-02-20 16:05:43 +05304908 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004909 hdd_err("Command not allowed in FTM mode");
4910 return -EPERM;
4911 }
4912
4913 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304914 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004915 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916
4917 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004918 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004919 return -ENOTSUPP;
4920 }
4921
4922 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004923 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924 return -EINVAL;
4925 }
4926
4927 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004928 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 return -EINVAL;
4930 }
4931 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004932 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004933
4934 if (control == WLAN_START_OFFLOADED_PACKETS)
4935 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4936 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4937 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4938 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004939 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940 return -EINVAL;
4941 }
4942}
4943
4944/*
4945 * done with short names for the global vendor params
4946 * used by __wlan_hdd_cfg80211_offloaded_packets()
4947 */
4948#undef PARAM_MAX
4949#undef PARAM_REQUEST_ID
4950#undef PARAM_CONTROL
4951#undef PARAM_IP_PACKET
4952#undef PARAM_SRC_MAC_ADDR
4953#undef PARAM_DST_MAC_ADDR
4954#undef PARAM_PERIOD
4955
4956/**
4957 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4958 * @wiphy: wiphy structure pointer
4959 * @wdev: Wireless device structure pointer
4960 * @data: Pointer to the data received
4961 * @data_len: Length of @data
4962 *
4963 * Return: 0 on success; errno on failure
4964 */
4965static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4966 struct wireless_dev *wdev,
4967 const void *data,
4968 int data_len)
4969{
4970 int ret = 0;
4971
4972 cds_ssr_protect(__func__);
4973 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4974 wdev, data, data_len);
4975 cds_ssr_unprotect(__func__);
4976
4977 return ret;
4978}
4979#endif
4980
4981/*
4982 * define short names for the global vendor params
4983 * used by __wlan_hdd_cfg80211_monitor_rssi()
4984 */
4985#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4986#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4987#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4988#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4989#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4990
4991/**
4992 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4993 * @wiphy: Pointer to wireless phy
4994 * @wdev: Pointer to wireless device
4995 * @data: Pointer to data
4996 * @data_len: Data length
4997 *
4998 * Return: 0 on success, negative errno on failure
4999 */
5000static int
5001__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5002 struct wireless_dev *wdev,
5003 const void *data,
5004 int data_len)
5005{
5006 struct net_device *dev = wdev->netdev;
5007 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5008 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5009 struct nlattr *tb[PARAM_MAX + 1];
5010 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305011 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012 int ret;
5013 uint32_t control;
5014 static const struct nla_policy policy[PARAM_MAX + 1] = {
5015 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5016 [PARAM_CONTROL] = { .type = NLA_U32 },
5017 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5018 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5019 };
5020
Jeff Johnson1f61b612016-02-12 16:28:33 -08005021 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005022
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305023 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5024 hdd_err("invalid session id: %d", adapter->sessionId);
5025 return -EINVAL;
5026 }
5027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305029 if (ret)
5030 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031
5032 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005033 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005034 return -ENOTSUPP;
5035 }
5036
5037 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005038 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039 return -EINVAL;
5040 }
5041
5042 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005043 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005044 return -EINVAL;
5045 }
5046
5047 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005048 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005049 return -EINVAL;
5050 }
5051
5052 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5053 req.session_id = adapter->sessionId;
5054 control = nla_get_u32(tb[PARAM_CONTROL]);
5055
5056 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5057 req.control = true;
5058 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005059 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005060 return -EINVAL;
5061 }
5062
5063 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005064 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065 return -EINVAL;
5066 }
5067
5068 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5069 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5070
5071 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005072 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005073 req.min_rssi, req.max_rssi);
5074 return -EINVAL;
5075 }
Jeff Johnson77848112016-06-29 14:52:06 -07005076 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005077 req.min_rssi, req.max_rssi);
5078
5079 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5080 req.control = false;
5081 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005082 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005083 return -EINVAL;
5084 }
Jeff Johnson77848112016-06-29 14:52:06 -07005085 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005086 req.request_id, req.session_id, req.control);
5087
5088 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305089 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005090 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005091 return -EINVAL;
5092 }
5093
5094 return 0;
5095}
5096
5097/*
5098 * done with short names for the global vendor params
5099 * used by __wlan_hdd_cfg80211_monitor_rssi()
5100 */
5101#undef PARAM_MAX
5102#undef PARAM_CONTROL
5103#undef PARAM_REQUEST_ID
5104#undef PARAM_MAX_RSSI
5105#undef PARAM_MIN_RSSI
5106
5107/**
5108 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5109 * @wiphy: wiphy structure pointer
5110 * @wdev: Wireless device structure pointer
5111 * @data: Pointer to the data received
5112 * @data_len: Length of @data
5113 *
5114 * Return: 0 on success; errno on failure
5115 */
5116static int
5117wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5118 const void *data, int data_len)
5119{
5120 int ret;
5121
5122 cds_ssr_protect(__func__);
5123 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5124 cds_ssr_unprotect(__func__);
5125
5126 return ret;
5127}
5128
5129/**
5130 * hdd_rssi_threshold_breached() - rssi breached NL event
5131 * @hddctx: HDD context
5132 * @data: rssi breached event data
5133 *
5134 * This function reads the rssi breached event %data and fill in the skb with
5135 * NL attributes and send up the NL event.
5136 *
5137 * Return: none
5138 */
5139void hdd_rssi_threshold_breached(void *hddctx,
5140 struct rssi_breach_event *data)
5141{
5142 hdd_context_t *hdd_ctx = hddctx;
5143 struct sk_buff *skb;
5144
5145 ENTER();
5146
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305147 if (wlan_hdd_validate_context(hdd_ctx))
5148 return;
5149 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005150 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005151 return;
5152 }
5153
5154 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5155 NULL,
5156 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5157 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5158 GFP_KERNEL);
5159
5160 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005161 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005162 return;
5163 }
5164
Jeff Johnson77848112016-06-29 14:52:06 -07005165 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005167 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5169
5170 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5171 data->request_id) ||
5172 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5173 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5174 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5175 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005176 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177 goto fail;
5178 }
5179
5180 cfg80211_vendor_event(skb, GFP_KERNEL);
5181 return;
5182
5183fail:
5184 kfree_skb(skb);
5185 return;
5186}
5187
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305188static const struct nla_policy
5189ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5190 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5191};
5192
5193/**
5194 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5195 * @wiphy: Pointer to wireless phy
5196 * @wdev: Pointer to wireless device
5197 * @data: Pointer to data
5198 * @data_len: Length of @data
5199 *
5200 * Return: 0 on success, negative errno on failure
5201 */
5202static int
5203__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5204 struct wireless_dev *wdev,
5205 const void *data, int data_len)
5206{
5207 int status;
5208 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5209 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005210 struct net_device *dev = wdev->netdev;
5211 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305212
5213 ENTER_DEV(wdev->netdev);
5214
5215 status = wlan_hdd_validate_context(pHddCtx);
5216 if (0 != status)
5217 return status;
5218 if (!pHddCtx->config->fhostNSOffload) {
5219 hdd_err("ND Offload not supported");
5220 return -EINVAL;
5221 }
5222
5223 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5224 (struct nlattr *)data,
5225 data_len, ns_offload_set_policy)) {
5226 hdd_err("nla_parse failed");
5227 return -EINVAL;
5228 }
5229
5230 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5231 hdd_err("ND Offload flag attribute not present");
5232 return -EINVAL;
5233 }
5234
5235 pHddCtx->ns_offload_enable =
5236 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5237
Dustin Brownd8279d22016-09-07 14:52:57 -07005238 /* update ns offload in case it is already enabled/disabled */
5239 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5240
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305241 return 0;
5242}
5243
5244/**
5245 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5246 * @wiphy: pointer to wireless wiphy structure.
5247 * @wdev: pointer to wireless_dev structure.
5248 * @data: Pointer to the data to be passed via vendor interface
5249 * @data_len:Length of the data to be passed
5250 *
5251 * Return: Return the Success or Failure code.
5252 */
5253static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5254 struct wireless_dev *wdev,
5255 const void *data, int data_len)
5256{
5257 int ret;
5258
5259 cds_ssr_protect(__func__);
5260 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5261 cds_ssr_unprotect(__func__);
5262
5263 return ret;
5264}
5265
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5267 * @wiphy: Pointer to wireless phy
5268 * @wdev: Pointer to wireless device
5269 * @data: Pointer to data
5270 * @data_len: Data length
5271 *
5272 * This function return the preferred frequency list generated by the policy
5273 * manager.
5274 *
5275 * Return: success or failure code
5276 */
5277static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5278 struct wireless_dev
5279 *wdev, const void *data,
5280 int data_len)
5281{
5282 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5283 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305284 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305285 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305287 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005288 enum cds_con_mode intf_mode;
5289 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5290 struct sk_buff *reply_skb;
5291
Jeff Johnson1f61b612016-02-12 16:28:33 -08005292 ENTER_DEV(wdev->netdev);
5293
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005294 ret = wlan_hdd_validate_context(hdd_ctx);
5295 if (ret)
5296 return -EINVAL;
5297
5298 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5299 data, data_len, NULL)) {
5300 hdd_err("Invalid ATTR");
5301 return -EINVAL;
5302 }
5303
5304 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5305 hdd_err("attr interface type failed");
5306 return -EINVAL;
5307 }
5308
5309 intf_mode = nla_get_u32(tb
5310 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5311
5312 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5313 hdd_err("Invalid interface type");
5314 return -EINVAL;
5315 }
5316
5317 hdd_debug("Userspace requested pref freq list");
5318
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305319 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5320 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305321 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 hdd_err("Get pcl failed");
5323 return -EINVAL;
5324 }
5325
5326 /* convert channel number to frequency */
5327 for (i = 0; i < pcl_len; i++) {
5328 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5329 freq_list[i] =
5330 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005331 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 else
5333 freq_list[i] =
5334 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005335 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 }
5337
5338 /* send the freq_list back to supplicant */
5339 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5340 sizeof(u32) *
5341 pcl_len +
5342 NLMSG_HDRLEN);
5343
5344 if (!reply_skb) {
5345 hdd_err("Allocate reply_skb failed");
5346 return -EINVAL;
5347 }
5348
5349 if (nla_put_u32(reply_skb,
5350 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5351 intf_mode) ||
5352 nla_put(reply_skb,
5353 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5354 sizeof(uint32_t) * pcl_len,
5355 freq_list)) {
5356 hdd_err("nla put fail");
5357 kfree_skb(reply_skb);
5358 return -EINVAL;
5359 }
5360
5361 return cfg80211_vendor_cmd_reply(reply_skb);
5362}
5363
5364/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5365 * @wiphy: Pointer to wireless phy
5366 * @wdev: Pointer to wireless device
5367 * @data: Pointer to data
5368 * @data_len: Data length
5369 *
5370 * This function return the preferred frequency list generated by the policy
5371 * manager.
5372 *
5373 * Return: success or failure code
5374 */
5375static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5376 struct wireless_dev
5377 *wdev, const void *data,
5378 int data_len)
5379{
5380 int ret = 0;
5381
5382 cds_ssr_protect(__func__);
5383 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5384 data, data_len);
5385 cds_ssr_unprotect(__func__);
5386
5387 return ret;
5388}
5389
5390/**
5391 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5392 * @wiphy: Pointer to wireless phy
5393 * @wdev: Pointer to wireless device
5394 * @data: Pointer to data
5395 * @data_len: Data length
5396 *
5397 * Return: 0 on success, negative errno on failure
5398 */
5399static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5400 struct wireless_dev *wdev,
5401 const void *data,
5402 int data_len)
5403{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305404 struct net_device *ndev = wdev->netdev;
5405 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005406 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5407 int ret = 0;
5408 enum cds_con_mode intf_mode;
5409 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5410 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411
Jeff Johnson1f61b612016-02-12 16:28:33 -08005412 ENTER_DEV(ndev);
5413
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414 ret = wlan_hdd_validate_context(hdd_ctx);
5415 if (ret)
5416 return ret;
5417
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5419 data, data_len, NULL)) {
5420 hdd_err("Invalid ATTR");
5421 return -EINVAL;
5422 }
5423
5424 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5425 hdd_err("attr interface type failed");
5426 return -EINVAL;
5427 }
5428
5429 intf_mode = nla_get_u32(tb
5430 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5431
5432 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5433 hdd_err("Invalid interface type");
5434 return -EINVAL;
5435 }
5436
5437 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5438 hdd_err("attr probable freq failed");
5439 return -EINVAL;
5440 }
5441
5442 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5443 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5444
5445 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005446 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 channel_hint, HW_MODE_20_MHZ)) {
5448 hdd_err("Set channel hint failed due to concurrency check");
5449 return -EINVAL;
5450 }
5451
Krunal Soni09e55032016-06-07 10:06:55 -07005452 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5453 hdd_warn("Remain On Channel Pending");
5454
Krunal Soni3091bcc2016-06-23 12:28:21 -07005455 ret = qdf_reset_connection_update();
5456 if (!QDF_IS_STATUS_SUCCESS(ret))
5457 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458
Krunal Soni3091bcc2016-06-23 12:28:21 -07005459 ret = cds_current_connections_update(adapter->sessionId,
5460 channel_hint,
5461 SIR_UPDATE_REASON_SET_OPER_CHAN);
5462 if (QDF_STATUS_E_FAILURE == ret) {
5463 /* return in the failure case */
5464 hdd_err("ERROR: connections update failed!!");
5465 return -EINVAL;
5466 }
5467
5468 if (QDF_STATUS_SUCCESS == ret) {
5469 /*
5470 * Success is the only case for which we expect hw mode
5471 * change to take place, hence we need to wait.
5472 * For any other return value it should be a pass
5473 * through
5474 */
5475 ret = qdf_wait_for_connection_update();
5476 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5477 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005478 return -EINVAL;
5479 }
5480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481 }
5482
5483 return 0;
5484}
5485
5486/**
5487 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5488 * @wiphy: Pointer to wireless phy
5489 * @wdev: Pointer to wireless device
5490 * @data: Pointer to data
5491 * @data_len: Data length
5492 *
5493 * Return: 0 on success, negative errno on failure
5494 */
5495static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5496 struct wireless_dev *wdev,
5497 const void *data,
5498 int data_len)
5499{
5500 int ret = 0;
5501
5502 cds_ssr_protect(__func__);
5503 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5504 data, data_len);
5505 cds_ssr_unprotect(__func__);
5506
5507 return ret;
5508}
5509
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305510static const struct
5511nla_policy
5512qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5513 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5514};
5515
5516/**
5517 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5518 * @wiphy: WIPHY structure pointer
5519 * @wdev: Wireless device structure pointer
5520 * @data: Pointer to the data received
5521 * @data_len: Length of the data received
5522 *
5523 * This function is used to get link properties like nss, rate flags and
5524 * operating frequency for the active connection with the given peer.
5525 *
5526 * Return: 0 on success and errno on failure
5527 */
5528static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5529 struct wireless_dev *wdev,
5530 const void *data,
5531 int data_len)
5532{
5533 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5534 struct net_device *dev = wdev->netdev;
5535 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5536 hdd_station_ctx_t *hdd_sta_ctx;
5537 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305538 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305539 uint32_t sta_id;
5540 struct sk_buff *reply_skb;
5541 uint32_t rate_flags = 0;
5542 uint8_t nss;
5543 uint8_t final_rate_flags = 0;
5544 uint32_t freq;
5545
Jeff Johnson1f61b612016-02-12 16:28:33 -08005546 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305547
Anurag Chouhan6d760662016-02-20 16:05:43 +05305548 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305549 hdd_err("Command not allowed in FTM mode");
5550 return -EPERM;
5551 }
5552
5553 if (0 != wlan_hdd_validate_context(hdd_ctx))
5554 return -EINVAL;
5555
5556 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5557 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005558 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305559 return -EINVAL;
5560 }
5561
5562 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005563 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305564 adapter->device_mode);
5565 return -EINVAL;
5566 }
5567
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305568 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305569 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005570 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305571 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5572
Krunal Sonib4326f22016-03-10 13:05:51 -08005573 if (adapter->device_mode == QDF_STA_MODE ||
5574 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305575 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5576 if ((hdd_sta_ctx->conn_info.connState !=
5577 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305578 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305579 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005580 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305581 MAC_ADDR_ARRAY(peer_mac));
5582 return -EINVAL;
5583 }
5584
5585 nss = hdd_sta_ctx->conn_info.nss;
5586 freq = cds_chan_to_freq(
5587 hdd_sta_ctx->conn_info.operationChannel);
5588 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005589 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5590 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305591
5592 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5593 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305594 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305595 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305596 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305597 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305598 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305599 break;
5600 }
5601
5602 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005603 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305604 MAC_ADDR_ARRAY(peer_mac));
5605 return -EINVAL;
5606 }
5607
5608 nss = adapter->aStaInfo[sta_id].nss;
5609 freq = cds_chan_to_freq(
5610 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5611 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5612 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005613 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305614 MAC_ADDR_ARRAY(peer_mac));
5615 return -EINVAL;
5616 }
5617
5618 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5619 if (rate_flags & eHAL_TX_RATE_VHT80) {
5620 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005621#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305622 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005623#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305624 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5625 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005626#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305627 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005628#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305629 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5630 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5631 } else if (rate_flags &
5632 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5633 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005634#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305635 if (rate_flags & eHAL_TX_RATE_HT40)
5636 final_rate_flags |=
5637 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005638#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305639 }
5640
5641 if (rate_flags & eHAL_TX_RATE_SGI) {
5642 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5643 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5644 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5645 }
5646 }
5647
5648 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5649 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5650
5651 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005652 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305653 return -EINVAL;
5654 }
5655
5656 if (nla_put_u8(reply_skb,
5657 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5658 nss) ||
5659 nla_put_u8(reply_skb,
5660 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5661 final_rate_flags) ||
5662 nla_put_u32(reply_skb,
5663 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5664 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005665 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305666 kfree_skb(reply_skb);
5667 return -EINVAL;
5668 }
5669
5670 return cfg80211_vendor_cmd_reply(reply_skb);
5671}
5672
5673/**
5674 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5675 * properties.
5676 * @wiphy: WIPHY structure pointer
5677 * @wdev: Wireless device structure pointer
5678 * @data: Pointer to the data received
5679 * @data_len: Length of the data received
5680 *
5681 * This function is used to get link properties like nss, rate flags and
5682 * operating frequency for the active connection with the given peer.
5683 *
5684 * Return: 0 on success and errno on failure
5685 */
5686static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5687 struct wireless_dev *wdev,
5688 const void *data,
5689 int data_len)
5690{
5691 int ret = 0;
5692
5693 cds_ssr_protect(__func__);
5694 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5695 wdev, data, data_len);
5696 cds_ssr_unprotect(__func__);
5697
5698 return ret;
5699}
5700
Peng Xu278d0122015-09-24 16:34:17 -07005701static const struct
5702nla_policy
5703qca_wlan_vendor_ota_test_policy
5704[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5705 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5706};
5707
5708/**
5709 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5710 * @wiphy: Pointer to wireless phy
5711 * @wdev: Pointer to wireless device
5712 * @data: Pointer to data
5713 * @data_len: Data length
5714 *
5715 * Return: 0 on success, negative errno on failure
5716 */
5717static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5718 struct wireless_dev *wdev,
5719 const void *data,
5720 int data_len)
5721{
5722 struct net_device *dev = wdev->netdev;
5723 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5724 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5725 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5726 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5727 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305728 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005729 uint32_t current_roam_state;
5730
Jeff Johnson1f61b612016-02-12 16:28:33 -08005731 ENTER_DEV(dev);
5732
Anurag Chouhan6d760662016-02-20 16:05:43 +05305733 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005734 hdd_err("Command not allowed in FTM mode");
5735 return -EPERM;
5736 }
5737
5738 if (0 != wlan_hdd_validate_context(hdd_ctx))
5739 return -EINVAL;
5740
5741 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5742 data, data_len,
5743 qca_wlan_vendor_ota_test_policy)) {
5744 hdd_err("invalid attr");
5745 return -EINVAL;
5746 }
5747
5748 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5749 hdd_err("attr ota test failed");
5750 return -EINVAL;
5751 }
5752
5753 ota_enable = nla_get_u8(
5754 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5755
5756 hdd_info(" OTA test enable = %d", ota_enable);
5757 if (ota_enable != 1) {
5758 hdd_err("Invalid value, only enable test mode is supported!");
5759 return -EINVAL;
5760 }
5761
5762 current_roam_state =
5763 sme_get_current_roam_state(hal, adapter->sessionId);
5764 status = sme_stop_roaming(hal, adapter->sessionId,
5765 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305766 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005767 hdd_err("Enable/Disable roaming failed");
5768 return -EINVAL;
5769 }
5770
5771 status = sme_ps_enable_disable(hal, adapter->sessionId,
5772 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305773 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005774 hdd_err("Enable/Disable power save failed");
5775 /* restore previous roaming setting */
5776 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5777 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5778 status = sme_start_roaming(hal, adapter->sessionId,
5779 eCsrHddIssued);
5780 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5781 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5782 status = sme_stop_roaming(hal, adapter->sessionId,
5783 eCsrHddIssued);
5784
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305785 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005786 hdd_err("Restoring roaming state failed");
5787
5788 return -EINVAL;
5789 }
5790
5791
5792 return 0;
5793}
5794
5795/**
5796 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5797 * @wiphy: Pointer to wireless phy
5798 * @wdev: Pointer to wireless device
5799 * @data: Pointer to data
5800 * @data_len: Data length
5801 *
5802 * Return: 0 on success, negative errno on failure
5803 */
5804static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5805 struct wireless_dev *wdev,
5806 const void *data,
5807 int data_len)
5808{
5809 int ret = 0;
5810
5811 cds_ssr_protect(__func__);
5812 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5813 cds_ssr_unprotect(__func__);
5814
5815 return ret;
5816}
5817
Peng Xu4d67c8f2015-10-16 16:02:26 -07005818/**
5819 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5820 * @wiphy: Pointer to wireless phy
5821 * @wdev: Pointer to wireless device
5822 * @data: Pointer to data
5823 * @data_len: Data length
5824 *
5825 * Return: 0 on success, negative errno on failure
5826 */
5827static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5828 struct wireless_dev *wdev,
5829 const void *data,
5830 int data_len)
5831{
5832 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5833 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005834 hdd_adapter_t *adapter;
5835 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005836 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5837 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005838 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005839
Jeff Johnson1f61b612016-02-12 16:28:33 -08005840 ENTER_DEV(dev);
5841
Peng Xu4d67c8f2015-10-16 16:02:26 -07005842 ret = wlan_hdd_validate_context(hdd_ctx);
5843 if (ret)
5844 return ret;
5845
5846 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5847
5848 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5849 data, data_len, NULL)) {
5850 hdd_err("Invalid ATTR");
5851 return -EINVAL;
5852 }
5853
5854 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5855 hdd_err("attr tx power scale failed");
5856 return -EINVAL;
5857 }
5858
5859 scale_value = nla_get_u8(tb
5860 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5861
5862 if (scale_value > MAX_TXPOWER_SCALE) {
5863 hdd_err("Invalid tx power scale level");
5864 return -EINVAL;
5865 }
5866
Peng Xu62c8c432016-05-09 15:23:02 -07005867 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005868
Peng Xu62c8c432016-05-09 15:23:02 -07005869 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005870 hdd_err("Set tx power scale failed");
5871 return -EINVAL;
5872 }
5873
5874 return 0;
5875}
5876
5877/**
5878 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5879 * @wiphy: Pointer to wireless phy
5880 * @wdev: Pointer to wireless device
5881 * @data: Pointer to data
5882 * @data_len: Data length
5883 *
5884 * Return: 0 on success, negative errno on failure
5885 */
5886static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5887 struct wireless_dev *wdev,
5888 const void *data,
5889 int data_len)
5890{
Peng Xu62c8c432016-05-09 15:23:02 -07005891 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005892
5893 cds_ssr_protect(__func__);
5894 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5895 data, data_len);
5896 cds_ssr_unprotect(__func__);
5897
5898 return ret;
5899}
5900
5901/**
5902 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5903 * @wiphy: Pointer to wireless phy
5904 * @wdev: Pointer to wireless device
5905 * @data: Pointer to data
5906 * @data_len: Data length
5907 *
5908 * Return: 0 on success, negative errno on failure
5909 */
5910static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5911 struct wireless_dev *wdev,
5912 const void *data,
5913 int data_len)
5914{
5915 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5916 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005917 hdd_adapter_t *adapter;
5918 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005919 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5920 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005921 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005922
Jeff Johnson1f61b612016-02-12 16:28:33 -08005923 ENTER_DEV(dev);
5924
Peng Xu4d67c8f2015-10-16 16:02:26 -07005925 ret = wlan_hdd_validate_context(hdd_ctx);
5926 if (ret)
5927 return ret;
5928
5929 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5930
5931 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5932 data, data_len, NULL)) {
5933 hdd_err("Invalid ATTR");
5934 return -EINVAL;
5935 }
5936
5937 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5938 hdd_err("attr tx power decrease db value failed");
5939 return -EINVAL;
5940 }
5941
5942 scale_value = nla_get_u8(tb
5943 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5944
Peng Xu62c8c432016-05-09 15:23:02 -07005945 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5946 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005947
Peng Xu62c8c432016-05-09 15:23:02 -07005948 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005949 hdd_err("Set tx power decrease db failed");
5950 return -EINVAL;
5951 }
5952
5953 return 0;
5954}
5955
5956/**
5957 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5958 * @wiphy: Pointer to wireless phy
5959 * @wdev: Pointer to wireless device
5960 * @data: Pointer to data
5961 * @data_len: Data length
5962 *
5963 * Return: 0 on success, negative errno on failure
5964 */
5965static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5966 struct wireless_dev *wdev,
5967 const void *data,
5968 int data_len)
5969{
Peng Xu62c8c432016-05-09 15:23:02 -07005970 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005971
5972 cds_ssr_protect(__func__);
5973 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5974 data, data_len);
5975 cds_ssr_unprotect(__func__);
5976
5977 return ret;
5978}
Peng Xu8fdaa492016-06-22 10:20:47 -07005979
5980/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305981 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5982 * @wiphy: Pointer to wireless phy
5983 * @wdev: Pointer to wireless device
5984 * @data: Pointer to data
5985 * @data_len: Data length
5986 *
5987 * Processes the conditional channel switch request and invokes the helper
5988 * APIs to process the channel switch request.
5989 *
5990 * Return: 0 on success, negative errno on failure
5991 */
5992static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5993 struct wireless_dev *wdev,
5994 const void *data,
5995 int data_len)
5996{
5997 int ret;
5998 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5999 struct net_device *dev = wdev->netdev;
6000 hdd_adapter_t *adapter;
6001 struct nlattr
6002 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6003 uint32_t freq_len, i;
6004 uint32_t *freq;
6005 uint8_t chans[QDF_MAX_NUM_CHAN];
6006
6007 ENTER_DEV(dev);
6008
6009 ret = wlan_hdd_validate_context(hdd_ctx);
6010 if (ret)
6011 return ret;
6012
6013 if (!hdd_ctx->config->enableDFSMasterCap) {
6014 hdd_err("DFS master capability is not present in the driver");
6015 return -EINVAL;
6016 }
6017
6018 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6019 hdd_err("Command not allowed in FTM mode");
6020 return -EPERM;
6021 }
6022
6023 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6024 if (adapter->device_mode != QDF_SAP_MODE) {
6025 hdd_err("Invalid device mode %d", adapter->device_mode);
6026 return -EINVAL;
6027 }
6028
6029 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6030 data, data_len, NULL)) {
6031 hdd_err("Invalid ATTR");
6032 return -EINVAL;
6033 }
6034
6035 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6036 hdd_err("Frequency list is missing");
6037 return -EINVAL;
6038 }
6039
6040 freq_len = nla_len(
6041 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6042 sizeof(uint32_t);
6043
6044 if (freq_len > QDF_MAX_NUM_CHAN) {
6045 hdd_err("insufficient space to hold channels");
6046 return -ENOMEM;
6047 }
6048
6049 hdd_debug("freq_len=%d", freq_len);
6050
6051 freq = nla_data(
6052 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6053
6054
6055 for (i = 0; i < freq_len; i++) {
6056 if (freq[i] == 0)
6057 chans[i] = 0;
6058 else
6059 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6060
6061 hdd_debug("freq[%d]=%d", i, freq[i]);
6062 }
6063
6064 /*
6065 * The input frequency list from user space is designed to be a
6066 * priority based frequency list. This is only to accommodate any
6067 * future request. But, current requirement is only to perform CAC
6068 * on a single channel. So, the first entry from the list is picked.
6069 *
6070 * If channel is zero, any channel in the available outdoor regulatory
6071 * domain will be selected.
6072 */
6073 ret = wlan_hdd_request_pre_cac(chans[0]);
6074 if (ret) {
6075 hdd_err("pre cac request failed with reason:%d", ret);
6076 return ret;
6077 }
6078
6079 return 0;
6080}
6081
6082/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006083 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6084 * @wiphy: Pointer to wireless phy
6085 * @wdev: Pointer to wireless device
6086 * @data: Pointer to data
6087 * @data_len: Data length
6088 *
6089 * This function is to process the p2p listen offload start vendor
6090 * command. It parses the input parameters and invoke WMA API to
6091 * send the command to firmware.
6092 *
6093 * Return: 0 on success, negative errno on failure
6094 */
6095static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6096 struct wireless_dev *wdev,
6097 const void *data,
6098 int data_len)
6099{
6100 int ret;
6101 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6102 struct net_device *dev = wdev->netdev;
6103 hdd_adapter_t *adapter;
6104 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6105 struct sir_p2p_lo_start params;
6106 QDF_STATUS status;
6107
6108 ENTER_DEV(dev);
6109
6110 ret = wlan_hdd_validate_context(hdd_ctx);
6111 if (ret)
6112 return ret;
6113
6114 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6115 hdd_err("Command not allowed in FTM mode");
6116 return -EPERM;
6117 }
6118
6119 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6120 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6121 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6122 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6123 hdd_err("Invalid device mode %d", adapter->device_mode);
6124 return -EINVAL;
6125 }
6126
6127 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6128 data, data_len, NULL)) {
6129 hdd_err("Invalid ATTR");
6130 return -EINVAL;
6131 }
6132
6133 memset(&params, 0, sizeof(params));
6134
6135 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6136 params.ctl_flags = 1; /* set to default value */
6137 else
6138 params.ctl_flags = nla_get_u32(tb
6139 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6140
6141 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6142 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6143 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6144 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6145 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6146 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6147 hdd_err("Attribute parsing failed");
6148 return -EINVAL;
6149 }
6150
6151 params.vdev_id = adapter->sessionId;
6152 params.freq = nla_get_u32(tb
6153 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6154 if ((params.freq != 2412) && (params.freq != 2437) &&
6155 (params.freq != 2462)) {
6156 hdd_err("Invalid listening channel: %d", params.freq);
6157 return -EINVAL;
6158 }
6159
6160 params.period = nla_get_u32(tb
6161 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6162 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6163 hdd_err("Invalid period: %d", params.period);
6164 return -EINVAL;
6165 }
6166
6167 params.interval = nla_get_u32(tb
6168 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6169 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6170 hdd_err("Invalid interval: %d", params.interval);
6171 return -EINVAL;
6172 }
6173
6174 params.count = nla_get_u32(tb
6175 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006176 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006177 hdd_err("Invalid count: %d", params.count);
6178 return -EINVAL;
6179 }
6180
6181 params.device_types = nla_data(tb
6182 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6183 if (params.device_types == NULL) {
6184 hdd_err("Invalid device types");
6185 return -EINVAL;
6186 }
6187
6188 params.dev_types_len = nla_len(tb
6189 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6190 if (params.dev_types_len < 8) {
6191 hdd_err("Invalid device type length: %d", params.dev_types_len);
6192 return -EINVAL;
6193 }
6194
6195 params.probe_resp_tmplt = nla_data(tb
6196 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6197 if (params.probe_resp_tmplt == NULL) {
6198 hdd_err("Invalid probe response template");
6199 return -EINVAL;
6200 }
6201
6202 params.probe_resp_len = nla_len(tb
6203 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6204 if (params.probe_resp_len == 0) {
6205 hdd_err("Invalid probe resp template length: %d",
6206 params.probe_resp_len);
6207 return -EINVAL;
6208 }
6209
6210 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6211 params.freq, params.period, params.interval, params.count);
6212
6213 status = wma_p2p_lo_start(&params);
6214
6215 if (!QDF_IS_STATUS_SUCCESS(status)) {
6216 hdd_err("P2P LO start failed");
6217 return -EINVAL;
6218 }
6219
6220 return 0;
6221}
6222
6223
6224/**
6225 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6226 * @wiphy: Pointer to wireless phy
6227 * @wdev: Pointer to wireless device
6228 * @data: Pointer to data
6229 * @data_len: Data length
6230 *
6231 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6232 * to process p2p listen offload start vendor command.
6233 *
6234 * Return: 0 on success, negative errno on failure
6235 */
6236static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6237 struct wireless_dev *wdev,
6238 const void *data,
6239 int data_len)
6240{
6241 int ret = 0;
6242
6243 cds_ssr_protect(__func__);
6244 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6245 data, data_len);
6246 cds_ssr_unprotect(__func__);
6247
6248 return ret;
6249}
6250
6251/**
6252 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6253 * @wiphy: Pointer to wireless phy
6254 * @wdev: Pointer to wireless device
6255 * @data: Pointer to data
6256 * @data_len: Data length
6257 *
6258 * This function is to process the p2p listen offload stop vendor
6259 * command. It invokes WMA API to send command to firmware.
6260 *
6261 * Return: 0 on success, negative errno on failure
6262 */
6263static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6264 struct wireless_dev *wdev,
6265 const void *data,
6266 int data_len)
6267{
6268 QDF_STATUS status;
6269 hdd_adapter_t *adapter;
6270 struct net_device *dev = wdev->netdev;
6271
6272 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6273 hdd_err("Command not allowed in FTM mode");
6274 return -EPERM;
6275 }
6276
6277 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6278 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6279 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6280 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6281 hdd_err("Invalid device mode");
6282 return -EINVAL;
6283 }
6284
6285 status = wma_p2p_lo_stop(adapter->sessionId);
6286
6287 if (!QDF_IS_STATUS_SUCCESS(status)) {
6288 hdd_err("P2P LO stop failed");
6289 return -EINVAL;
6290 }
6291
6292 return 0;
6293}
6294
6295/**
6296 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6297 * @wiphy: Pointer to wireless phy
6298 * @wdev: Pointer to wireless device
6299 * @data: Pointer to data
6300 * @data_len: Data length
6301 *
6302 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6303 * to process p2p listen offload stop vendor command.
6304 *
6305 * Return: 0 on success, negative errno on failure
6306 */
6307static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6308 struct wireless_dev *wdev,
6309 const void *data,
6310 int data_len)
6311{
6312 int ret = 0;
6313
6314 cds_ssr_protect(__func__);
6315 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6316 data, data_len);
6317 cds_ssr_unprotect(__func__);
6318
6319 return ret;
6320}
6321
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306322/**
6323 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6324 * @wiphy: Pointer to wireless phy
6325 * @wdev: Pointer to wireless device
6326 * @data: Pointer to data
6327 * @data_len: Data length
6328 *
6329 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6330 * to process the conditional channel switch request.
6331 *
6332 * Return: 0 on success, negative errno on failure
6333 */
6334static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6335 struct wireless_dev *wdev,
6336 const void *data,
6337 int data_len)
6338{
6339 int ret;
6340
6341 cds_ssr_protect(__func__);
6342 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6343 data, data_len);
6344 cds_ssr_unprotect(__func__);
6345
6346 return ret;
6347}
6348
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306349/*
6350 * define short names for the global vendor params
6351 * used by __wlan_hdd_cfg80211_bpf_offload()
6352 */
6353#define BPF_INVALID \
6354 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6355#define BPF_SET_RESET \
6356 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6357#define BPF_VERSION \
6358 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6359#define BPF_FILTER_ID \
6360 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6361#define BPF_PACKET_SIZE \
6362 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6363#define BPF_CURRENT_OFFSET \
6364 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6365#define BPF_PROGRAM \
6366 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6367#define BPF_MAX \
6368 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006369
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306370static const struct nla_policy
6371wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6372 [BPF_SET_RESET] = {.type = NLA_U32},
6373 [BPF_VERSION] = {.type = NLA_U32},
6374 [BPF_FILTER_ID] = {.type = NLA_U32},
6375 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6376 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6377 [BPF_PROGRAM] = {.type = NLA_U8},
6378};
6379
6380/**
6381 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6382 * @hdd_context: hdd_context
6383 * @bpf_get_offload: struct for get offload
6384 *
6385 * This function receives the response/data from the lower layer and
6386 * checks to see if the thread is still waiting then post the results to
6387 * upper layer, if the request has timed out then ignore.
6388 *
6389 * Return: None
6390 */
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006391static void hdd_get_bpf_offload_cb(void *hdd_context,
6392 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306393{
6394 hdd_context_t *hdd_ctx = hdd_context;
6395 struct hdd_bpf_context *context;
6396
6397 ENTER();
6398
6399 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006400 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306401 data);
6402 return;
6403 }
6404
6405 spin_lock(&hdd_context_lock);
6406
6407 context = &bpf_context;
6408 /* The caller presumably timed out so there is nothing we can do */
6409 if (context->magic != BPF_CONTEXT_MAGIC) {
6410 spin_unlock(&hdd_context_lock);
6411 return;
6412 }
6413
6414 /* context is valid so caller is still waiting */
6415 /* paranoia: invalidate the magic */
6416 context->magic = 0;
6417
6418 context->capability_response = *data;
6419 complete(&context->completion);
6420
6421 spin_unlock(&hdd_context_lock);
6422
6423 return;
6424}
6425
6426/**
6427 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6428 * @hdd_context: hdd_context
6429 * @bpf_get_offload: struct for get offload
6430 *
6431 * Return: 0 on success, error number otherwise.
6432 */
6433static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6434 struct sir_bpf_get_offload *bpf_get_offload)
6435{
6436 struct sk_buff *skb;
6437 uint32_t nl_buf_len;
6438
6439 ENTER();
6440
6441 nl_buf_len = NLMSG_HDRLEN;
6442 nl_buf_len +=
6443 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6444 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6445
6446 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6447 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006448 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306449 return -ENOMEM;
6450 }
6451
Jeff Johnson77848112016-06-29 14:52:06 -07006452 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306453 bpf_get_offload->bpf_version,
6454 bpf_get_offload->max_bytes_for_bpf_inst);
6455
6456 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6457 bpf_get_offload->max_bytes_for_bpf_inst) ||
6458 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006459 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306460 goto nla_put_failure;
6461 }
6462
6463 cfg80211_vendor_cmd_reply(skb);
6464 EXIT();
6465 return 0;
6466
6467nla_put_failure:
6468 kfree_skb(skb);
6469 return -EINVAL;
6470}
6471
6472/**
6473 * hdd_get_bpf_offload - Get BPF offload Capabilities
6474 * @hdd_ctx: Hdd context
6475 *
6476 * Return: 0 on success, errno on failure
6477 */
6478static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6479{
6480 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006481 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306482 QDF_STATUS status;
6483 int ret;
6484
6485 ENTER();
6486
6487 spin_lock(&hdd_context_lock);
6488 context = &bpf_context;
6489 context->magic = BPF_CONTEXT_MAGIC;
6490 INIT_COMPLETION(context->completion);
6491 spin_unlock(&hdd_context_lock);
6492
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006493 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6494 hdd_get_bpf_offload_cb,
6495 hdd_ctx);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306496 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006497 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306498 return -EINVAL;
6499 }
6500 /* request was sent -- wait for the response */
6501 rc = wait_for_completion_timeout(&context->completion,
6502 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6503 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006504 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306505 spin_lock(&hdd_context_lock);
6506 context->magic = 0;
6507 spin_unlock(&hdd_context_lock);
6508
6509 return -ETIMEDOUT;
6510 }
6511 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6512 &bpf_context.capability_response);
6513 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006514 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306515
6516 EXIT();
6517 return ret;
6518}
6519
6520/**
6521 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6522 * @hdd_ctx: Hdd context
6523 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306524 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306525 *
6526 * Return: 0 on success; errno on failure
6527 */
6528static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6529 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306530 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306531{
6532 struct sir_bpf_set_offload *bpf_set_offload;
6533 QDF_STATUS status;
6534 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306535 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306536
6537 ENTER();
6538
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306539 if (adapter->device_mode == QDF_STA_MODE ||
6540 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6541 if (!hdd_conn_is_connected(
6542 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6543 hdd_err("Not in Connected state!");
6544 return -ENOTSUPP;
6545 }
6546 }
6547
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306548 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6549 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006550 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306551 return -ENOMEM;
6552 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306553
6554 /* Parse and fetch bpf packet size */
6555 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006556 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306557 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306558 goto fail;
6559 }
6560 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6561
6562 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006563 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306564 goto post_sme;
6565 }
6566
6567 /* Parse and fetch bpf program */
6568 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006569 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306570 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306571 goto fail;
6572 }
6573
6574 prog_len = nla_len(tb[BPF_PROGRAM]);
6575 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306576
6577 if (bpf_set_offload->program == NULL) {
6578 hdd_err("qdf_mem_malloc failed for bpf offload program");
6579 ret = -ENOMEM;
6580 goto fail;
6581 }
6582
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306583 bpf_set_offload->current_length = prog_len;
6584 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306585 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306586
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306587 hdd_info("BPF set instructions");
6588 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6589 bpf_set_offload->program, prog_len);
6590
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306591 /* Parse and fetch filter Id */
6592 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006593 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306594 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306595 goto fail;
6596 }
6597 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6598
6599 /* Parse and fetch current offset */
6600 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006601 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306602 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306603 goto fail;
6604 }
6605 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6606
6607post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006608 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 +05306609 bpf_set_offload->session_id,
6610 bpf_set_offload->version,
6611 bpf_set_offload->filter_id,
6612 bpf_set_offload->total_length,
6613 bpf_set_offload->current_length,
6614 bpf_set_offload->current_offset);
6615
6616 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6617 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006618 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306619 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306620 goto fail;
6621 }
6622 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306623
6624fail:
6625 if (bpf_set_offload->current_length)
6626 qdf_mem_free(bpf_set_offload->program);
6627 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306628 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306629}
6630
6631/**
6632 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6633 * @wiphy: wiphy structure pointer
6634 * @wdev: Wireless device structure pointer
6635 * @data: Pointer to the data received
6636 * @data_len: Length of @data
6637 *
6638 * Return: 0 on success; errno on failure
6639 */
6640static int
6641__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6642 struct wireless_dev *wdev,
6643 const void *data, int data_len)
6644{
6645 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6646 struct net_device *dev = wdev->netdev;
6647 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6648 struct nlattr *tb[BPF_MAX + 1];
6649 int ret_val, packet_filter_subcmd;
6650
6651 ENTER();
6652
6653 ret_val = wlan_hdd_validate_context(hdd_ctx);
6654 if (ret_val)
6655 return ret_val;
6656
6657 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006658 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306659 return -EINVAL;
6660 }
6661
6662 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006663 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306664 return -ENOTSUPP;
6665 }
6666
6667 if (nla_parse(tb, BPF_MAX, data, data_len,
6668 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006669 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306670 return -EINVAL;
6671 }
6672
6673 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006674 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306675 return -EINVAL;
6676 }
6677
6678 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6679
6680 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6681 return hdd_get_bpf_offload(hdd_ctx);
6682 else
6683 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306684 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306685}
6686
6687/**
6688 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6689 * @wiphy: wiphy structure pointer
6690 * @wdev: Wireless device structure pointer
6691 * @data: Pointer to the data received
6692 * @data_len: Length of @data
6693 *
6694 * Return: 0 on success; errno on failure
6695 */
6696
6697static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6698 struct wireless_dev *wdev,
6699 const void *data, int data_len)
6700{
6701 int ret;
6702
6703 cds_ssr_protect(__func__);
6704 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6705 cds_ssr_unprotect(__func__);
6706
6707 return ret;
6708}
6709
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306710/**
6711 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6712 * @pre_cac_adapter: AP adapter used for pre cac
6713 * @status: Status (true or false)
6714 * @handle: Global handle
6715 *
6716 * Sets the status of pre cac i.e., whether the pre cac is active or not
6717 *
6718 * Return: Zero on success, non-zero on failure
6719 */
6720static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6721 bool status, tHalHandle handle)
6722{
6723 QDF_STATUS ret;
6724
6725 ret = wlan_sap_set_pre_cac_status(
6726 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6727 if (QDF_IS_STATUS_ERROR(ret))
6728 return -EINVAL;
6729
6730 return 0;
6731}
6732
6733/**
6734 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6735 * @ap_adapter: AP adapter
6736 * @chan_before_pre_cac: Channel
6737 *
6738 * Saves the channel which the AP was beaconing on before moving to the pre
6739 * cac channel. If radar is detected on the pre cac channel, this saved
6740 * channel will be used for AP operations.
6741 *
6742 * Return: Zero on success, non-zero on failure
6743 */
6744static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6745 uint8_t chan_before_pre_cac)
6746{
6747 QDF_STATUS ret;
6748
6749 ret = wlan_sap_set_chan_before_pre_cac(
6750 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6751 if (QDF_IS_STATUS_ERROR(ret))
6752 return -EINVAL;
6753
6754 return 0;
6755}
6756
6757/**
6758 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6759 * @ap_adapter: AP adapter
6760 * @nol: Non-occupancy list
6761 * @nol_len: Length of NOL
6762 *
6763 * Get the NOL for SAP
6764 *
6765 * Return: Zero on success, non-zero on failure
6766 */
6767static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6768 uint32_t *nol_len)
6769{
6770 QDF_STATUS ret;
6771
6772 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6773 nol, nol_len);
6774 if (QDF_IS_STATUS_ERROR(ret))
6775 return -EINVAL;
6776
6777 return 0;
6778}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306779
6780/**
6781 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6782 * @hdd_ctx: HDD context
6783 * @ap_adapter: AP adapter
6784 * @channel: Channel requested by userspace
6785 * @pre_cac_chan: Pointer to the pre CAC channel
6786 *
6787 * Validates the channel provided by userspace. If user provided channel 0,
6788 * a valid outdoor channel must be selected from the regulatory channel.
6789 *
6790 * Return: Zero on success and non zero value on error
6791 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006792static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6793 hdd_adapter_t *ap_adapter,
6794 uint8_t channel,
6795 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306796{
6797 uint32_t i, j;
6798 QDF_STATUS status;
6799 int ret;
6800 uint8_t nol[QDF_MAX_NUM_CHAN];
6801 uint32_t nol_len = 0, weight_len = 0;
6802 bool found;
6803 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6804 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6805 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6806
6807 if (0 == channel) {
6808 /* Channel is not obtained from PCL because PCL may not have
6809 * the entire channel list. For example: if SAP is up on
6810 * channel 6 and PCL is queried for the next SAP interface,
6811 * if SCC is preferred, the PCL will contain only the channel
6812 * 6. But, we are in need of a DFS channel. So, going with the
6813 * first channel from the valid channel list.
6814 */
6815 status = cds_get_valid_chans(channel_list, &len);
6816 if (QDF_IS_STATUS_ERROR(status)) {
6817 hdd_err("Failed to get channel list");
6818 return -EINVAL;
6819 }
6820 cds_update_with_safe_channel_list(channel_list, &len,
6821 pcl_weights, weight_len);
6822 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6823 for (i = 0; i < len; i++) {
6824 found = false;
6825 for (j = 0; j < nol_len; j++) {
6826 if (channel_list[i] == nol[j]) {
6827 found = true;
6828 break;
6829 }
6830 }
6831 if (found)
6832 continue;
6833 if (CDS_IS_DFS_CH(channel_list[i])) {
6834 *pre_cac_chan = channel_list[i];
6835 break;
6836 }
6837 }
6838 if (*pre_cac_chan == 0) {
6839 hdd_err("unable to find outdoor channel");
6840 return -EINVAL;
6841 }
6842 } else {
6843 /* Only when driver selects a channel, check is done for
6844 * unnsafe and NOL channels. When user provides a fixed channel
6845 * the user is expected to take care of this.
6846 */
6847 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6848 !CDS_IS_DFS_CH(channel)) {
6849 hdd_err("Invalid channel for pre cac:%d", channel);
6850 return -EINVAL;
6851 } else {
6852 *pre_cac_chan = channel;
6853 }
6854 }
6855 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6856 return 0;
6857}
6858
6859/**
6860 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6861 * @channel: Channel option provided by userspace
6862 *
6863 * Sets the driver to the required hardware mode and start an adapater for
6864 * pre CAC which will mimic an AP.
6865 *
6866 * Return: Zero on success, non-zero value on error
6867 */
6868int wlan_hdd_request_pre_cac(uint8_t channel)
6869{
Krunal Sonib37bb352016-12-20 14:12:21 -08006870 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306871 hdd_context_t *hdd_ctx;
6872 int ret;
6873 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6874 hdd_ap_ctx_t *hdd_ap_ctx;
6875 QDF_STATUS status;
6876 struct wiphy *wiphy;
6877 struct net_device *dev;
6878 struct cfg80211_chan_def chandef;
6879 enum nl80211_channel_type channel_type;
6880 uint32_t freq;
6881 struct ieee80211_channel *chan;
6882 tHalHandle handle;
6883 bool val;
6884
6885 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6886 if (0 != wlan_hdd_validate_context(hdd_ctx))
6887 return -EINVAL;
6888
6889 if (cds_get_connection_count() > 1) {
6890 hdd_err("pre cac not allowed in concurrency");
6891 return -EINVAL;
6892 }
6893
6894 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6895 if (!ap_adapter) {
6896 hdd_err("unable to get SAP adapter");
6897 return -EINVAL;
6898 }
6899
6900 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6901 if (!handle) {
6902 hdd_err("Invalid handle");
6903 return -EINVAL;
6904 }
6905
6906 val = wlan_sap_is_pre_cac_active(handle);
6907 if (val) {
6908 hdd_err("pre cac is already in progress");
6909 return -EINVAL;
6910 }
6911
6912 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6913 if (!hdd_ap_ctx) {
6914 hdd_err("SAP context is NULL");
6915 return -EINVAL;
6916 }
6917
6918 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6919 hdd_err("SAP is already on DFS channel:%d",
6920 hdd_ap_ctx->operatingChannel);
6921 return -EINVAL;
6922 }
6923
6924 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6925 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6926 hdd_ap_ctx->operatingChannel);
6927 return -EINVAL;
6928 }
6929
Krunal Sonib37bb352016-12-20 14:12:21 -08006930 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6931 if (!mac_addr) {
6932 hdd_err("can't add virtual intf: Not getting valid mac addr");
6933 return -EINVAL;
6934 }
6935
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306936 hdd_info("channel:%d", channel);
6937
6938 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6939 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006940 if (ret != 0) {
6941 hdd_err("can't validate pre-cac channel");
6942 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306943 }
6944
6945 hdd_debug("starting pre cac SAP adapter");
6946
6947 /* Starting a SAP adapter:
6948 * Instead of opening an adapter, we could just do a SME open session
6949 * for AP type. But, start BSS would still need an adapter.
6950 * So, this option is not taken.
6951 *
6952 * hdd open adapter is going to register this precac interface with
6953 * user space. This interface though exposed to user space will be in
6954 * DOWN state. Consideration was done to avoid this registration to the
6955 * user space. But, as part of SAP operations multiple events are sent
6956 * to user space. Some of these events received from unregistered
6957 * interface was causing crashes. So, retaining the registration.
6958 *
6959 * So, this interface would remain registered and will remain in DOWN
6960 * state for the CAC duration. We will add notes in the feature
6961 * announcement to not use this temporary interface for any activity
6962 * from user space.
6963 */
6964 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006965 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306966 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306967 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006968 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306969 }
6970
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306971 /*
6972 * This interface is internally created by the driver. So, no interface
6973 * up comes for this interface from user space and hence starting
6974 * the adapter internally.
6975 */
6976 if (hdd_start_adapter(pre_cac_adapter)) {
6977 hdd_err("error starting the pre cac adapter");
6978 goto close_pre_cac_adapter;
6979 }
6980
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306981 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6982
6983 wiphy = hdd_ctx->wiphy;
6984 dev = pre_cac_adapter->dev;
6985
6986 /* Since this is only a dummy interface lets us use the IEs from the
6987 * other active SAP interface. In regular scenarios, these IEs would
6988 * come from the user space entity
6989 */
6990 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6991 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6992 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6993 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306994 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306995 }
6996 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6997 ap_adapter->sessionCtx.ap.beacon,
6998 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6999 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7000 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7001 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7002 ap_adapter->sessionCtx.ap.sapConfig.authType;
7003
7004 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7005 * to operate on the same bandwidth as that of the 2.4GHz operations.
7006 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7007 */
7008 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7009 case CH_WIDTH_20MHZ:
7010 channel_type = NL80211_CHAN_HT20;
7011 break;
7012 case CH_WIDTH_40MHZ:
7013 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7014 ap_adapter->sessionCtx.ap.sapConfig.channel)
7015 channel_type = NL80211_CHAN_HT40PLUS;
7016 else
7017 channel_type = NL80211_CHAN_HT40MINUS;
7018 break;
7019 default:
7020 channel_type = NL80211_CHAN_NO_HT;
7021 break;
7022 }
7023
7024 freq = cds_chan_to_freq(pre_cac_chan);
7025 chan = __ieee80211_get_channel(wiphy, freq);
7026 if (!chan) {
7027 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307028 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307029 }
7030
7031 cfg80211_chandef_create(&chandef, chan, channel_type);
7032
7033 hdd_debug("orig width:%d channel_type:%d freq:%d",
7034 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7035 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007036 /*
7037 * Doing update after opening and starting pre-cac adapter will make
7038 * sure that driver won't do hardware mode change if there are any
7039 * initial hick-ups or issues in pre-cac adapter's configuration.
7040 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7041 * connection update should result in DBS mode
7042 */
7043 status = cds_update_and_wait_for_connection_update(
7044 ap_adapter->sessionId,
7045 pre_cac_chan,
7046 SIR_UPDATE_REASON_PRE_CAC);
7047 if (QDF_IS_STATUS_ERROR(status)) {
7048 hdd_err("error in moving to DBS mode");
7049 goto stop_close_pre_cac_adapter;
7050 }
7051
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307052
7053 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7054 if (0 != ret) {
7055 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307056 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307057 }
7058
7059 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7060 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007061 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307062 if (QDF_IS_STATUS_ERROR(status)) {
7063 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307064 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307065 }
7066
7067 /*
7068 * The pre cac status is set here. But, it would not be reset explicitly
7069 * anywhere, since after the pre cac success/failure, the pre cac
7070 * adapter itself would be removed.
7071 */
7072 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7073 if (0 != ret) {
7074 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307075 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307076 }
7077
7078 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7079 hdd_ap_ctx->operatingChannel);
7080 if (0 != ret) {
7081 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307082 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307083 }
7084
7085 ap_adapter->pre_cac_chan = pre_cac_chan;
7086
7087 return 0;
7088
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307089stop_close_pre_cac_adapter:
7090 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307091 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7092 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307093close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307094 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007095release_intf_addr_and_return_failure:
7096 /*
7097 * Release the interface address as the adapter
7098 * failed to start, if you don't release then next
7099 * adapter which is trying to come wouldn't get valid
7100 * mac address. Remember we have limited pool of mac addresses
7101 */
7102 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307103 return -EINVAL;
7104}
7105
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307106/**
7107 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7108 *
7109 * Return: None
7110 */
7111void hdd_init_bpf_completion(void)
7112{
7113 init_completion(&bpf_context.completion);
7114}
7115
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307116static const struct nla_policy
7117wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7118 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7119};
7120
Agrawal Ashish65634612016-08-18 13:24:32 +05307121static const struct nla_policy
7122wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7123 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7124 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7125};
7126
7127/**
7128 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7129 * @wiphy: Pointer to wireless phy
7130 * @wdev: Pointer to wireless device
7131 * @data: Pointer to data
7132 * @data_len: Length of @data
7133 *
7134 * This function parses the incoming NL vendor command data attributes and
7135 * updates the SAP context about channel_hint and DFS mode.
7136 * If channel_hint is set, SAP will choose that channel
7137 * as operating channel.
7138 *
7139 * If DFS mode is enabled, driver will include DFS channels
7140 * in ACS else driver will skip DFS channels.
7141 *
7142 * Return: 0 on success, negative errno on failure
7143 */
7144static int
7145__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7146 struct wireless_dev *wdev,
7147 const void *data, int data_len)
7148{
7149 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7150 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7151 int ret;
7152 struct acs_dfs_policy *acs_policy;
7153 int mode = DFS_MODE_NONE;
7154 int channel_hint = 0;
7155
7156 ENTER_DEV(wdev->netdev);
7157
7158 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7159 hdd_err("Command not allowed in FTM mode");
7160 return -EINVAL;
7161 }
7162
7163 ret = wlan_hdd_validate_context(hdd_ctx);
7164 if (0 != ret)
7165 return ret;
7166
7167 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7168 data, data_len,
7169 wlan_hdd_set_acs_dfs_config_policy)) {
7170 hdd_err("invalid attr");
7171 return -EINVAL;
7172 }
7173
7174 acs_policy = &hdd_ctx->acs_policy;
7175 /*
7176 * SCM sends this attribute to restrict SAP from choosing
7177 * DFS channels from ACS.
7178 */
7179 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7180 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7181
7182 if (!IS_DFS_MODE_VALID(mode)) {
7183 hdd_err("attr acs dfs mode is not valid");
7184 return -EINVAL;
7185 }
7186 acs_policy->acs_dfs_mode = mode;
7187
7188 /*
7189 * SCM sends this attribute to provide an active channel,
7190 * to skip redundant ACS between drivers, and save driver start up time
7191 */
7192 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7193 channel_hint = nla_get_u8(
7194 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7195
7196 if (!IS_CHANNEL_VALID(channel_hint)) {
7197 hdd_err("acs channel is not valid");
7198 return -EINVAL;
7199 }
7200 acs_policy->acs_channel = channel_hint;
7201
7202 return 0;
7203}
7204
7205/**
7206 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7207 * @wiphy: wiphy structure pointer
7208 * @wdev: Wireless device structure pointer
7209 * @data: Pointer to the data received
7210 * @data_len: Length of @data
7211 *
7212 * This function parses the incoming NL vendor command data attributes and
7213 * updates the SAP context about channel_hint and DFS mode.
7214 *
7215 * Return: 0 on success; errno on failure
7216 */
7217static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7218 struct wireless_dev *wdev,
7219 const void *data, int data_len)
7220{
7221 int ret;
7222
7223 cds_ssr_protect(__func__);
7224 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7225 cds_ssr_unprotect(__func__);
7226
7227 return ret;
7228}
7229
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307230/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307231 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7232 * @mode : cfg80211 dfs mode
7233 *
7234 * Return: return csr sta roam dfs mode else return NONE
7235 */
7236static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7237 enum dfs_mode mode)
7238{
7239 switch (mode) {
7240 case DFS_MODE_ENABLE:
7241 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7242 break;
7243 case DFS_MODE_DISABLE:
7244 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7245 break;
7246 case DFS_MODE_DEPRIORITIZE:
7247 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7248 break;
7249 default:
7250 hdd_err("STA Roam policy dfs mode is NONE");
7251 return CSR_STA_ROAM_POLICY_NONE;
7252 }
7253}
7254
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307255/*
7256 * hdd_get_sap_operating_band: Get current operating channel
7257 * for sap.
7258 * @hdd_ctx: hdd context
7259 *
7260 * Return : Corresponding band for SAP operating channel
7261 */
7262uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7263{
7264 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7265 QDF_STATUS status;
7266 hdd_adapter_t *adapter;
7267 uint8_t operating_channel = 0;
7268 uint8_t sap_operating_band = 0;
7269 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7270 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7271 adapter = adapter_node->pAdapter;
7272
7273 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7274 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7275 &next);
7276 adapter_node = next;
7277 continue;
7278 }
7279 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7280 if (IS_24G_CH(operating_channel))
7281 sap_operating_band = eCSR_BAND_24;
7282 else if (IS_5G_CH(operating_channel))
7283 sap_operating_band = eCSR_BAND_5G;
7284 else
7285 sap_operating_band = eCSR_BAND_ALL;
7286 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7287 &next);
bings373b99b2017-01-23 10:35:08 +08007288 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307289 }
7290 return sap_operating_band;
7291}
7292
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307293static const struct nla_policy
7294wlan_hdd_set_sta_roam_config_policy[
7295QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7296 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7297 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7298};
7299
7300/**
7301 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7302 * for station connection or roaming.
7303 * @wiphy: Pointer to wireless phy
7304 * @wdev: Pointer to wireless device
7305 * @data: Pointer to data
7306 * @data_len: Length of @data
7307 *
7308 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7309 * channels needs to be skipped in scanning or not.
7310 * If dfs_mode is disabled, driver will not scan DFS channels.
7311 * If skip_unsafe_channels is set, driver will skip unsafe channels
7312 * in Scanning.
7313 *
7314 * Return: 0 on success, negative errno on failure
7315 */
7316static int
7317__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7318 struct wireless_dev *wdev,
7319 const void *data, int data_len)
7320{
7321 struct net_device *dev = wdev->netdev;
7322 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7323 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7324 struct nlattr *tb[
7325 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7326 int ret;
7327 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7328 enum dfs_mode mode = DFS_MODE_NONE;
7329 bool skip_unsafe_channels = false;
7330 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307331 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307332
7333 ENTER_DEV(dev);
7334
7335 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7336 hdd_err("Command not allowed in FTM mode");
7337 return -EINVAL;
7338 }
7339
7340 ret = wlan_hdd_validate_context(hdd_ctx);
7341 if (0 != ret)
7342 return ret;
7343 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7344 data, data_len,
7345 wlan_hdd_set_sta_roam_config_policy)) {
7346 hdd_err("invalid attr");
7347 return -EINVAL;
7348 }
7349 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7350 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7351 if (!IS_DFS_MODE_VALID(mode)) {
7352 hdd_err("attr sta roam dfs mode policy is not valid");
7353 return -EINVAL;
7354 }
7355
7356 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7357
7358 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7359 skip_unsafe_channels = nla_get_u8(
7360 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307361 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307362 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307363 skip_unsafe_channels, adapter->sessionId,
7364 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307365
7366 if (!QDF_IS_STATUS_SUCCESS(status)) {
7367 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7368 return -EINVAL;
7369 }
7370 return 0;
7371}
7372
7373/**
7374 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7375 * connection and roaming for station.
7376 * @wiphy: wiphy structure pointer
7377 * @wdev: Wireless device structure pointer
7378 * @data: Pointer to the data received
7379 * @data_len: Length of @data
7380 *
7381 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7382 * channels needs to be skipped in scanning or not.
7383 * If dfs_mode is disabled, driver will not scan DFS channels.
7384 * If skip_unsafe_channels is set, driver will skip unsafe channels
7385 * in Scanning.
7386 * Return: 0 on success; errno on failure
7387 */
7388static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7389 struct wireless_dev *wdev,
7390 const void *data, int data_len)
7391{
7392 int ret;
7393
7394 cds_ssr_protect(__func__);
7395 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7396 cds_ssr_unprotect(__func__);
7397
7398 return ret;
7399}
7400
Agrawal Ashish467dde42016-09-08 18:44:22 +05307401#ifdef FEATURE_WLAN_CH_AVOID
7402/**
7403 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7404 * is on unsafe channel.
7405 * @wiphy: wiphy structure pointer
7406 * @wdev: Wireless device structure pointer
7407 * @data: Pointer to the data received
7408 * @data_len: Length of @data
7409 *
7410 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7411 * on any of unsafe channels.
7412 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7413 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7414 *
7415 * Return: 0 on success; errno on failure
7416 */
7417static int
7418__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7419 struct wireless_dev *wdev,
7420 const void *data, int data_len)
7421{
7422 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7423 int ret;
7424 uint16_t unsafe_channel_count;
7425 int unsafe_channel_index;
7426 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7427
7428 ENTER_DEV(wdev->netdev);
7429
7430 if (!qdf_ctx) {
7431 cds_err("qdf_ctx is NULL");
7432 return -EINVAL;
7433 }
7434
7435 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7436 hdd_err("Command not allowed in FTM mode");
7437 return -EINVAL;
7438 }
7439
7440 ret = wlan_hdd_validate_context(hdd_ctx);
7441 if (0 != ret)
7442 return ret;
7443 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7444 &(hdd_ctx->unsafe_channel_count),
7445 sizeof(hdd_ctx->unsafe_channel_list));
7446
7447 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7448 (uint16_t)NUM_CHANNELS);
7449 for (unsafe_channel_index = 0;
7450 unsafe_channel_index < unsafe_channel_count;
7451 unsafe_channel_index++) {
7452 hdd_info("Channel %d is not safe",
7453 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7454 }
7455 hdd_unsafe_channel_restart_sap(hdd_ctx);
7456 return 0;
7457}
7458
7459/**
7460 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7461 * is on unsafe channel.
7462 * @wiphy: wiphy structure pointer
7463 * @wdev: Wireless device structure pointer
7464 * @data: Pointer to the data received
7465 * @data_len: Length of @data
7466 *
7467 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7468 * on any of unsafe channels.
7469 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7470 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7471 *
7472 * Return: 0 on success; errno on failure
7473 */
7474static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7475 struct wireless_dev *wdev,
7476 const void *data, int data_len)
7477{
7478 int ret;
7479
7480 cds_ssr_protect(__func__);
7481 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7482 cds_ssr_unprotect(__func__);
7483
7484 return ret;
7485}
7486
7487#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307488/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307489 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7490 * SAP is on unsafe channel.
7491 * @wiphy: wiphy structure pointer
7492 * @wdev: Wireless device structure pointer
7493 * @data: Pointer to the data received
7494 * @data_len: Length of @data
7495 *
7496 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7497 * driver.
7498 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7499 * will initiate restart of sap.
7500 *
7501 * Return: 0 on success; errno on failure
7502 */
7503static int
7504__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7505 struct wireless_dev *wdev,
7506 const void *data, int data_len)
7507{
7508 struct net_device *ndev = wdev->netdev;
7509 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7510 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7511 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7512 uint8_t config_channel = 0;
7513 hdd_ap_ctx_t *ap_ctx;
7514 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307515 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307516
7517 ENTER();
7518
7519 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007520 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307521 return -EINVAL;
7522 }
7523
7524 ret = wlan_hdd_validate_context(hdd_ctx);
7525 if (0 != ret)
7526 return -EINVAL;
7527
7528 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7529 data, data_len,
7530 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007531 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307532 return -EINVAL;
7533 }
7534
7535 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7536 if (!test_bit(SOFTAP_BSS_STARTED,
7537 &hostapd_adapter->event_flags)) {
7538 hdd_err("SAP is not started yet. Restart sap will be invalid");
7539 return -EINVAL;
7540 }
7541
7542 config_channel =
7543 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7544
7545 if (!((IS_24G_CH(config_channel)) ||
7546 (IS_5G_CH(config_channel)))) {
7547 hdd_err("Channel %d is not valid to restart SAP",
7548 config_channel);
7549 return -ENOTSUPP;
7550 }
7551
7552 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7553 ap_ctx->sapConfig.channel = config_channel;
7554 ap_ctx->sapConfig.ch_params.ch_width =
7555 ap_ctx->sapConfig.ch_width_orig;
7556
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007557 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307558 ap_ctx->sapConfig.sec_ch,
7559 &ap_ctx->sapConfig.ch_params);
7560
7561 cds_restart_sap(hostapd_adapter);
7562 }
7563
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307564 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7565 uint32_t freq_len, i;
7566 uint32_t *freq;
7567 uint8_t chans[QDF_MAX_NUM_CHAN];
7568
7569 hdd_debug("setting mandatory freq/chan list");
7570
7571 freq_len = nla_len(
7572 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7573 sizeof(uint32_t);
7574
7575 if (freq_len > QDF_MAX_NUM_CHAN) {
7576 hdd_err("insufficient space to hold channels");
7577 return -ENOMEM;
7578 }
7579
7580 freq = nla_data(
7581 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7582
7583 hdd_debug("freq_len=%d", freq_len);
7584
7585 for (i = 0; i < freq_len; i++) {
7586 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7587 hdd_debug("freq[%d]=%d", i, freq[i]);
7588 }
7589
7590 status = cds_set_sap_mandatory_channels(chans, freq_len);
7591 if (QDF_IS_STATUS_ERROR(status))
7592 return -EINVAL;
7593 }
7594
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307595 return 0;
7596}
7597
7598/**
7599 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7600 * @wiphy: wiphy structure pointer
7601 * @wdev: Wireless device structure pointer
7602 * @data: Pointer to the data received
7603 * @data_len: Length of @data
7604 *
7605 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7606 * driver.
7607 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7608 * will initiate restart of sap.
7609 *
7610 * Return: 0 on success; errno on failure
7611 */
7612static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7613 struct wireless_dev *wdev,
7614 const void *data, int data_len)
7615{
7616 int ret;
7617
7618 cds_ssr_protect(__func__);
7619 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7620 wdev, data, data_len);
7621 cds_ssr_unprotect(__func__);
7622
7623 return ret;
7624}
7625
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307626#undef BPF_INVALID
7627#undef BPF_SET_RESET
7628#undef BPF_VERSION
7629#undef BPF_ID
7630#undef BPF_PACKET_SIZE
7631#undef BPF_CURRENT_OFFSET
7632#undef BPF_PROGRAM
7633#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307634
7635/**
7636 * define short names for the global vendor params
7637 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7638 */
7639#define PARAM_TOTAL_CMD_EVENT_WAKE \
7640 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7641#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7642 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7643#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7644 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7645#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7646 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7647#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7648 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7649#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7650 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7651#define PARAM_TOTAL_RX_DATA_WAKE \
7652 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7653#define PARAM_RX_UNICAST_CNT \
7654 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7655#define PARAM_RX_MULTICAST_CNT \
7656 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7657#define PARAM_RX_BROADCAST_CNT \
7658 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7659#define PARAM_ICMP_PKT \
7660 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7661#define PARAM_ICMP6_PKT \
7662 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7663#define PARAM_ICMP6_RA \
7664 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7665#define PARAM_ICMP6_NA \
7666 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7667#define PARAM_ICMP6_NS \
7668 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7669#define PARAM_ICMP4_RX_MULTICAST_CNT \
7670 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7671#define PARAM_ICMP6_RX_MULTICAST_CNT \
7672 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7673#define PARAM_OTHER_RX_MULTICAST_CNT \
7674 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307675#define PARAM_RSSI_BREACH_CNT \
7676 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
7677#define PARAM_LOW_RSSI_CNT \
7678 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
7679#define PARAM_GSCAN_CNT \
7680 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
7681#define PARAM_PNO_COMPLETE_CNT \
7682 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
7683#define PARAM_PNO_MATCH_CNT \
7684 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
7685
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307686
7687
7688/**
7689 * hdd_send_wakelock_stats() - API to send wakelock stats
7690 * @ctx: context to be passed to callback
7691 * @data: data passed to callback
7692 *
7693 * This function is used to send wake lock stats to HAL layer
7694 *
7695 * Return: 0 on success, error number otherwise.
7696 */
7697static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7698 const struct sir_wake_lock_stats *data)
7699{
7700 struct sk_buff *skb;
7701 uint32_t nl_buf_len;
7702 uint32_t total_rx_data_wake, rx_multicast_cnt;
7703 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307704 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307705
7706 ENTER();
7707
7708 nl_buf_len = NLMSG_HDRLEN;
7709 nl_buf_len +=
7710 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7711 (NLMSG_HDRLEN + sizeof(uint32_t));
7712
7713 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7714
7715 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007716 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307717 return -ENOMEM;
7718 }
7719
Jeff Johnson64943bd2016-08-23 13:14:06 -07007720 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307721 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007722 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307723 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007724 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307725 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007726 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307727 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007728 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307729 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007730 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307731 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007732 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307733 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007734 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7735 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307736 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307737 hdd_info("wow_rssi_breach_wake_up_count %d",
7738 data->wow_rssi_breach_wake_up_count);
7739 hdd_info("wow_low_rssi_wake_up_count %d",
7740 data->wow_low_rssi_wake_up_count);
7741 hdd_info("wow_gscan_wake_up_count %d",
7742 data->wow_gscan_wake_up_count);
7743 hdd_info("wow_pno_complete_wake_up_count %d",
7744 data->wow_pno_complete_wake_up_count);
7745 hdd_info("wow_pno_match_wake_up_count %d",
7746 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307747
7748 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307749 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307750
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307751 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307752 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307753
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307754 rx_multicast_cnt =
7755 data->wow_ipv4_mcast_wake_up_count +
7756 ipv6_rx_multicast_addr_cnt;
7757
7758 total_rx_data_wake =
7759 data->wow_ucast_wake_up_count +
7760 data->wow_bcast_wake_up_count +
7761 rx_multicast_cnt;
7762
7763 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7764 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7765 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7766 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7767 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7768 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7769 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7770 total_rx_data_wake) ||
7771 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7772 data->wow_ucast_wake_up_count) ||
7773 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7774 rx_multicast_cnt) ||
7775 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7776 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307777 nla_put_u32(skb, PARAM_ICMP_PKT,
7778 data->wow_icmpv4_count) ||
7779 nla_put_u32(skb, PARAM_ICMP6_PKT,
7780 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307781 nla_put_u32(skb, PARAM_ICMP6_RA,
7782 data->wow_ipv6_mcast_ra_stats) ||
7783 nla_put_u32(skb, PARAM_ICMP6_NA,
7784 data->wow_ipv6_mcast_na_stats) ||
7785 nla_put_u32(skb, PARAM_ICMP6_NS,
7786 data->wow_ipv6_mcast_ns_stats) ||
7787 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7788 data->wow_ipv4_mcast_wake_up_count) ||
7789 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7790 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307791 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
7792 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
7793 data->wow_rssi_breach_wake_up_count) ||
7794 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
7795 data->wow_low_rssi_wake_up_count) ||
7796 nla_put_u32(skb, PARAM_GSCAN_CNT,
7797 data->wow_gscan_wake_up_count) ||
7798 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
7799 data->wow_pno_complete_wake_up_count) ||
7800 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
7801 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007802 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307803 goto nla_put_failure;
7804 }
7805
7806 cfg80211_vendor_cmd_reply(skb);
7807
7808 EXIT();
7809 return 0;
7810
7811nla_put_failure:
7812 kfree_skb(skb);
7813 return -EINVAL;
7814}
7815
7816/**
7817 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7818 * @wiphy: wiphy pointer
7819 * @wdev: pointer to struct wireless_dev
7820 * @data: pointer to incoming NL vendor data
7821 * @data_len: length of @data
7822 *
7823 * This function parses the incoming NL vendor command data attributes and
7824 * invokes the SME Api and blocks on a completion variable.
7825 * WMA copies required data and invokes callback
7826 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7827 *
7828 * Return: 0 on success; error number otherwise.
7829 */
7830static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7831 struct wireless_dev *wdev,
7832 const void *data,
7833 int data_len)
7834{
7835 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7836 int status, ret;
7837 struct sir_wake_lock_stats wake_lock_stats;
7838 QDF_STATUS qdf_status;
7839
7840 ENTER();
7841
7842 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007843 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307844 return -EINVAL;
7845 }
7846
7847 status = wlan_hdd_validate_context(hdd_ctx);
7848 if (0 != status)
7849 return -EINVAL;
7850
7851 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7852 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007853 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307854 return -EINVAL;
7855 }
7856
7857 ret = hdd_send_wakelock_stats(hdd_ctx,
7858 &wake_lock_stats);
7859 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007860 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307861
7862 EXIT();
7863 return ret;
7864}
7865
7866/**
7867 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7868 * @wiphy: wiphy pointer
7869 * @wdev: pointer to struct wireless_dev
7870 * @data: pointer to incoming NL vendor data
7871 * @data_len: length of @data
7872 *
7873 * This function parses the incoming NL vendor command data attributes and
7874 * invokes the SME Api and blocks on a completion variable.
7875 * WMA copies required data and invokes callback
7876 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7877 *
7878 * Return: 0 on success; error number otherwise.
7879 */
7880static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7881 struct wireless_dev *wdev,
7882 const void *data, int data_len)
7883{
7884 int ret;
7885
7886 cds_ssr_protect(__func__);
7887 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7888 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007889 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307890
7891 return ret;
7892}
7893
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307894/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307895 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7896 * @wiphy: wiphy structure pointer
7897 * @wdev: Wireless device structure pointer
7898 * @data: Pointer to the data received
7899 * @data_len: Length of @data
7900 *
7901 * This function reads wmi max bus size and fill in the skb with
7902 * NL attributes and send up the NL event.
7903 * Return: 0 on success; errno on failure
7904 */
7905static int
7906__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7907 struct wireless_dev *wdev,
7908 const void *data, int data_len)
7909{
7910 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7911 int ret_val;
7912 struct sk_buff *skb;
7913 uint32_t nl_buf_len;
7914
7915 ENTER();
7916
7917 ret_val = wlan_hdd_validate_context(hdd_ctx);
7918 if (ret_val)
7919 return ret_val;
7920
7921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7922 hdd_err("Command not allowed in FTM mode");
7923 return -EINVAL;
7924 }
7925
7926 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7927
7928 nl_buf_len = NLMSG_HDRLEN;
7929 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7930
7931 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7932 if (!skb) {
7933 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7934 return -ENOMEM;
7935 }
7936
7937 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7938 hdd_ctx->wmi_max_len)) {
7939 hdd_err("nla put failure");
7940 goto nla_put_failure;
7941 }
7942
7943 cfg80211_vendor_cmd_reply(skb);
7944
7945 EXIT();
7946
7947 return 0;
7948
7949nla_put_failure:
7950 kfree_skb(skb);
7951 return -EINVAL;
7952}
7953
7954/**
7955 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7956 * @wiphy: wiphy structure pointer
7957 * @wdev: Wireless device structure pointer
7958 * @data: Pointer to the data received
7959 * @data_len: Length of @data
7960 *
7961 * Return: 0 on success; errno on failure
7962 */
7963static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7964 struct wireless_dev *wdev,
7965 const void *data, int data_len)
7966{
7967 int ret;
7968
7969 cds_ssr_protect(__func__);
7970 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7971 cds_ssr_unprotect(__func__);
7972
7973 return ret;
7974}
7975
7976/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307977 *__wlan_hdd_cfg80211_setband() - set band
7978 * @wiphy: Pointer to wireless phy
7979 * @wdev: Pointer to wireless device
7980 * @data: Pointer to data
7981 * @data_len: Length of @data
7982 *
7983 * Return: 0 on success, negative errno on failure
7984 */
7985static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7986 struct wireless_dev *wdev,
7987 const void *data, int data_len)
7988{
7989 struct net_device *dev = wdev->netdev;
7990 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7991 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7992 int ret;
7993 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7994 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7995
7996 ENTER();
7997
7998 ret = wlan_hdd_validate_context(hdd_ctx);
7999 if (ret)
8000 return ret;
8001
8002 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8003 hdd_err(FL("Invalid ATTR"));
8004 return -EINVAL;
8005 }
8006
8007 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8008 hdd_err(FL("attr SETBAND_VALUE failed"));
8009 return -EINVAL;
8010 }
8011
8012 ret = hdd_set_band(dev,
8013 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8014
8015 EXIT();
8016 return ret;
8017}
8018
8019/**
8020 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8021 * @wiphy: wiphy structure pointer
8022 * @wdev: Wireless device structure pointer
8023 * @data: Pointer to the data received
8024 * @data_len: Length of @data
8025 *
8026 * Return: 0 on success; errno on failure
8027 */
8028static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8029 struct wireless_dev *wdev,
8030 const void *data, int data_len)
8031{
8032 int ret;
8033
8034 cds_ssr_protect(__func__);
8035 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8036 cds_ssr_unprotect(__func__);
8037
8038 return ret;
8039}
8040
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008041/**
8042 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8043 * @nl80211_value: Vendor command attribute value
8044 * @wmi_value: Pointer to return converted WMI return value
8045 *
8046 * Convert NL80211 vendor command value for SAR limit set to WMI value
8047 * Return: 0 on success, -1 on invalid value
8048 */
8049static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8050 u32 *wmi_value)
8051{
8052 int ret = 0;
8053
8054 switch (nl80211_value) {
8055 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8056 *wmi_value = WMI_SAR_FEATURE_OFF;
8057 break;
8058 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8059 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8060 break;
8061 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8062 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8063 break;
8064 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8065 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8066 break;
8067 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8068 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8069 break;
8070 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8071 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8072 break;
8073 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8074 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8075 break;
8076 default:
8077 ret = -1;
8078 }
8079 return ret;
8080}
8081
8082/**
8083 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8084 * @nl80211_value: Vendor command attribute value
8085 * @wmi_value: Pointer to return converted WMI return value
8086 *
8087 * Convert NL80211 vendor command value for SAR BAND to WMI value
8088 * Return: 0 on success, -1 on invalid value
8089 */
8090static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8091{
8092 int ret = 0;
8093
8094 switch (nl80211_value) {
8095 case NL80211_BAND_2GHZ:
8096 *wmi_value = WMI_SAR_2G_ID;
8097 break;
8098 case NL80211_BAND_5GHZ:
8099 *wmi_value = WMI_SAR_5G_ID;
8100 break;
8101 default:
8102 ret = -1;
8103 }
8104 return ret;
8105}
8106
8107/**
8108 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8109 * @nl80211_value: Vendor command attribute value
8110 * @wmi_value: Pointer to return converted WMI return value
8111 *
8112 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8113 * Return: 0 on success, -1 on invalid value
8114 */
8115static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8116 u32 *wmi_value)
8117{
8118 int ret = 0;
8119
8120 switch (nl80211_value) {
8121 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8122 *wmi_value = WMI_SAR_MOD_CCK;
8123 break;
8124 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8125 *wmi_value = WMI_SAR_MOD_OFDM;
8126 break;
8127 default:
8128 ret = -1;
8129 }
8130 return ret;
8131}
8132
8133
8134/**
8135 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8136 * @wiphy: Pointer to wireless phy
8137 * @wdev: Pointer to wireless device
8138 * @data: Pointer to data
8139 * @data_len: Length of @data
8140 *
8141 * This function is used to setup Specific Absorption Rate limit specs.
8142 *
8143 * Return: 0 on success, negative errno on failure
8144 */
8145static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8146 struct wireless_dev *wdev,
8147 const void *data, int data_len)
8148{
8149 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8150 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8151 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8152 *sar_spec_list;
8153 struct sar_limit_cmd_params sar_limit_cmd = {0};
8154 int ret = -EINVAL, i = 0, rem = 0;
8155
8156 ENTER();
8157
8158 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8159 hdd_err("Command not allowed in FTM mode");
8160 return -EPERM;
8161 }
8162
8163 if (wlan_hdd_validate_context(hdd_ctx))
8164 return -EINVAL;
8165
8166 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8167 data, data_len, NULL)) {
8168 hdd_err("Invalid SAR attributes");
8169 return -EINVAL;
8170 }
8171
8172 /* Vendor command manadates all SAR Specs in single call */
8173 sar_limit_cmd.commit_limits = 1;
8174 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
8175 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
8176 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
8177 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
8178 &sar_limit_cmd.sar_enable) < 0) {
8179 hdd_err("Invalid SAR Enable attr");
8180 goto fail;
8181 }
8182 }
8183 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
8184
8185 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
8186 sar_limit_cmd.num_limit_rows = nla_get_u32(
8187 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
8188 hdd_info("attr sar num_limit_rows %d",
8189 sar_limit_cmd.num_limit_rows);
8190 }
8191 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
8192 hdd_err("SAR Spec list exceed supported size");
8193 goto fail;
8194 }
8195 if (sar_limit_cmd.num_limit_rows == 0)
8196 goto send_sar_limits;
8197 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
8198 struct sar_limit_cmd_row) *
8199 sar_limit_cmd.num_limit_rows);
8200 if (!sar_limit_cmd.sar_limit_row_list) {
8201 ret = -ENOMEM;
8202 goto fail;
8203 }
8204 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
8205 hdd_err("Invalid SAR SPECs list");
8206 goto fail;
8207 }
8208
8209 nla_for_each_nested(sar_spec_list,
8210 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
8211 if (i == sar_limit_cmd.num_limit_rows) {
8212 hdd_warn("SAR Cmd has excess SPECs in list");
8213 break;
8214 }
8215
8216 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8217 nla_data(sar_spec_list), nla_len(sar_spec_list),
8218 NULL)) {
8219 hdd_err("nla_parse failed for SAR Spec list");
8220 goto fail;
8221 }
8222 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
8223 if (sar_spec[
8224 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
8225 sar_limit_cmd.sar_limit_row_list[i].limit_value =
8226 nla_get_u32(sar_spec[
8227 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
8228 } else {
8229 hdd_err("SAR Spec does not have power limit value");
8230 goto fail;
8231 }
8232
8233 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
8234 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
8235 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
8236 &sar_limit_cmd.sar_limit_row_list[i].band_id)
8237 < 0) {
8238 hdd_err("Invalid SAR Band attr");
8239 goto fail;
8240 }
8241 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8242 WMI_SAR_BAND_ID_VALID_MASK;
8243 }
8244 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
8245 sar_limit_cmd.sar_limit_row_list[i].chain_id =
8246 nla_get_u32(sar_spec[
8247 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
8248 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8249 WMI_SAR_CHAIN_ID_VALID_MASK;
8250 }
8251 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
8252 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
8253 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
8254 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
8255 < 0) {
8256 hdd_err("Invalid SAR Modulation attr");
8257 goto fail;
8258 }
8259 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8260 WMI_SAR_MOD_ID_VALID_MASK;
8261 }
8262 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
8263 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
8264 sar_limit_cmd.sar_limit_row_list[i].chain_id,
8265 sar_limit_cmd.sar_limit_row_list[i].mod_id,
8266 sar_limit_cmd.sar_limit_row_list[i].limit_value,
8267 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
8268 i++;
8269 }
8270
8271 if (i < sar_limit_cmd.num_limit_rows) {
8272 hdd_warn("SAR Cmd has less SPECs in list");
8273 sar_limit_cmd.num_limit_rows = i;
8274 }
8275
8276send_sar_limits:
8277 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
8278 QDF_STATUS_SUCCESS)
8279 ret = 0;
8280fail:
8281 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
8282 return ret;
8283}
8284
8285/**
8286 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
8287 * @wiphy: Pointer to wireless phy
8288 * @wdev: Pointer to wireless device
8289 * @data: Pointer to data
8290 * @data_len: Length of @data
8291 *
8292 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
8293 *
8294 * Return: 0 on success, negative errno on failure
8295 */
8296static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
8297 struct wireless_dev *wdev,
8298 const void *data,
8299 int data_len)
8300{
8301 int ret;
8302
8303 cds_ssr_protect(__func__);
8304 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
8305 data_len);
8306 cds_ssr_unprotect(__func__);
8307
8308 return ret;
8309}
8310
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308311static const struct
8312nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
8313 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
8314 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
8315 .len = QDF_MAC_ADDR_SIZE},
8316};
8317
8318/**
8319 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8320 * @wiphy: Pointer to wireless phy
8321 * @wdev: Pointer to wireless device
8322 * @data: Pointer to data
8323 * @data_len: Length of @data
8324 *
8325 * This function is used to enable/disable roaming using vendor commands
8326 *
8327 * Return: 0 on success, negative errno on failure
8328 */
8329static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8330 struct wireless_dev *wdev,
8331 const void *data, int data_len)
8332{
8333 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8334 struct net_device *dev = wdev->netdev;
8335 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8336 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8337 uint32_t is_fast_roam_enabled;
8338 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308339 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308340
8341 ENTER_DEV(dev);
8342
8343 ret = wlan_hdd_validate_context(hdd_ctx);
8344 if (0 != ret)
8345 return ret;
8346
8347 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8348 hdd_err("Command not allowed in FTM mode");
8349 return -EINVAL;
8350 }
8351
8352 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
8353 qca_wlan_vendor_attr);
8354 if (ret) {
8355 hdd_err("Invalid ATTR");
8356 return -EINVAL;
8357 }
8358
8359 /* Parse and fetch Enable flag */
8360 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
8361 hdd_err("attr enable failed");
8362 return -EINVAL;
8363 }
8364
8365 is_fast_roam_enabled = nla_get_u32(
8366 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008367 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
8368 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308369
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008370 if (!adapter->fast_roaming_allowed) {
8371 hdd_err("fast roaming not allowed on %s interface",
8372 adapter->dev->name);
8373 return -EINVAL;
8374 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308375 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308376 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008377 (is_fast_roam_enabled &&
8378 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308379 if (qdf_status != QDF_STATUS_SUCCESS)
8380 hdd_err("sme_config_fast_roaming failed with status=%d",
8381 qdf_status);
8382 ret = qdf_status_to_os_return(qdf_status);
8383
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308384 EXIT();
8385 return ret;
8386}
8387
8388/**
8389 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8390 * @wiphy: Pointer to wireless phy
8391 * @wdev: Pointer to wireless device
8392 * @data: Pointer to data
8393 * @data_len: Length of @data
8394 *
8395 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8396 *
8397 * Return: 0 on success, negative errno on failure
8398 */
8399static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8400 struct wireless_dev *wdev,
8401 const void *data, int data_len)
8402{
8403 int ret;
8404
8405 cds_ssr_protect(__func__);
8406 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8407 cds_ssr_unprotect(__func__);
8408
8409 return ret;
8410}
8411
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05308412static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
8413 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
8414 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
8415 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
8416 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
8417};
8418
8419/**
8420 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
8421 * @wiphy: Pointer to wireless phy
8422 * @wdev: Pointer to wireless device
8423 * @data: Pointer to data
8424 * @data_len: Length of @data
8425 *
8426 * Return: 0 on success, negative errno on failure
8427 */
8428static int
8429__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
8430 struct wireless_dev *wdev,
8431 const void *data,
8432 int data_len)
8433{
8434 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8435 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
8436 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
8437 struct nlattr *apth;
8438 int rem;
8439 int ret = 1;
8440 int print_idx = -1;
8441 int module_id = -1;
8442 int bit_mask = -1;
8443 int status;
8444
8445 ENTER();
8446
8447 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8448 hdd_err("Command not allowed in FTM mode");
8449 return -EINVAL;
8450 }
8451
8452 ret = wlan_hdd_validate_context(hdd_ctx);
8453 if (ret != 0)
8454 return -EINVAL;
8455
8456 print_idx = qdf_get_pidx();
8457 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
8458 hdd_err("Invalid print controle object index");
8459 return -EINVAL;
8460 }
8461
8462 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
8463 data_len, qca_wlan_vendor_set_trace_level_policy)) {
8464 hdd_err("Invalid attr");
8465 return -EINVAL;
8466 }
8467
8468 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
8469 hdd_err("attr trace level param failed");
8470 return -EINVAL;
8471 }
8472
8473 nla_for_each_nested(apth,
8474 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
8475 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
8476 nla_data(apth), nla_len(apth), NULL)) {
8477 hdd_err("Invalid attr");
8478 return -EINVAL;
8479 }
8480
8481 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
8482 hdd_err("attr Module ID failed");
8483 return -EINVAL;
8484 }
8485 module_id = nla_get_u32
8486 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
8487
8488 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
8489 hdd_err("attr Verbose mask failed");
8490 return -EINVAL;
8491 }
8492 bit_mask = nla_get_u32
8493 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
8494
8495 status = hdd_qdf_trace_enable(module_id, bit_mask);
8496
8497 if (status != 0)
8498 hdd_err("can not set verbose mask %d for the category %d",
8499 bit_mask, module_id);
8500 }
8501
8502 EXIT();
8503 return ret;
8504}
8505
8506/**
8507 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
8508 * @wiphy: Pointer to wireless phy
8509 * @wdev: Pointer to wireless device
8510 * @data: Pointer to data
8511 * @data_len: Length of @data
8512 *
8513 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
8514 *
8515 * Return: 0 on success, negative errno on failure
8516 */
8517
8518static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
8519 struct wireless_dev *wdev,
8520 const void *data,
8521 int data_len)
8522{
8523 int ret;
8524
8525 cds_ssr_protect(__func__);
8526 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
8527 cds_ssr_unprotect(__func__);
8528
8529 return ret;
8530}
8531
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008532const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8533 {
8534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308537 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008538 .doit = is_driver_dfs_capable
8539 },
8540
8541#ifdef WLAN_FEATURE_NAN
8542 {
8543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8544 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8546 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8547 .doit = wlan_hdd_cfg80211_nan_request
8548 },
8549#endif
8550
8551#ifdef WLAN_FEATURE_STATS_EXT
8552 {
8553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8556 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8557 .doit = wlan_hdd_cfg80211_stats_ext_request
8558 },
8559#endif
8560#ifdef FEATURE_WLAN_EXTSCAN
8561 {
8562 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8563 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8564 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8565 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8566 .doit = wlan_hdd_cfg80211_extscan_start
8567 },
8568 {
8569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8572 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8573 .doit = wlan_hdd_cfg80211_extscan_stop
8574 },
8575 {
8576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8577 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8578 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8579 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8580 },
8581 {
8582 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8583 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8584 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8585 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8586 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8587 },
8588 {
8589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8592 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8593 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8594 },
8595 {
8596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8599 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8600 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8601 },
8602 {
8603 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8604 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8605 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8606 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8607 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8608 },
8609 {
8610 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8611 .info.subcmd =
8612 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8613 .flags =
8614 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8615 WIPHY_VENDOR_CMD_NEED_RUNNING,
8616 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8617 },
8618 {
8619 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8620 .info.subcmd =
8621 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8622 .flags =
8623 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8624 WIPHY_VENDOR_CMD_NEED_RUNNING,
8625 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8626 },
8627 {
8628 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8629 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8630 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8631 WIPHY_VENDOR_CMD_NEED_NETDEV |
8632 WIPHY_VENDOR_CMD_NEED_RUNNING,
8633 .doit = wlan_hdd_cfg80211_set_epno_list
8634 },
8635#endif /* FEATURE_WLAN_EXTSCAN */
8636
8637#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8638 {
8639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8642 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8643 .doit = wlan_hdd_cfg80211_ll_stats_clear
8644 },
8645
8646 {
8647 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8648 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8649 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8650 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8651 .doit = wlan_hdd_cfg80211_ll_stats_set
8652 },
8653
8654 {
8655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8656 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8657 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8658 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8659 .doit = wlan_hdd_cfg80211_ll_stats_get
8660 },
8661#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8662#ifdef FEATURE_WLAN_TDLS
8663 {
8664 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8665 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8666 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8667 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8668 .doit = wlan_hdd_cfg80211_exttdls_enable
8669 },
8670 {
8671 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8672 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8673 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8674 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8675 .doit = wlan_hdd_cfg80211_exttdls_disable
8676 },
8677 {
8678 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8679 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8680 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8681 .doit = wlan_hdd_cfg80211_exttdls_get_status
8682 },
8683#endif
8684 {
8685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8688 .doit = wlan_hdd_cfg80211_get_supported_features
8689 },
8690 {
8691 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8692 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8693 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8694 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8695 },
8696 {
8697 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8698 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8699 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308700 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008701 },
8702 {
8703 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8704 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8705 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8706 WIPHY_VENDOR_CMD_NEED_NETDEV,
8707 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8708 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008709 {
8710 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8711 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8712 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8713 WIPHY_VENDOR_CMD_NEED_NETDEV,
8714 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8715 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008716 {
8717 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308718 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8719 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8720 WIPHY_VENDOR_CMD_NEED_NETDEV |
8721 WIPHY_VENDOR_CMD_NEED_RUNNING,
8722 .doit = hdd_cfg80211_get_station_cmd
8723 },
8724 {
8725 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8727 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8728 WIPHY_VENDOR_CMD_NEED_NETDEV |
8729 WIPHY_VENDOR_CMD_NEED_RUNNING,
8730 .doit = wlan_hdd_cfg80211_do_acs
8731 },
8732
8733 {
8734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8737 WIPHY_VENDOR_CMD_NEED_NETDEV,
8738 .doit = wlan_hdd_cfg80211_get_features
8739 },
8740#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8741 {
8742 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8743 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8744 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8745 WIPHY_VENDOR_CMD_NEED_NETDEV |
8746 WIPHY_VENDOR_CMD_NEED_RUNNING,
8747 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8748 },
8749#endif
8750#ifdef FEATURE_WLAN_EXTSCAN
8751 {
8752 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8753 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8754 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8755 WIPHY_VENDOR_CMD_NEED_NETDEV |
8756 WIPHY_VENDOR_CMD_NEED_RUNNING,
8757 .doit = wlan_hdd_cfg80211_set_passpoint_list
8758 },
8759 {
8760 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8761 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8762 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8763 WIPHY_VENDOR_CMD_NEED_NETDEV |
8764 WIPHY_VENDOR_CMD_NEED_RUNNING,
8765 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8766 },
8767 {
8768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8769 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8770 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8771 WIPHY_VENDOR_CMD_NEED_NETDEV |
8772 WIPHY_VENDOR_CMD_NEED_RUNNING,
8773 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8774 },
8775 {
8776 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8777 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8778 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8779 WIPHY_VENDOR_CMD_NEED_NETDEV |
8780 WIPHY_VENDOR_CMD_NEED_RUNNING,
8781 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8782 },
8783#endif /* FEATURE_WLAN_EXTSCAN */
8784 {
8785 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8786 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8787 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8788 WIPHY_VENDOR_CMD_NEED_NETDEV,
8789 .doit = wlan_hdd_cfg80211_get_wifi_info
8790 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008791#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008792 {
8793 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8794 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8795 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8796 WIPHY_VENDOR_CMD_NEED_NETDEV |
8797 WIPHY_VENDOR_CMD_NEED_RUNNING,
8798 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8799 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008800#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008801 {
8802 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8803 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8804 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8805 WIPHY_VENDOR_CMD_NEED_NETDEV,
8806 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8807 },
8808 {
8809 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8810 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8811 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8812 WIPHY_VENDOR_CMD_NEED_NETDEV,
8813 .doit = wlan_hdd_cfg80211_wifi_logger_start
8814 },
8815 {
8816 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8817 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8818 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8819 WIPHY_VENDOR_CMD_NEED_NETDEV,
8820 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8821 },
8822 {
8823 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8824 .info.subcmd =
8825 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8826 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8827 WIPHY_VENDOR_CMD_NEED_NETDEV |
8828 WIPHY_VENDOR_CMD_NEED_RUNNING,
8829 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8830 },
8831 {
8832 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8833 .info.subcmd =
8834 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8835 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8836 WIPHY_VENDOR_CMD_NEED_NETDEV |
8837 WIPHY_VENDOR_CMD_NEED_RUNNING,
8838 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8839 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008840#ifdef WLAN_FEATURE_TSF
8841 {
8842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8845 WIPHY_VENDOR_CMD_NEED_NETDEV |
8846 WIPHY_VENDOR_CMD_NEED_RUNNING,
8847 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8848 },
8849#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008850#ifdef FEATURE_WLAN_TDLS
8851 {
8852 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8853 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8854 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8855 WIPHY_VENDOR_CMD_NEED_NETDEV |
8856 WIPHY_VENDOR_CMD_NEED_RUNNING,
8857 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8858 },
8859#endif
8860#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8861 {
8862 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8863 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8864 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8865 WIPHY_VENDOR_CMD_NEED_NETDEV |
8866 WIPHY_VENDOR_CMD_NEED_RUNNING,
8867 .doit = wlan_hdd_cfg80211_offloaded_packets
8868 },
8869#endif
8870 {
8871 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8872 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8873 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8874 WIPHY_VENDOR_CMD_NEED_NETDEV |
8875 WIPHY_VENDOR_CMD_NEED_RUNNING,
8876 .doit = wlan_hdd_cfg80211_monitor_rssi
8877 },
8878 {
8879 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308880 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8881 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8882 WIPHY_VENDOR_CMD_NEED_NETDEV |
8883 WIPHY_VENDOR_CMD_NEED_RUNNING,
8884 .doit = wlan_hdd_cfg80211_set_ns_offload
8885 },
8886 {
8887 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008888 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8890 WIPHY_VENDOR_CMD_NEED_NETDEV |
8891 WIPHY_VENDOR_CMD_NEED_RUNNING,
8892 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8893 },
8894#ifdef WLAN_FEATURE_MEMDUMP
8895 {
8896 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8897 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8898 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8899 WIPHY_VENDOR_CMD_NEED_NETDEV |
8900 WIPHY_VENDOR_CMD_NEED_RUNNING,
8901 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8902 },
8903#endif /* WLAN_FEATURE_MEMDUMP */
8904 {
8905 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8906 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8907 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8908 WIPHY_VENDOR_CMD_NEED_NETDEV |
8909 WIPHY_VENDOR_CMD_NEED_RUNNING,
8910 .doit = wlan_hdd_cfg80211_vendor_scan
8911 },
8912
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05308913 /* Vendor abort scan */
8914 {
8915 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8916 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
8917 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8918 WIPHY_VENDOR_CMD_NEED_NETDEV |
8919 WIPHY_VENDOR_CMD_NEED_RUNNING,
8920 .doit = wlan_hdd_vendor_abort_scan
8921 },
8922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008923 /* OCB commands */
8924 {
8925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8928 WIPHY_VENDOR_CMD_NEED_NETDEV |
8929 WIPHY_VENDOR_CMD_NEED_RUNNING,
8930 .doit = wlan_hdd_cfg80211_ocb_set_config
8931 },
8932 {
8933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8934 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8935 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8936 WIPHY_VENDOR_CMD_NEED_NETDEV |
8937 WIPHY_VENDOR_CMD_NEED_RUNNING,
8938 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8939 },
8940 {
8941 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8942 .info.subcmd =
8943 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8944 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8945 WIPHY_VENDOR_CMD_NEED_NETDEV |
8946 WIPHY_VENDOR_CMD_NEED_RUNNING,
8947 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8948 },
8949 {
8950 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8951 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8952 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8953 WIPHY_VENDOR_CMD_NEED_NETDEV |
8954 WIPHY_VENDOR_CMD_NEED_RUNNING,
8955 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8956 },
8957 {
8958 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8959 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8960 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8961 WIPHY_VENDOR_CMD_NEED_NETDEV |
8962 WIPHY_VENDOR_CMD_NEED_RUNNING,
8963 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8964 },
8965 {
8966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8967 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8969 WIPHY_VENDOR_CMD_NEED_NETDEV |
8970 WIPHY_VENDOR_CMD_NEED_RUNNING,
8971 .doit = wlan_hdd_cfg80211_dcc_get_stats
8972 },
8973 {
8974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8975 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8976 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8977 WIPHY_VENDOR_CMD_NEED_NETDEV |
8978 WIPHY_VENDOR_CMD_NEED_RUNNING,
8979 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8980 },
8981 {
8982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8985 WIPHY_VENDOR_CMD_NEED_NETDEV |
8986 WIPHY_VENDOR_CMD_NEED_RUNNING,
8987 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8988 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308989 {
8990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8991 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8992 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8993 WIPHY_VENDOR_CMD_NEED_NETDEV |
8994 WIPHY_VENDOR_CMD_NEED_RUNNING,
8995 .doit = wlan_hdd_cfg80211_get_link_properties
8996 },
Peng Xu278d0122015-09-24 16:34:17 -07008997 {
Peng Xud2220962016-07-11 17:59:17 -07008998 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008999 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9000 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9001 WIPHY_VENDOR_CMD_NEED_NETDEV |
9002 WIPHY_VENDOR_CMD_NEED_RUNNING,
9003 .doit = wlan_hdd_cfg80211_set_ota_test
9004 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009005#ifdef FEATURE_LFR_SUBNET_DETECTION
9006 {
9007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9010 WIPHY_VENDOR_CMD_NEED_NETDEV |
9011 WIPHY_VENDOR_CMD_NEED_RUNNING,
9012 .doit = wlan_hdd_cfg80211_set_gateway_params
9013 },
9014#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009015 {
Peng Xud2220962016-07-11 17:59:17 -07009016 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009017 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9019 WIPHY_VENDOR_CMD_NEED_NETDEV |
9020 WIPHY_VENDOR_CMD_NEED_RUNNING,
9021 .doit = wlan_hdd_cfg80211_txpower_scale
9022 },
9023 {
9024 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9025 .info.subcmd =
9026 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9027 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9028 WIPHY_VENDOR_CMD_NEED_NETDEV |
9029 WIPHY_VENDOR_CMD_NEED_RUNNING,
9030 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9031 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309032 {
9033 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9034 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9035 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9036 WIPHY_VENDOR_CMD_NEED_NETDEV |
9037 WIPHY_VENDOR_CMD_NEED_RUNNING,
9038 .doit = wlan_hdd_cfg80211_bpf_offload
9039 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309040 {
9041 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309042 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9043 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9044 WIPHY_VENDOR_CMD_NEED_NETDEV |
9045 WIPHY_VENDOR_CMD_NEED_RUNNING,
9046 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9047 },
9048 {
9049 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309050 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9051 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9052 WIPHY_VENDOR_CMD_NEED_NETDEV |
9053 WIPHY_VENDOR_CMD_NEED_RUNNING,
9054 .doit = wlan_hdd_cfg80211_sta_roam_policy
9055 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309056#ifdef FEATURE_WLAN_CH_AVOID
9057 {
9058 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9059 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9060 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9061 WIPHY_VENDOR_CMD_NEED_NETDEV |
9062 WIPHY_VENDOR_CMD_NEED_RUNNING,
9063 .doit = wlan_hdd_cfg80211_avoid_freq
9064 },
9065#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309066 {
9067 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309068 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9069 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9070 WIPHY_VENDOR_CMD_NEED_NETDEV |
9071 WIPHY_VENDOR_CMD_NEED_RUNNING,
9072 .doit = wlan_hdd_cfg80211_sap_configuration_set
9073 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009074 {
Peng Xu4225c152016-07-14 21:18:14 -07009075 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009076 .info.subcmd =
9077 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9078 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9079 WIPHY_VENDOR_CMD_NEED_NETDEV |
9080 WIPHY_VENDOR_CMD_NEED_RUNNING,
9081 .doit = wlan_hdd_cfg80211_p2p_lo_start
9082 },
9083 {
9084 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9085 .info.subcmd =
9086 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9087 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9088 WIPHY_VENDOR_CMD_NEED_NETDEV |
9089 WIPHY_VENDOR_CMD_NEED_RUNNING,
9090 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9091 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309092 {
9093 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9094 .info.subcmd =
9095 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9096 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9097 WIPHY_VENDOR_CMD_NEED_NETDEV |
9098 WIPHY_VENDOR_CMD_NEED_RUNNING,
9099 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9100 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009101#ifdef WLAN_FEATURE_NAN_DATAPATH
9102 {
9103 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9104 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9105 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9106 WIPHY_VENDOR_CMD_NEED_NETDEV |
9107 WIPHY_VENDOR_CMD_NEED_RUNNING,
9108 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9109 },
9110#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309111 {
9112 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9113 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9114 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9115 WIPHY_VENDOR_CMD_NEED_NETDEV |
9116 WIPHY_VENDOR_CMD_NEED_RUNNING,
9117 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9118 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309119 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309120 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9121 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9122 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9123 WIPHY_VENDOR_CMD_NEED_NETDEV |
9124 WIPHY_VENDOR_CMD_NEED_RUNNING,
9125 .doit = wlan_hdd_cfg80211_get_bus_size
9126 },
9127 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309128 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9129 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9130 WIPHY_VENDOR_CMD_NEED_NETDEV |
9131 WIPHY_VENDOR_CMD_NEED_RUNNING,
9132 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309133 },
9134 {
9135 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9136 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9137 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9138 WIPHY_VENDOR_CMD_NEED_NETDEV |
9139 WIPHY_VENDOR_CMD_NEED_RUNNING,
9140 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309141 },
9142#ifdef WLAN_FEATURE_DISA
9143 {
9144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9145 .info.subcmd =
9146 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
9147 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9148 WIPHY_VENDOR_CMD_NEED_NETDEV |
9149 WIPHY_VENDOR_CMD_NEED_RUNNING,
9150 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
9151 },
9152#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009153#ifdef FEATURE_WLAN_TDLS
9154 {
9155 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9156 .info.subcmd =
9157 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
9158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9159 WIPHY_VENDOR_CMD_NEED_NETDEV |
9160 WIPHY_VENDOR_CMD_NEED_RUNNING,
9161 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009162 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009163#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009164 {
9165 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9166 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
9167 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9168 WIPHY_VENDOR_CMD_NEED_RUNNING,
9169 .doit = wlan_hdd_cfg80211_set_sar_power_limits
9170 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309171 {
9172 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9173 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
9174 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9175 WIPHY_VENDOR_CMD_NEED_NETDEV |
9176 WIPHY_VENDOR_CMD_NEED_RUNNING,
9177 .doit = wlan_hdd_cfg80211_set_trace_level
9178 },
9179
Paul Zhang3a210c52016-12-08 10:18:12 +08009180#ifdef WLAN_UMAC_CONVERGENCE
9181 COMMON_VENDOR_COMMANDS
9182#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009183};
9184
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309185#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
9186 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
9187 defined(FEATURE_WLAN_SCAN_PNO)
9188/**
9189 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
9190 * @wiphy: pointer to wiphy
9191 * @config: pointer to config
9192 *
9193 * Return: None
9194 */
9195static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9196 struct hdd_config *config)
9197{
9198 if (config->configPNOScanSupport) {
9199 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9200 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
9201 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
9202 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
9203 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
9204 if (config->max_sched_scan_plan_interval)
9205 wiphy->max_sched_scan_plan_interval =
9206 config->max_sched_scan_plan_interval;
9207 if (config->max_sched_scan_plan_iterations)
9208 wiphy->max_sched_scan_plan_iterations =
9209 config->max_sched_scan_plan_iterations;
9210 }
9211}
9212#else
9213static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9214 struct hdd_config *config)
9215{
9216}
9217#endif
9218
9219
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009220/**
9221 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
9222 * @priv_size: Size of the hdd context.
9223 *
9224 * Allocate wiphy context and hdd context.
9225 *
9226 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009227 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009228hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009229{
9230 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009231 hdd_context_t *hdd_ctx;
9232
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009233 ENTER();
9234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009235 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
9236
9237 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009238 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009239 return NULL;
9240 }
9241
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009242 hdd_ctx = wiphy_priv(wiphy);
9243
9244 hdd_ctx->wiphy = wiphy;
9245
9246 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009247}
9248
9249/*
9250 * FUNCTION: wlan_hdd_cfg80211_update_band
9251 * This function is called from the supplicant through a
9252 * private ioctl to change the band value
9253 */
9254int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
9255{
9256 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07009257 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009258
9259 ENTER();
9260
Dustin Browna30892e2016-10-12 17:28:36 -07009261 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009262
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009263 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009264 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009265
9266 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9267 struct ieee80211_supported_band *band = wiphy->bands[i];
9268
9269 channelEnabledState =
9270 cds_get_channel_state(band->channels[j].
9271 hw_value);
9272
Dustin Browna30892e2016-10-12 17:28:36 -07009273 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009274 /* 5G only */
9275#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9276 /* Enable Social channels for P2P */
9277 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9278 (band->channels[j].center_freq)
9279 && CHANNEL_STATE_ENABLE ==
9280 channelEnabledState)
9281 band->channels[j].flags &=
9282 ~IEEE80211_CHAN_DISABLED;
9283 else
9284#endif
9285 band->channels[j].flags |=
9286 IEEE80211_CHAN_DISABLED;
9287 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009288 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009289 eCSR_BAND_24 == eBand) {
9290 /* 2G only */
9291 band->channels[j].flags |=
9292 IEEE80211_CHAN_DISABLED;
9293 continue;
9294 }
9295
Amar Singhal6842e8f2016-02-23 16:30:32 -08009296 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009297 band->channels[j].flags &=
9298 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 }
9300 }
9301 return 0;
9302}
9303
Peng Xuacfdda12017-02-06 16:15:38 -08009304#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009305/*
9306 * FUNCTION: wlan_hdd_cfg80211_init
9307 * This function is called by hdd_wlan_startup()
9308 * during initialization.
9309 * This function is used to initialize and register wiphy structure.
9310 */
9311int wlan_hdd_cfg80211_init(struct device *dev,
9312 struct wiphy *wiphy, struct hdd_config *pCfg)
9313{
9314 int i, j;
9315 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9316
9317 ENTER();
9318
9319 /* Now bind the underlying wlan device with wiphy */
9320 set_wiphy_dev(wiphy, dev);
9321
9322 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
9323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009324#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9325 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009326 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009327#else
9328 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009329 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009330#endif
9331
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009332 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
9333 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
9334 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
9335#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
9336 | WIPHY_FLAG_4ADDR_STATION
9337#endif
9338 | WIPHY_FLAG_OFFCHAN_TX;
9339
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9341 wiphy->wowlan = &wowlan_support_cfg80211_init;
9342#else
9343 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
9344 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
9345 wiphy->wowlan.pattern_min_len = 1;
9346 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
9347#endif
9348
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07009349 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009350#ifdef FEATURE_WLAN_ESE
9351 || pCfg->isEseIniFeatureEnabled
9352#endif
9353 ) {
9354 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9355 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009356#ifdef FEATURE_WLAN_TDLS
9357 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
9358 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
9359#endif
9360
9361 wiphy->features |= NL80211_FEATURE_HT_IBSS;
9362
Naveen Rawatc77e6e72016-08-05 15:19:03 -07009363#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
9364 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
9365#endif
9366
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309367 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009368
9369#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05309370 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009371#endif
9372
9373 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009374 * driver can still register regulatory callback and
9375 * it will get regulatory settings in wiphy->band[], but
9376 * driver need to determine what to do with both
9377 * regulatory settings
9378 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009379
9380 wiphy->reg_notifier = hdd_reg_notifier;
9381
9382#if defined QCA_WIFI_FTM
9383}
9384#endif
9385
9386 wiphy->max_scan_ssids = MAX_SCAN_SSID;
9387
9388 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
9389
9390 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
9391
Arun Khandavallifae92942016-08-01 13:31:08 +05309392 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
9393 | BIT(NL80211_IFTYPE_ADHOC)
9394 | BIT(NL80211_IFTYPE_P2P_CLIENT)
9395 | BIT(NL80211_IFTYPE_P2P_GO)
9396 | BIT(NL80211_IFTYPE_AP)
9397 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398
Arun Khandavallifae92942016-08-01 13:31:08 +05309399 if (pCfg->advertiseConcurrentOperation) {
9400 if (pCfg->enableMCC) {
9401 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07009402
Arun Khandavallifae92942016-08-01 13:31:08 +05309403 for (i = 0;
9404 i < ARRAY_SIZE(wlan_hdd_iface_combination);
9405 i++) {
9406 if (!pCfg->allowMCCGODiffBI)
9407 wlan_hdd_iface_combination[i].
9408 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009409 }
9410 }
9411 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05309412 ARRAY_SIZE(wlan_hdd_iface_combination);
9413 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009414 }
9415
9416 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009417 * on ini values
9418 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009419 if (!pCfg->ShortGI20MhzEnable) {
9420 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
9421 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009422 }
9423
9424 if (!pCfg->ShortGI40MhzEnable) {
9425 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
9426 }
9427
9428 if (!pCfg->nChannelBondingMode5GHz) {
9429 wlan_hdd_band_5_ghz.ht_cap.cap &=
9430 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
9431 }
9432
Abhishek Singhf512bf32016-05-04 16:47:46 +05309433 /*
9434 * In case of static linked driver at the time of driver unload,
9435 * module exit doesn't happens. Module cleanup helps in cleaning
9436 * of static memory.
9437 * If driver load happens statically, at the time of driver unload,
9438 * wiphy flags don't get reset because of static memory.
9439 * It's better not to store channel in static memory.
9440 */
Dustin Browna30892e2016-10-12 17:28:36 -07009441 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
9442 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309443 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009444 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309445 hdd_err("Not enough memory to allocate channels");
9446 return -ENOMEM;
9447 }
Dustin Browna30892e2016-10-12 17:28:36 -07009448 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309449 &hdd_channels_2_4_ghz[0],
9450 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05309451 if ((hdd_is_5g_supported(pHddCtx)) &&
9452 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
9453 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
9454 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
9455 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07009456 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
9457 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309458 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009459 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309460 hdd_err("Not enough memory to allocate channels");
9461 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07009462 bands[NL80211_BAND_2GHZ]->channels);
9463 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05309464 return -ENOMEM;
9465 }
Dustin Browna30892e2016-10-12 17:28:36 -07009466 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309467 &hdd_channels_5_ghz[0],
9468 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009469 }
9470
Dustin Browna30892e2016-10-12 17:28:36 -07009471 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009472
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009473 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009474 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009475
9476 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9477 struct ieee80211_supported_band *band = wiphy->bands[i];
9478
Dustin Browna30892e2016-10-12 17:28:36 -07009479 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009480 eCSR_BAND_5G == pCfg->nBandCapability) {
9481 /* 5G only */
9482#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9483 /* Enable social channels for P2P */
9484 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9485 (band->channels[j].center_freq))
9486 band->channels[j].flags &=
9487 ~IEEE80211_CHAN_DISABLED;
9488 else
9489#endif
9490 band->channels[j].flags |=
9491 IEEE80211_CHAN_DISABLED;
9492 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009493 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009494 eCSR_BAND_24 == pCfg->nBandCapability) {
9495 /* 2G only */
9496 band->channels[j].flags |=
9497 IEEE80211_CHAN_DISABLED;
9498 continue;
9499 }
9500 }
9501 }
9502 /*Initialise the supported cipher suite details */
9503 wiphy->cipher_suites = hdd_cipher_suites;
9504 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
9505
9506 /*signal strength in mBm (100*dBm) */
9507 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9508 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
9509
Anurag Chouhan6d760662016-02-20 16:05:43 +05309510 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009511 wiphy->n_vendor_commands =
9512 ARRAY_SIZE(hdd_wiphy_vendor_commands);
9513 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
9514
9515 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
9516 wiphy->n_vendor_events =
9517 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
9518 }
9519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009520 if (pCfg->enableDFSMasterCap) {
9521 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
9522 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009523
9524 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
9525
9526#ifdef QCA_HT_2040_COEX
9527 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9528#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309529 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309530 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -08009531 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009533 EXIT();
9534 return 0;
9535}
9536
Abhishek Singhf512bf32016-05-04 16:47:46 +05309537/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009538 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9539 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309540 *
9541 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309542 * memory allocated in wlan_hdd_cfg80211_init also
9543 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309544 *
9545 * Return: void
9546 */
9547void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9548{
9549 int i;
9550
Dustin Browna30892e2016-10-12 17:28:36 -07009551 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309552 if (NULL != wiphy->bands[i] &&
9553 (NULL != wiphy->bands[i]->channels)) {
9554 qdf_mem_free(wiphy->bands[i]->channels);
9555 wiphy->bands[i]->channels = NULL;
9556 }
9557 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309558 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309559}
9560
Yingying Tang80e15f32016-09-27 18:23:01 +08009561/**
9562 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9563 * @hdd_ctx: HDD context
9564 *
9565 * this function will update capabilities for supported bands
9566 *
9567 * Return: void
9568 */
9569static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9570{
9571 uint32_t val32;
9572 uint16_t val16;
9573 tSirMacHTCapabilityInfo *ht_cap_info;
9574 QDF_STATUS status;
9575
9576 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9577 if (QDF_STATUS_SUCCESS != status) {
9578 hdd_err("could not get HT capability info");
9579 val32 = 0;
9580 }
9581 val16 = (uint16_t)val32;
9582 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9583
9584 if (ht_cap_info->txSTBC == true) {
9585 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9586 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9587 IEEE80211_HT_CAP_TX_STBC;
9588 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9589 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9590 IEEE80211_HT_CAP_TX_STBC;
9591 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009592
9593 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9594 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9595 vht_cap.vht_supported = 0;
9596 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9597 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9598 vht_cap.vht_supported = 0;
9599 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9600 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009601}
9602
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309604 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009605 * initialization. In wlan_hdd_cfg80211_init, only the
9606 * default values will be initialized. The final initialization
9607 * of all required members can be done here.
9608 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009609void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610{
Yingying Tang80e15f32016-09-27 18:23:01 +08009611 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9612
9613 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009614}
9615
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009616/**
9617 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9618 * @cfg: hdd cfg
9619 *
9620 * this function update 11n mode in hdd cfg
9621 *
9622 * Return: void
9623 */
9624void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9625{
9626 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9627 hdd_notice("support 11ac");
9628 } else {
9629 hdd_notice("not support 11ac");
9630 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9631 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9632 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9633 cfg->sap_p2p_11ac_override = 0;
9634 }
9635 }
9636}
9637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009638/* In this function we are registering wiphy. */
9639int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9640{
9641 ENTER();
9642 /* Register our wiphy dev with cfg80211 */
9643 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009644 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009645 return -EIO;
9646 }
9647
9648 EXIT();
9649 return 0;
9650}
9651
9652/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009653 * HDD function to update wiphy capability based on target offload status.
9654 *
9655 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
9656 * capability even before downloading firmware to the target. In discrete
9657 * case, host will get know certain offload capability (say sched_scan
9658 * caps) only after downloading firmware to the target and target boots up.
9659 * This function is used to override setting done in wlan_hdd_cfg80211_init()
9660 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009661 */
9662void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9663{
9664#ifdef FEATURE_WLAN_SCAN_PNO
9665 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9666 struct hdd_config *pCfg = pHddCtx->config;
9667
9668 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9669 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009670 * have PNO support.
9671 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009672 if (!pCfg->PnoOffload) {
9673 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9674 wiphy->max_sched_scan_ssids = 0;
9675 wiphy->max_match_sets = 0;
9676 wiphy->max_sched_scan_ie_len = 0;
9677 }
9678#endif
9679}
9680
9681/* This function registers for all frame which supplicant is interested in */
9682void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9683{
9684 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9685 /* Register for all P2P action, public action etc frames */
9686 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9687
9688 ENTER();
9689
Abhishek Singh7996eb72015-12-30 17:24:02 +05309690 /* Register frame indication call back */
9691 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9692
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309693 /* Register for p2p ack indication */
9694 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9695
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009696 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009697 * initialized. Once we will move to 2.6.37 kernel, in which we have
9698 * frame register ops, we will move this code as a part of that
9699 */
9700
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701 /* GAS Initial Request */
9702 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9703 (uint8_t *) GAS_INITIAL_REQ,
9704 GAS_INITIAL_REQ_SIZE);
9705
9706 /* GAS Initial Response */
9707 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9708 (uint8_t *) GAS_INITIAL_RSP,
9709 GAS_INITIAL_RSP_SIZE);
9710
9711 /* GAS Comeback Request */
9712 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9713 (uint8_t *) GAS_COMEBACK_REQ,
9714 GAS_COMEBACK_REQ_SIZE);
9715
9716 /* GAS Comeback Response */
9717 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9718 (uint8_t *) GAS_COMEBACK_RSP,
9719 GAS_COMEBACK_RSP_SIZE);
9720
9721 /* P2P Public Action */
9722 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9723 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9724 P2P_PUBLIC_ACTION_FRAME_SIZE);
9725
9726 /* P2P Action */
9727 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9728 (uint8_t *) P2P_ACTION_FRAME,
9729 P2P_ACTION_FRAME_SIZE);
9730
9731 /* WNM BSS Transition Request frame */
9732 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9733 (uint8_t *) WNM_BSS_ACTION_FRAME,
9734 WNM_BSS_ACTION_FRAME_SIZE);
9735
9736 /* WNM-Notification */
9737 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9738 (uint8_t *) WNM_NOTIFICATION_FRAME,
9739 WNM_NOTIFICATION_FRAME_SIZE);
9740}
9741
9742void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9743{
9744 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9745 /* Register for all P2P action, public action etc frames */
9746 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9747
9748 ENTER();
9749
9750 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009751 * initialized. Once we will move to 2.6.37 kernel, in which we have
9752 * frame register ops, we will move this code as a part of that
9753 */
9754
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009755 /* GAS Initial Request */
9756
9757 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9758 (uint8_t *) GAS_INITIAL_REQ,
9759 GAS_INITIAL_REQ_SIZE);
9760
9761 /* GAS Initial Response */
9762 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9763 (uint8_t *) GAS_INITIAL_RSP,
9764 GAS_INITIAL_RSP_SIZE);
9765
9766 /* GAS Comeback Request */
9767 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9768 (uint8_t *) GAS_COMEBACK_REQ,
9769 GAS_COMEBACK_REQ_SIZE);
9770
9771 /* GAS Comeback Response */
9772 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9773 (uint8_t *) GAS_COMEBACK_RSP,
9774 GAS_COMEBACK_RSP_SIZE);
9775
9776 /* P2P Public Action */
9777 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9778 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9779 P2P_PUBLIC_ACTION_FRAME_SIZE);
9780
9781 /* P2P Action */
9782 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9783 (uint8_t *) P2P_ACTION_FRAME,
9784 P2P_ACTION_FRAME_SIZE);
9785
9786 /* WNM-Notification */
9787 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9788 (uint8_t *) WNM_NOTIFICATION_FRAME,
9789 WNM_NOTIFICATION_FRAME_SIZE);
9790}
9791
9792#ifdef FEATURE_WLAN_WAPI
9793void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9794 const uint8_t *mac_addr, const uint8_t *key,
9795 int key_Len)
9796{
9797 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9798 tCsrRoamSetKey setKey;
9799 bool isConnected = true;
9800 int status = 0;
9801 uint32_t roamId = 0xFF;
9802 uint8_t *pKeyPtr = NULL;
9803 int n = 0;
9804
Jeff Johnson46b40792016-06-29 14:03:14 -07009805 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009806 hdd_device_mode_to_string(pAdapter->device_mode),
9807 pAdapter->device_mode);
9808
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309809 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810 setKey.keyId = key_index; /* Store Key ID */
9811 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9812 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9813 setKey.paeRole = 0; /* the PAE role */
9814 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309815 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009816 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309817 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818 }
9819 setKey.keyLength = key_Len;
9820 pKeyPtr = setKey.Key;
9821 memcpy(pKeyPtr, key, key_Len);
9822
Jeff Johnson46b40792016-06-29 14:03:14 -07009823 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009824 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009825 hdd_notice("WAPI KEY Data[%d]:%02x ",
9826 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009827
9828 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9829 if (isConnected) {
9830 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9831 pAdapter->sessionId, &setKey, &roamId);
9832 }
9833 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009834 hdd_err("sme_roam_set_key returned ERROR status= %d",
9835 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009836 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9837 }
9838}
9839#endif /* FEATURE_WLAN_WAPI */
9840
9841uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9842 uint8_t eid)
9843{
9844 int left = length;
9845 uint8_t *ptr = (uint8_t *)ies_ptr;
9846 uint8_t elem_id, elem_len;
9847
9848 while (left >= 2) {
9849 elem_id = ptr[0];
9850 elem_len = ptr[1];
9851 left -= 2;
9852 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009853 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854 eid, elem_len, left);
9855 return NULL;
9856 }
9857 if (elem_id == eid) {
9858 return ptr;
9859 }
9860
9861 left -= elem_len;
9862 ptr += (elem_len + 2);
9863 }
9864 return NULL;
9865}
9866
9867/*
9868 * FUNCTION: wlan_hdd_validate_operation_channel
9869 * called by wlan_hdd_cfg80211_start_bss() and
9870 * wlan_hdd_set_channel()
9871 * This function validates whether given channel is part of valid
9872 * channel list.
9873 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309874QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875 int channel)
9876{
9877
9878 uint32_t num_ch = 0;
9879 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9880 u32 indx = 0;
9881 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9882 uint8_t fValidChannel = false, count = 0;
9883 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9884
9885 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9886
9887 if (hdd_pConfig_ini->sapAllowAllChannel) {
9888 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009889 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009890 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009891 fValidChannel = true;
9892 break;
9893 }
9894 }
9895 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009896 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309897 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009898 }
9899 } else {
9900 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9901 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009902 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309903 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009904 }
9905 for (indx = 0; indx < num_ch; indx++) {
9906 if (channel == valid_ch[indx]) {
9907 break;
9908 }
9909 }
9910
9911 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009912 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309913 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009914 }
9915 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309916 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009917
9918}
9919
9920#ifdef DHCP_SERVER_OFFLOAD
9921static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9922{
9923 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9924 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9925 uint8_t numEntries = 0;
9926 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9927 uint8_t num;
9928 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309929 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009931 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009932 return;
9933 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009934 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9935 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9936 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9937 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9938 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9939 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009940 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009941 goto end;
9942 }
9943 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009944 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009945 goto end;
9946 }
9947 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009948 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009949 goto end;
9950 }
9951 for (num = 0; num < numEntries; num++) {
9952 temp = srv_ip[num];
9953 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9954 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309955 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009956 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009957 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009958 goto end;
9959 }
Jeff Johnson77848112016-06-29 14:52:06 -07009960 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309962 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009963 return;
9964}
9965#endif /* DHCP_SERVER_OFFLOAD */
9966
9967static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9968 struct net_device *dev,
9969 struct bss_parameters *params)
9970{
9971 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9972 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9973 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309974 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009975
9976 ENTER();
9977
Anurag Chouhan6d760662016-02-20 16:05:43 +05309978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009980 return -EINVAL;
9981 }
9982
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309983 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9984 hdd_err("invalid session id: %d", pAdapter->sessionId);
9985 return -EINVAL;
9986 }
9987
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309988 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009989 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9990 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009991 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 hdd_device_mode_to_string(pAdapter->device_mode),
9993 pAdapter->device_mode, params->ap_isolate);
9994
9995 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9996 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309997 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009998 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009999
Krunal Sonib4326f22016-03-10 13:05:51 -080010000 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10001 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010002 return -EOPNOTSUPP;
10003 }
10004
10005 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010006 * want to update this parameter
10007 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010008 if (-1 != params->ap_isolate) {
10009 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10010 !!params->ap_isolate;
10011
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010012 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010013 pAdapter->sessionId,
10014 pAdapter->sessionCtx.
10015 ap.
10016 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010017 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010018 ret = -EINVAL;
10019 }
10020 }
10021
10022 EXIT();
10023 return ret;
10024}
10025
Krunal Soni8c37e322016-02-03 16:08:37 -080010026/**
10027 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10028 * @ndev: pointer to net device provided by supplicant
10029 * @type: type of the interface, upper layer wanted to change
10030 *
10031 * Upper layer provides the new interface mode that needs to be changed
10032 * for given net device
10033 *
10034 * Return: success or failure in terms of integer value
10035 */
10036static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010037 enum nl80211_iftype type)
10038{
Krunal Soni8c37e322016-02-03 16:08:37 -080010039 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10040 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10041 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010042 hdd_wext_state_t *wext;
10043 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010044 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010045
10046 ENTER();
10047
Krunal Soni8c37e322016-02-03 16:08:37 -080010048 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010049 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010050 return 0;
10051 }
10052
10053 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010054 hdd_stop_adapter(hdd_ctx, adapter, true);
10055 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056 wdev->iftype = type;
10057 /*Check for sub-string p2p to confirm its a p2p interface */
10058 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010059 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010060 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010061 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010062 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010063 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010064 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010065 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010066 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010067 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010068 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010069 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10070 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010071 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10072 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010073 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010074 adapter->scan_info.scanAddIE.length;
10075 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010076 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010077 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10078 wext->roamProfile.phyMode =
10079 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10080 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010081 EXIT();
10082 return status;
10083}
10084
10085static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10086 struct net_device *dev,
10087 struct bss_parameters *params)
10088{
10089 int ret;
10090
10091 cds_ssr_protect(__func__);
10092 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10093 cds_ssr_unprotect(__func__);
10094
10095 return ret;
10096}
10097
10098/* FUNCTION: wlan_hdd_change_country_code_cd
10099 * to wait for contry code completion
10100 */
10101void *wlan_hdd_change_country_code_cb(void *pAdapter)
10102{
10103 hdd_adapter_t *call_back_pAdapter = pAdapter;
10104 complete(&call_back_pAdapter->change_country_code);
10105 return NULL;
10106}
10107
Rajeev Kumar98edb772016-01-19 12:42:19 -080010108/**
10109 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10110 * @wiphy: Pointer to the wiphy structure
10111 * @ndev: Pointer to the net device
10112 * @type: Interface type
10113 * @flags: Flags for change interface
10114 * @params: Pointer to change interface parameters
10115 *
10116 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 */
10118static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10119 struct net_device *ndev,
10120 enum nl80211_iftype type,
10121 u32 *flags,
10122 struct vif_params *params)
10123{
10124 struct wireless_dev *wdev;
10125 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10126 hdd_context_t *pHddCtx;
10127 tCsrRoamProfile *pRoamProfile = NULL;
10128 eCsrRoamBssType LastBSSType;
10129 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010130 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131 int status;
10132
10133 ENTER();
10134
Anurag Chouhan6d760662016-02-20 16:05:43 +053010135 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010136 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010137 return -EINVAL;
10138 }
10139
10140 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10141 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010142 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010143 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010144
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010145 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010146 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
10147 pAdapter->sessionId, type));
10148
Jeff Johnson77848112016-06-29 14:52:06 -070010149 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010150 pAdapter->device_mode, type);
10151
Arun Khandavallifae92942016-08-01 13:31:08 +053010152 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
10153 if (status) {
10154 hdd_err("Failed to start modules");
10155 return -EINVAL;
10156 }
10157
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010158 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010159 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
10160 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010161 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010162 return -EINVAL;
10163 }
10164
10165 pConfig = pHddCtx->config;
10166 wdev = ndev->ieee80211_ptr;
10167
10168 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010169 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170
10171 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
10172
Krunal Sonib4326f22016-03-10 13:05:51 -080010173 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10174 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
10175 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
10176 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010177 hdd_wext_state_t *pWextState =
10178 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10179
10180 pRoamProfile = &pWextState->roamProfile;
10181 LastBSSType = pRoamProfile->BSSType;
10182
10183 switch (type) {
10184 case NL80211_IFTYPE_STATION:
10185 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080010186 case NL80211_IFTYPE_ADHOC:
10187 if (type == NL80211_IFTYPE_ADHOC) {
10188 wlan_hdd_tdls_exit(pAdapter);
10189 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070010190 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080010191 }
10192 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
10193 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010194 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010195 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010196 if (hdd_start_adapter(pAdapter)) {
10197 hdd_err("Failed to start adapter :%d",
10198 pAdapter->device_mode);
10199 return -EINVAL;
10200 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010202 case NL80211_IFTYPE_AP:
10203 case NL80211_IFTYPE_P2P_GO:
10204 {
Jeff Johnson77848112016-06-29 14:52:06 -070010205 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010206 (type ==
10207 NL80211_IFTYPE_AP) ? "SoftAP" :
10208 "P2pGo");
10209
10210 /* Cancel any remain on channel for GO mode */
10211 if (NL80211_IFTYPE_P2P_GO == type) {
10212 wlan_hdd_cancel_existing_remain_on_channel
10213 (pAdapter);
10214 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215
Arun Khandavallifae92942016-08-01 13:31:08 +053010216 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010217 /* De-init the adapter */
10218 hdd_deinit_adapter(pHddCtx, pAdapter, true);
10219 memset(&pAdapter->sessionCtx, 0,
10220 sizeof(pAdapter->sessionCtx));
10221 pAdapter->device_mode =
10222 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080010223 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
10224 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010225
10226 /*
10227 * Fw will take care incase of concurrency
10228 */
10229
Krunal Sonib4326f22016-03-10 13:05:51 -080010230 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010231 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010232 /* To meet Android requirements create
10233 * a randomized MAC address of the
10234 * form 02:1A:11:Fx:xx:xx
10235 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010236 get_random_bytes(&ndev->dev_addr[3], 3);
10237 ndev->dev_addr[0] = 0x02;
10238 ndev->dev_addr[1] = 0x1A;
10239 ndev->dev_addr[2] = 0x11;
10240 ndev->dev_addr[3] |= 0xF0;
10241 memcpy(pAdapter->macAddressCurrent.
10242 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010243 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244 pr_info("wlan: Generated HotSpot BSSID "
10245 MAC_ADDRESS_STR "\n",
10246 MAC_ADDR_ARRAY(ndev->dev_addr));
10247 }
10248
10249 hdd_set_ap_ops(pAdapter->dev);
10250
Arun Khandavallifae92942016-08-01 13:31:08 +053010251 if (hdd_start_adapter(pAdapter)) {
10252 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253 return -EINVAL;
10254 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010255 /* Interface type changed update in wiphy structure */
10256 if (wdev) {
10257 wdev->iftype = type;
10258 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010259 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010260 return -EINVAL;
10261 }
10262 goto done;
10263 }
10264
10265 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010266 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010267 type);
10268 return -EOPNOTSUPP;
10269 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010270 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10271 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010272 switch (type) {
10273 case NL80211_IFTYPE_STATION:
10274 case NL80211_IFTYPE_P2P_CLIENT:
10275 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080010276 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
10277 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010278 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010279 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010280 if (hdd_start_adapter(pAdapter)) {
10281 hdd_err("Failed to start adapter :%d",
10282 pAdapter->device_mode);
10283 return -EINVAL;
10284 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285 goto done;
10286
10287 case NL80211_IFTYPE_AP:
10288 case NL80211_IFTYPE_P2P_GO:
10289 wdev->iftype = type;
10290 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010291 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010292 goto done;
10293
10294 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010295 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010296 type);
10297 return -EOPNOTSUPP;
10298 }
10299 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010300 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301 pAdapter->device_mode);
10302 return -EOPNOTSUPP;
10303 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010304done:
10305 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010306 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010307
Jeff Johnson2ae6f712016-09-23 15:08:48 -070010308 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010309
10310 EXIT();
10311 return 0;
10312}
10313
Rajeev Kumar98edb772016-01-19 12:42:19 -080010314/**
10315 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10316 * @wiphy: Pointer to the wiphy structure
10317 * @ndev: Pointer to the net device
10318 * @type: Interface type
10319 * @flags: Flags for change interface
10320 * @params: Pointer to change interface parameters
10321 *
10322 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 */
10324static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10325 struct net_device *ndev,
10326 enum nl80211_iftype type,
10327 u32 *flags,
10328 struct vif_params *params)
10329{
10330 int ret;
10331
10332 cds_ssr_protect(__func__);
10333 ret =
10334 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
10335 cds_ssr_unprotect(__func__);
10336
10337 return ret;
10338}
10339
10340#ifdef FEATURE_WLAN_TDLS
10341static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
10342 int index, uint8_t match)
10343{
10344 int i;
10345 for (i = 0; i < index; i++) {
10346 if (arr[i] == match)
10347 return true;
10348 }
10349 return false;
10350}
10351#endif
10352
10353/**
10354 * __wlan_hdd_change_station() - change station
10355 * @wiphy: Pointer to the wiphy structure
10356 * @dev: Pointer to the net device.
10357 * @mac: bssid
10358 * @params: Pointer to station parameters
10359 *
10360 * Return: 0 for success, error number on failure.
10361 */
10362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10363static int __wlan_hdd_change_station(struct wiphy *wiphy,
10364 struct net_device *dev,
10365 const uint8_t *mac,
10366 struct station_parameters *params)
10367#else
10368static int __wlan_hdd_change_station(struct wiphy *wiphy,
10369 struct net_device *dev,
10370 uint8_t *mac,
10371 struct station_parameters *params)
10372#endif
10373{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010374 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010375 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10376 hdd_context_t *pHddCtx;
10377 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053010378 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010379#ifdef FEATURE_WLAN_TDLS
10380 tCsrStaParams StaParams = { 0 };
10381 uint8_t isBufSta = 0;
10382 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053010383 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010384#endif
10385 int ret;
10386
10387 ENTER();
10388
Anurag Chouhan6d760662016-02-20 16:05:43 +053010389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010390 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010391 return -EINVAL;
10392 }
10393
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010394 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010395 TRACE_CODE_HDD_CHANGE_STATION,
10396 pAdapter->sessionId, params->listen_interval));
10397
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010398 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10399 hdd_err("invalid session id: %d", pAdapter->sessionId);
10400 return -EINVAL;
10401 }
10402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10404 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010405 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010406 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010407
10408 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10409
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010410 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411
Krunal Sonib4326f22016-03-10 13:05:51 -080010412 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10413 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
10415 status =
10416 hdd_softap_change_sta_state(pAdapter,
10417 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080010418 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010419
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010420 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010421 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 return -EINVAL;
10423 }
10424 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010425 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10426 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010427#ifdef FEATURE_WLAN_TDLS
10428 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070010429
10430 if (cds_is_sub_20_mhz_enabled()) {
10431 hdd_err("TDLS not allowed with sub 20 MHz");
10432 return -EINVAL;
10433 }
10434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010435 StaParams.capability = params->capability;
10436 StaParams.uapsd_queues = params->uapsd_queues;
10437 StaParams.max_sp = params->max_sp;
10438
10439 /* Convert (first channel , number of channels) tuple to
10440 * the total list of channels. This goes with the assumption
10441 * that if the first channel is < 14, then the next channels
10442 * are an incremental of 1 else an incremental of 4 till the number
10443 * of channels.
10444 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010445 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010446 if (0 != params->supported_channels_len) {
10447 int i = 0, j = 0, k = 0, no_of_channels = 0;
10448 int num_unique_channels;
10449 int next;
10450 for (i = 0;
10451 i < params->supported_channels_len
10452 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
10453 int wifi_chan_index;
10454 if (!wlan_hdd_is_duplicate_channel
10455 (StaParams.supported_channels, j,
10456 params->supported_channels[i])) {
10457 StaParams.
10458 supported_channels[j] =
10459 params->
10460 supported_channels[i];
10461 } else {
10462 continue;
10463 }
10464 wifi_chan_index =
10465 ((StaParams.supported_channels[j] <=
10466 HDD_CHANNEL_14) ? 1 : 4);
10467 no_of_channels =
10468 params->supported_channels[i + 1];
10469
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010470 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 -080010471 StaParams.
10472 supported_channels[j],
10473 wifi_chan_index,
10474 no_of_channels);
10475 for (k = 1; k <= no_of_channels &&
10476 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
10477 k++) {
10478 next =
10479 StaParams.
10480 supported_channels[j] +
10481 wifi_chan_index;
10482 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
10483 StaParams.
10484 supported_channels[j
10485 +
10486 1]
10487 = next;
10488 } else {
10489 continue;
10490 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010491 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010492 j + 1,
10493 StaParams.
10494 supported_channels[j +
10495 1]);
10496 j += 1;
10497 }
10498 }
10499 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010500 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010501 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010502 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503 StaParams.
10504 supported_channels[i]);
10505 }
10506 if (MAX_CHANNEL < num_unique_channels)
10507 num_unique_channels = MAX_CHANNEL;
10508 StaParams.supported_channels_len =
10509 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010510 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511 StaParams.supported_channels_len);
10512 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010513 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010514 params->supported_oper_classes,
10515 params->supported_oper_classes_len);
10516 StaParams.supported_oper_classes_len =
10517 params->supported_oper_classes_len;
10518
10519 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010520 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010521 params->ext_capab,
10522 sizeof(StaParams.extn_capability));
10523
10524 if (NULL != params->ht_capa) {
10525 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010526 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010527 sizeof(tSirHTCap));
10528 }
10529
10530 StaParams.supported_rates_len =
10531 params->supported_rates_len;
10532
10533 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
10534 * The supported_rates array , for all the structures propogating till Add Sta
10535 * to the firmware has to be modified , if the supplicant (ieee80211) is
10536 * modified to send more rates.
10537 */
10538
10539 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10540 */
10541 if (StaParams.supported_rates_len >
10542 SIR_MAC_MAX_SUPP_RATES)
10543 StaParams.supported_rates_len =
10544 SIR_MAC_MAX_SUPP_RATES;
10545
10546 if (0 != StaParams.supported_rates_len) {
10547 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010548 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010549 params->supported_rates,
10550 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010551 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010552 StaParams.supported_rates_len);
10553 for (i = 0; i < StaParams.supported_rates_len;
10554 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010555 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556 StaParams.supported_rates[i]);
10557 }
10558
10559 if (NULL != params->vht_capa) {
10560 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010561 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562 params->vht_capa,
10563 sizeof(tSirVHTCap));
10564 }
10565
10566 if (0 != params->ext_capab_len) {
10567 /*Define A Macro : TODO Sunil */
10568 if ((1 << 4) & StaParams.extn_capability[3]) {
10569 isBufSta = 1;
10570 }
10571 /* TDLS Channel Switching Support */
10572 if ((1 << 6) & StaParams.extn_capability[3]) {
10573 isOffChannelSupported = 1;
10574 }
10575 }
10576
Nitesh Shah99934ac2016-09-05 15:54:08 +053010577 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010578 (params->ht_capa || params->vht_capa ||
10579 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010580 is_qos_wmm_sta = true;
10581
10582 hdd_notice("%s: TDLS Peer is QOS capable"
10583 " is_qos_wmm_sta= %d HTcapPresent = %d",
10584 __func__, is_qos_wmm_sta,
10585 StaParams.htcap_present);
10586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010587 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010588 &StaParams,
10589 isBufSta,
10590 isOffChannelSupported,
10591 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010592 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010593 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010594 return -EINVAL;
10595 }
10596
10597 status =
10598 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10599 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010600 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010601 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010602 return -EINVAL;
10603 }
10604 }
10605#endif
10606 }
10607 EXIT();
10608 return ret;
10609}
10610
10611/**
10612 * wlan_hdd_change_station() - cfg80211 change station handler function
10613 * @wiphy: Pointer to the wiphy structure
10614 * @dev: Pointer to the net device.
10615 * @mac: bssid
10616 * @params: Pointer to station parameters
10617 *
10618 * This is the cfg80211 change station handler function which invokes
10619 * the internal function @__wlan_hdd_change_station with
10620 * SSR protection.
10621 *
10622 * Return: 0 for success, error number on failure.
10623 */
10624#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10625static int wlan_hdd_change_station(struct wiphy *wiphy,
10626 struct net_device *dev,
10627 const u8 *mac,
10628 struct station_parameters *params)
10629#else
10630static int wlan_hdd_change_station(struct wiphy *wiphy,
10631 struct net_device *dev,
10632 u8 *mac,
10633 struct station_parameters *params)
10634#endif
10635{
10636 int ret;
10637
10638 cds_ssr_protect(__func__);
10639 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10640 cds_ssr_unprotect(__func__);
10641
10642 return ret;
10643}
10644
10645/*
10646 * FUNCTION: __wlan_hdd_cfg80211_add_key
10647 * This function is used to initialize the key information
10648 */
10649static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10650 struct net_device *ndev,
10651 u8 key_index, bool pairwise,
10652 const u8 *mac_addr,
10653 struct key_params *params)
10654{
10655 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10656 tCsrRoamSetKey setKey;
10657 int status;
10658 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010660 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661 hdd_context_t *pHddCtx;
10662 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10663
10664 ENTER();
10665
Anurag Chouhan6d760662016-02-20 16:05:43 +053010666 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010667 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010668 return -EINVAL;
10669 }
10670
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010671 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10672 hdd_err("invalid session id: %d", pAdapter->sessionId);
10673 return -EINVAL;
10674 }
10675
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010676 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010677 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10678 pAdapter->sessionId, params->key_len));
10679 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10680 status = wlan_hdd_validate_context(pHddCtx);
10681
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010682 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010683 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010684
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010685 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010686 hdd_device_mode_to_string(pAdapter->device_mode),
10687 pAdapter->device_mode);
10688
10689 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010690 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010691
10692 return -EINVAL;
10693 }
10694
10695 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010696 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697
10698 return -EINVAL;
10699 }
10700
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010701 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010702
10703 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010704 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010705 setKey.keyId = key_index;
10706 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010707 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708
10709 switch (params->cipher) {
10710 case WLAN_CIPHER_SUITE_WEP40:
10711 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10712 break;
10713
10714 case WLAN_CIPHER_SUITE_WEP104:
10715 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10716 break;
10717
10718 case WLAN_CIPHER_SUITE_TKIP:
10719 {
10720 u8 *pKey = &setKey.Key[0];
10721 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10722
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010723 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010724
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010725 /* Supplicant sends the 32bytes key in this order
10726 *
10727 * |--------------|----------|----------|
10728 * | Tk1 |TX-MIC | RX Mic |
10729 * |--------------|----------|----------|
10730 * <---16bytes---><--8bytes--><--8bytes-->
10731 *
10732 * Sme expects the 32 bytes key to be in the below order
10733 *
10734 * |--------------|----------|----------|
10735 * | Tk1 |RX-MIC | TX Mic |
10736 * |--------------|----------|----------|
10737 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010738 */
10739 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010740 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010741
10742 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010743 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010744
10745 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010746 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010747
10748 break;
10749 }
10750
10751 case WLAN_CIPHER_SUITE_CCMP:
10752 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10753 break;
10754
10755#ifdef FEATURE_WLAN_WAPI
10756 case WLAN_CIPHER_SUITE_SMS4:
10757 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010758 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10760 mac_addr, params->key,
10761 params->key_len);
10762 return 0;
10763 }
10764#endif
10765
10766#ifdef FEATURE_WLAN_ESE
10767 case WLAN_CIPHER_SUITE_KRK:
10768 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10769 break;
10770#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10771 case WLAN_CIPHER_SUITE_BTK:
10772 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10773 break;
10774#endif
10775#endif
10776
10777#ifdef WLAN_FEATURE_11W
10778 case WLAN_CIPHER_SUITE_AES_CMAC:
10779 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10780 break;
10781#endif
10782
10783 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010784 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010785 return -EOPNOTSUPP;
10786 }
10787
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010788 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010789
10790 if (!pairwise) {
10791 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010792 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010794 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010795 } else {
10796 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010797 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010798 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010799 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010800 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010801 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802 /* if a key is already installed, block all subsequent ones */
10803 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010804 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010805 return 0;
10806 }
10807
10808 setKey.keyDirection = eSIR_TX_RX;
10809 /*Set the group key */
10810 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10811 pAdapter->sessionId, &setKey, &roamId);
10812
10813 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010814 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010815 return -EINVAL;
10816 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010817 /* Save the keys here and call sme_roam_set_key for setting
10818 * the PTK after peer joins the IBSS network
10819 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010820 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010821 &setKey, sizeof(tCsrRoamSetKey));
10822
10823 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10824 return status;
10825 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010826 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10827 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010828 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10829 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010830 status = wlansap_set_key_sta(
10831 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010832 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010833 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010834 __LINE__, status);
10835 }
10836 }
10837
10838 /* Save the key in ap ctx for use on START_BASS and restart */
10839 if (pairwise ||
10840 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10841 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010842 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843 sizeof(tCsrRoamSetKey));
10844 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010845 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846 sizeof(tCsrRoamSetKey));
10847
Krunal Sonib4326f22016-03-10 13:05:51 -080010848 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10849 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 hdd_wext_state_t *pWextState =
10851 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10852 hdd_station_ctx_t *pHddStaCtx =
10853 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10854
10855 if (!pairwise) {
10856 /* set group key */
10857 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010858 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859 __func__, __LINE__);
10860 hdd_perform_roam_set_key_complete(pAdapter);
10861 }
10862 }
10863
10864 pWextState->roamProfile.Keys.KeyLength[key_index] =
10865 (u8) params->key_len;
10866
10867 pWextState->roamProfile.Keys.defaultIndex = key_index;
10868
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010869 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010870 KeyMaterial[key_index][0], params->key,
10871 params->key_len);
10872
10873 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10874
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010875 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010876 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10877 setKey.keyDirection);
10878
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010879 /* The supplicant may attempt to set the PTK once
10880 * pre-authentication is done. Save the key in the
10881 * UMAC and include it in the ADD BSS request
10882 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010883 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010885 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010886 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010888 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010889 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890 return -EINVAL;
10891 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892
10893 /* issue set key request to SME */
10894 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10895 pAdapter->sessionId, &setKey, &roamId);
10896
10897 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010898 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899 pHddStaCtx->roam_info.roamingState =
10900 HDD_ROAM_STATE_NONE;
10901 return -EINVAL;
10902 }
10903
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010904 /* in case of IBSS as there was no information
10905 * available about WEP keys during IBSS join, group
10906 * key intialized with NULL key, so re-initialize
10907 * group key with correct value
10908 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 if ((eCSR_BSS_TYPE_START_IBSS ==
10910 pWextState->roamProfile.BSSType)
10911 &&
10912 !((IW_AUTH_KEY_MGMT_802_1X ==
10913 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10914 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10915 pHddStaCtx->conn_info.authType)
10916 )
10917 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10918 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10919 )
10920 ) {
10921 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010922 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010924 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010925 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10926 setKey.keyDirection);
10927
10928 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10929 pAdapter->sessionId, &setKey,
10930 &roamId);
10931
10932 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010933 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010934 pHddStaCtx->roam_info.roamingState =
10935 HDD_ROAM_STATE_NONE;
10936 return -EINVAL;
10937 }
10938 }
10939 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010940 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 return 0;
10942}
10943
10944static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10945 struct net_device *ndev,
10946 u8 key_index, bool pairwise,
10947 const u8 *mac_addr,
10948 struct key_params *params)
10949{
10950 int ret;
10951 cds_ssr_protect(__func__);
10952 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10953 mac_addr, params);
10954 cds_ssr_unprotect(__func__);
10955
10956 return ret;
10957}
10958
10959/*
10960 * FUNCTION: __wlan_hdd_cfg80211_get_key
10961 * This function is used to get the key information
10962 */
10963static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10964 struct net_device *ndev,
10965 u8 key_index, bool pairwise,
10966 const u8 *mac_addr, void *cookie,
10967 void (*callback)(void *cookie,
10968 struct key_params *)
10969 )
10970{
10971 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10972 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10973 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10974 struct key_params params;
10975
10976 ENTER();
10977
Anurag Chouhan6d760662016-02-20 16:05:43 +053010978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010980 return -EINVAL;
10981 }
10982
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010983 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010984 hdd_device_mode_to_string(pAdapter->device_mode),
10985 pAdapter->device_mode);
10986
10987 memset(&params, 0, sizeof(params));
10988
10989 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010990 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010991 key_index);
10992 return -EINVAL;
10993 }
10994
10995 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10996 case eCSR_ENCRYPT_TYPE_NONE:
10997 params.cipher = IW_AUTH_CIPHER_NONE;
10998 break;
10999
11000 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11001 case eCSR_ENCRYPT_TYPE_WEP40:
11002 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11003 break;
11004
11005 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11006 case eCSR_ENCRYPT_TYPE_WEP104:
11007 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11008 break;
11009
11010 case eCSR_ENCRYPT_TYPE_TKIP:
11011 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11012 break;
11013
11014 case eCSR_ENCRYPT_TYPE_AES:
11015 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11016 break;
11017
11018 default:
11019 params.cipher = IW_AUTH_CIPHER_NONE;
11020 break;
11021 }
11022
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011023 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011024 TRACE_CODE_HDD_CFG80211_GET_KEY,
11025 pAdapter->sessionId, params.cipher));
11026
11027 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11028 params.seq_len = 0;
11029 params.seq = NULL;
11030 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11031 callback(cookie, &params);
11032
11033 EXIT();
11034 return 0;
11035}
11036
11037static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11038 struct net_device *ndev,
11039 u8 key_index, bool pairwise,
11040 const u8 *mac_addr, void *cookie,
11041 void (*callback)(void *cookie,
11042 struct key_params *)
11043 )
11044{
11045 int ret;
11046
11047 cds_ssr_protect(__func__);
11048 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11049 mac_addr, cookie, callback);
11050 cds_ssr_unprotect(__func__);
11051
11052 return ret;
11053}
11054
11055/**
11056 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11057 * @wiphy: wiphy interface context
11058 * @ndev: pointer to net device
11059 * @key_index: Key index used in 802.11 frames
11060 * @unicast: true if it is unicast key
11061 * @multicast: true if it is multicast key
11062 *
11063 * This function is required for cfg80211_ops API.
11064 * It is used to delete the key information
11065 * Underlying hardware implementation does not have API to delete the
11066 * encryption key. It is automatically deleted when the peer is
11067 * removed. Hence this function currently does nothing.
11068 * Future implementation may interprete delete key operation to
11069 * replacing the key with a random junk value, effectively making it
11070 * useless.
11071 *
11072 * Return: status code, always 0.
11073 */
11074
11075static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11076 struct net_device *ndev,
11077 u8 key_index,
11078 bool pairwise, const u8 *mac_addr)
11079{
11080 EXIT();
11081 return 0;
11082}
11083
11084/**
11085 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11086 * @wiphy: Pointer to wiphy structure.
11087 * @dev: Pointer to net_device structure.
11088 * @key_index: key index
11089 * @pairwise: pairwise
11090 * @mac_addr: mac address
11091 *
11092 * This is the cfg80211 delete key handler function which invokes
11093 * the internal function @__wlan_hdd_cfg80211_del_key with
11094 * SSR protection.
11095 *
11096 * Return: 0 for success, error number on failure.
11097 */
11098static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11099 struct net_device *dev,
11100 u8 key_index,
11101 bool pairwise, const u8 *mac_addr)
11102{
11103 int ret;
11104
11105 cds_ssr_protect(__func__);
11106 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11107 pairwise, mac_addr);
11108 cds_ssr_unprotect(__func__);
11109
11110 return ret;
11111}
11112
11113/*
11114 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11115 * This function is used to set the default tx key index
11116 */
11117static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11118 struct net_device *ndev,
11119 u8 key_index,
11120 bool unicast, bool multicast)
11121{
11122 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11123 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11124 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11125 hdd_context_t *pHddCtx;
11126 int status;
11127
11128 ENTER();
11129
Anurag Chouhan6d760662016-02-20 16:05:43 +053011130 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011131 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 return -EINVAL;
11133 }
11134
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011135 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11136 hdd_err("invalid session id: %d", pAdapter->sessionId);
11137 return -EINVAL;
11138 }
11139
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011140 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011141 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
11142 pAdapter->sessionId, key_index));
11143
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011144 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011145 hdd_device_mode_to_string(pAdapter->device_mode),
11146 pAdapter->device_mode, key_index);
11147
11148 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011149 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150 return -EINVAL;
11151 }
11152
11153 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11154 status = wlan_hdd_validate_context(pHddCtx);
11155
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011156 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158
Krunal Sonib4326f22016-03-10 13:05:51 -080011159 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11160 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11162 pHddStaCtx->conn_info.ucEncryptionType) &&
11163 (eCSR_ENCRYPT_TYPE_AES !=
11164 pHddStaCtx->conn_info.ucEncryptionType)) {
11165 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011166 * then update the default key index
11167 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168
11169 tCsrRoamSetKey setKey;
11170 uint32_t roamId = 0xFF;
11171 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
11172
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011173 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174
11175 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011176 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 setKey.keyId = key_index;
11178 setKey.keyLength = Keys->KeyLength[key_index];
11179
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011180 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011181 &Keys->KeyMaterial[key_index][0],
11182 Keys->KeyLength[key_index]);
11183
11184 setKey.keyDirection = eSIR_TX_RX;
11185
Anurag Chouhanc5548422016-02-24 18:33:27 +053011186 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011187 &pHddStaCtx->conn_info.bssId);
11188
11189 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
11190 pWextState->roamProfile.EncryptionType.
11191 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011192 /* In the case of dynamic wep
11193 * supplicant hardcodes DWEP type to
11194 * eCSR_ENCRYPT_TYPE_WEP104 even
11195 * though ap is configured for WEP-40
11196 * encryption. In this canse the key
11197 * length is 5 but the encryption type
11198 * is 104 hence checking the key
11199 * lenght(5) and encryption type(104)
11200 * and switching encryption type to 40
11201 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011202 pWextState->roamProfile.EncryptionType.
11203 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11204 pWextState->roamProfile.mcEncryptionType.
11205 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11206 }
11207
11208 setKey.encType =
11209 pWextState->roamProfile.EncryptionType.
11210 encryptionType[0];
11211
11212 /* Issue set key request */
11213 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11214 pAdapter->sessionId, &setKey,
11215 &roamId);
11216
11217 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011218 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219 status);
11220 return -EINVAL;
11221 }
11222 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011223 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011224 /* In SoftAp mode setting key direction for default mode */
11225 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11226 pWextState->roamProfile.EncryptionType.encryptionType[0])
11227 && (eCSR_ENCRYPT_TYPE_AES !=
11228 pWextState->roamProfile.EncryptionType.
11229 encryptionType[0])) {
11230 /* Saving key direction for default key index to TX default */
11231 hdd_ap_ctx_t *pAPCtx =
11232 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11233 pAPCtx->wepKey[key_index].keyDirection =
11234 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011235 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053011236 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011237 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 }
11239 }
11240
11241 EXIT();
11242 return status;
11243}
11244
11245static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11246 struct net_device *ndev,
11247 u8 key_index,
11248 bool unicast, bool multicast)
11249{
11250 int ret;
11251 cds_ssr_protect(__func__);
11252 ret =
11253 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
11254 multicast);
11255 cds_ssr_unprotect(__func__);
11256
11257 return ret;
11258}
11259
Abhishek Singhc9941602016-08-09 16:06:22 +053011260/*
Abhishek Singhc9941602016-08-09 16:06:22 +053011261 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
11262 * interface that BSS might have been lost.
11263 * @pAdapter: adaptor
11264 * @bssid: bssid which might have been lost
11265 *
11266 * Return: bss which is unlinked from kernel cache
11267 */
11268struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
11269 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270{
11271 struct net_device *dev = pAdapter->dev;
11272 struct wireless_dev *wdev = dev->ieee80211_ptr;
11273 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 struct cfg80211_bss *bss = NULL;
11275
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053011276 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053011277 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011278 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011279 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011280 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053011281 hdd_info("cfg80211_unlink_bss called for BSSID "
11282 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011283 cfg80211_unlink_bss(wiphy, bss);
11284 }
11285 return bss;
11286}
11287
Abhishek Singhc9941602016-08-09 16:06:22 +053011288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289/**
11290 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
11291 * @pAdapter: Pointer to adapter
11292 * @bss_desc: Pointer to bss descriptor
11293 *
11294 * This function is used to inform the BSS details to nl80211 interface.
11295 *
11296 * Return: struct cfg80211_bss pointer
11297 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053011298struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
11299 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300{
11301 /*
11302 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
11303 * already exists in bss data base of cfg80211 for that particular BSS
11304 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
11305 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
11306 * As of now there is no possibility to get the mgmt(probe response)
11307 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
11308 * and passing to cfg80211_inform_bss_frame.
11309 */
11310 struct net_device *dev = pAdapter->dev;
11311 struct wireless_dev *wdev = dev->ieee80211_ptr;
11312 struct wiphy *wiphy = wdev->wiphy;
11313 int chan_no = bss_desc->channelId;
11314#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11315 qcom_ie_age *qie_age = NULL;
11316 int ie_length =
11317 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
11318#else
11319 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
11320#endif
11321 const char *ie =
11322 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
11323 unsigned int freq;
11324 struct ieee80211_channel *chan;
11325 struct ieee80211_mgmt *mgmt = NULL;
11326 struct cfg80211_bss *bss_status = NULL;
11327 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
11328 int rssi = 0;
11329 hdd_context_t *pHddCtx;
11330 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011331 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011332 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333
11334 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11335 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011336 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011337 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011338
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011339 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011340 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011341 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011342 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011343 return NULL;
11344 }
11345
11346 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
11347
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011349 * Instead it wants a monotonic increasing value
11350 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070011351 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011352 mgmt->u.probe_resp.timestamp =
11353 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354
11355 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
11356 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
11357
11358#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11359 /* GPS Requirement: need age ie per entry. Using vendor specific. */
11360 /* Assuming this is the last IE, copy at the end */
11361 ie_length -= sizeof(qcom_ie_age);
11362 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
11363 qie_age->element_id = QCOM_VENDOR_IE_ID;
11364 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
11365 qie_age->oui_1 = QCOM_OUI1;
11366 qie_age->oui_2 = QCOM_OUI2;
11367 qie_age->oui_3 = QCOM_OUI3;
11368 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053011369 /*
11370 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
11371 * all bss related timestamp is in units of ms. Due to this when scan
11372 * results are sent to lowi the scan age is high.To address this,
11373 * send age in units of 1/10 ms.
11374 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053011376 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070011378 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
11379 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070011380 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
11381 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382#endif
11383
11384 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
11385 if (bss_desc->fProbeRsp) {
11386 mgmt->frame_control |=
11387 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
11388 } else {
11389 mgmt->frame_control |=
11390 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
11391 }
11392
11393 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070011394 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011395 freq =
11396 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011397 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011398 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070011399 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011400 freq =
11401 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011402 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011404 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011405 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 return NULL;
11407 }
11408
11409 chan = __ieee80211_get_channel(wiphy, freq);
11410 /* When the band is changed on the fly using the GUI, three things are done
11411 * 1. scan abort
11412 * 2. flush scan results from cache
11413 * 3. update the band with the new band user specified (refer to the
11414 * hdd_set_band_helper function) as part of the scan abort, message will be
11415 * queued to PE and we proceed with flushing and changinh the band.
11416 * PE will stop the scanning further and report back the results what ever
11417 * it had till now by calling the call back function.
11418 * if the time between update band and scandone call back is sufficient
11419 * enough the band change reflects in SME, SME validates the channels
11420 * and discards the channels correponding to previous band and calls back
11421 * with zero bss results. but if the time between band update and scan done
11422 * callback is very small then band change will not reflect in SME and SME
11423 * reports to HDD all the channels correponding to previous band.this is due
11424 * to race condition.but those channels are invalid to the new band and so
11425 * this function __ieee80211_get_channel will return NULL.Each time we
11426 * report scan result with this pointer null warning kernel trace is printed.
11427 * if the scan results contain large number of APs continuosly kernel
11428 * warning trace is printed and it will lead to apps watch dog bark.
11429 * So drop the bss and continue to next bss.
11430 */
11431 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053011432 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
11433 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011434 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 return NULL;
11436 }
11437
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011438 /* Based on .ini configuration, raw rssi can be reported for bss.
11439 * Raw rssi is typically used for estimating power.
11440 */
11441
11442 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
11443 bss_desc->rssi;
11444
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011445 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053011446 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053011448 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011449 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070011450 (int)(rssi / 100),
11451 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452
11453 bss_status =
11454 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
11455 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053011456 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070011457 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 return bss_status;
11459}
11460
11461/**
11462 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
11463 * @pAdapter: Pointer to adapter
11464 * @pRoamInfo: Pointer to roam info
11465 *
11466 * This function is used to update the BSS data base of CFG8011
11467 *
11468 * Return: struct cfg80211_bss pointer
11469 */
11470struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
11471 tCsrRoamInfo *pRoamInfo)
11472{
11473 tCsrRoamConnectedProfile roamProfile;
11474 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11475 struct cfg80211_bss *bss = NULL;
11476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
11478 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
11479
11480 if (NULL != roamProfile.pBssDesc) {
11481 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11482 roamProfile.pBssDesc);
11483
11484 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011485 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011486
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080011487 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011488 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011489 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011490 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011491 return bss;
11492}
11493/**
11494 * wlan_hdd_cfg80211_update_bss() - update bss
11495 * @wiphy: Pointer to wiphy
11496 * @pAdapter: Pointer to adapter
11497 * @scan_time: scan request timestamp
11498 *
11499 * Return: zero if success, non-zero otherwise
11500 */
11501int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
11502 hdd_adapter_t *pAdapter,
11503 uint32_t scan_time)
11504{
11505 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11506 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011507 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508 tScanResultHandle pResult;
11509 struct cfg80211_bss *bss_status = NULL;
11510 hdd_context_t *pHddCtx;
11511 int ret;
11512
11513 ENTER();
11514
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011515 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11516 hdd_err("invalid session id: %d", pAdapter->sessionId);
11517 return -EINVAL;
11518 }
11519
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011520 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011521 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11522 NO_SESSION, pAdapter->sessionId));
11523
11524 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11525 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011526 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011527 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528
11529 /* start getting scan results and populate cgf80211 BSS database */
11530 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11531
11532 /* no scan results */
11533 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011534 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011535 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011536 }
11537
11538 pScanResult = sme_scan_result_get_first(hHal, pResult);
11539
11540 while (pScanResult) {
11541 /*
11542 * - cfg80211_inform_bss() is not updating ie field of bss
11543 * entry if entry already exists in bss data base of cfg80211
11544 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11545 * to update thebss entry instead of cfg80211_inform_bss,
11546 * But this call expects mgmt packet as input. As of now
11547 * there is no possibility to get the mgmt(probe response)
11548 * frame from PE, converting bss_desc to
11549 * ieee80211_mgmt(probe response) and passing to c
11550 * fg80211_inform_bss_frame.
11551 * - Update BSS only if beacon timestamp is later than
11552 * scan request timestamp.
11553 */
11554 if ((scan_time == 0) ||
11555 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011556 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 bss_status =
11558 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11559 &pScanResult->BssDescriptor);
11560
11561 if (NULL == bss_status) {
11562 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11563 } else {
11564 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011566 bss_status);
11567 }
11568 } else {
11569 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11570 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11571 }
11572 pScanResult = sme_scan_result_get_next(hHal, pResult);
11573 }
11574
11575 sme_scan_result_purge(hHal, pResult);
11576 /*
11577 * For SAP mode, scan is invoked by hostapd during SAP start
11578 * if hostapd is restarted, we need to flush previous scan
11579 * result so that it will reflect environment change
11580 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011581 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011582#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11583 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11584#endif
11585 )
11586 sme_scan_flush_result(hHal);
11587
11588 EXIT();
11589 return 0;
11590}
11591
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011592/**
11593 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11594 * @pAdapter: Pointer to adapter
11595 * @pRoamInfo: Pointer to roam info
11596 * @index: Index
11597 * @preauth: Preauth flag
11598 *
11599 * This function is used to notify the supplicant of a new PMKSA candidate.
11600 *
11601 * Return: 0 for success, non-zero for failure
11602 */
11603int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11604 tCsrRoamInfo *pRoamInfo,
11605 int index, bool preauth)
11606{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011607 struct net_device *dev = pAdapter->dev;
11608 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11609
11610 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011611 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011612
11613 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011614 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 return -EINVAL;
11616 }
11617
11618 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011619 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11621 cfg80211_pmksa_candidate_notify(dev, index,
11622 pRoamInfo->bssid.bytes,
11623 preauth, GFP_KERNEL);
11624 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011625 return 0;
11626}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011627
11628#ifdef FEATURE_WLAN_LFR_METRICS
11629/**
11630 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11631 * @pAdapter: Pointer to adapter
11632 * @pRoamInfo: Pointer to roam info
11633 *
11634 * 802.11r/LFR metrics reporting function to report preauth initiation
11635 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011636 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 */
11638#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011639QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011640 tCsrRoamInfo *pRoamInfo)
11641{
11642 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11643 union iwreq_data wrqu;
11644
11645 ENTER();
11646
11647 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011648 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011649 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 }
11651
11652 /* create the event */
11653 memset(&wrqu, 0, sizeof(wrqu));
11654 memset(metrics_notification, 0, sizeof(metrics_notification));
11655
11656 wrqu.data.pointer = metrics_notification;
11657 wrqu.data.length = scnprintf(metrics_notification,
11658 sizeof(metrics_notification),
11659 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11660 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11661
11662 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11663 metrics_notification);
11664
11665 EXIT();
11666
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011667 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011668}
11669
11670/**
11671 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11672 * @pAdapter: Pointer to adapter
11673 * @pRoamInfo: Pointer to roam info
11674 * @preauth_status: Preauth status
11675 *
11676 * 802.11r/LFR metrics reporting function to report handover initiation
11677 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011678 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011679 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011680QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011681wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11682 tCsrRoamInfo *pRoamInfo,
11683 bool preauth_status)
11684{
11685 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11686 union iwreq_data wrqu;
11687
11688 ENTER();
11689
11690 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011691 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011692 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 }
11694
11695 /* create the event */
11696 memset(&wrqu, 0, sizeof(wrqu));
11697 memset(metrics_notification, 0, sizeof(metrics_notification));
11698
11699 scnprintf(metrics_notification, sizeof(metrics_notification),
11700 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11701 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11702
11703 if (1 == preauth_status)
11704 strlcat(metrics_notification, " true",
11705 sizeof(metrics_notification));
11706 else
11707 strlcat(metrics_notification, " false",
11708 sizeof(metrics_notification));
11709
11710 wrqu.data.pointer = metrics_notification;
11711 wrqu.data.length = strlen(metrics_notification);
11712
11713 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11714 metrics_notification);
11715
11716 EXIT();
11717
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011718 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719}
11720
11721/**
11722 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11723 * @pAdapter: Pointer to adapter
11724 * @pRoamInfo: Pointer to roam info
11725 *
11726 * 802.11r/LFR metrics reporting function to report handover initiation
11727 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011728 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011730QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011731 tCsrRoamInfo *pRoamInfo)
11732{
11733 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11734 union iwreq_data wrqu;
11735
11736 ENTER();
11737
11738 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011739 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011740 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741 }
11742
11743 /* create the event */
11744 memset(&wrqu, 0, sizeof(wrqu));
11745 memset(metrics_notification, 0, sizeof(metrics_notification));
11746
11747 wrqu.data.pointer = metrics_notification;
11748 wrqu.data.length = scnprintf(metrics_notification,
11749 sizeof(metrics_notification),
11750 "QCOM: LFR_PREAUTH_HANDOVER "
11751 MAC_ADDRESS_STR,
11752 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11753
11754 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11755 metrics_notification);
11756
11757 EXIT();
11758
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011759 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760}
11761#endif
11762
11763/**
11764 * hdd_select_cbmode() - select channel bonding mode
11765 * @pAdapter: Pointer to adapter
11766 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011767 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 *
11769 * Return: none
11770 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011771void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11772 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011774 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011775 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011776 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011777
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011778 /*
11779 * CDS api expects secondary channel for calculating
11780 * the channel params
11781 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011782 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011783 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11784 if (operationChannel >= 1 && operationChannel <= 5)
11785 sec_ch = operationChannel + 4;
11786 else if (operationChannel >= 6 && operationChannel <= 13)
11787 sec_ch = operationChannel - 4;
11788 }
11789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011791 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011792
11793 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011794 eHddDot11Mode hdd_dot11_mode;
11795 uint8_t iniDot11Mode =
11796 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11797
11798 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11799 switch (iniDot11Mode) {
11800 case eHDD_DOT11_MODE_AUTO:
11801 case eHDD_DOT11_MODE_11ac:
11802 case eHDD_DOT11_MODE_11ac_ONLY:
11803 if (sme_is_feature_supported_by_fw(DOT11AC))
11804 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11805 else
11806 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11807 break;
11808 case eHDD_DOT11_MODE_11n:
11809 case eHDD_DOT11_MODE_11n_ONLY:
11810 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11811 break;
11812 default:
11813 hdd_dot11_mode = iniDot11Mode;
11814 break;
11815 }
11816 ch_info->channel_width = ch_params->ch_width;
11817 ch_info->phy_mode =
11818 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011819 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011820 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011821 hdd_info("ch_info width %d, phymode %d channel %d",
11822 ch_info->channel_width, ch_info->phy_mode,
11823 ch_info->channel);
11824 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011825}
11826
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011827/**
11828 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11829 * @adapter: STA adapter
11830 * @roam_profile: STA roam profile
11831 *
11832 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11833 *
11834 * Return: false if sta-sap conc is not allowed, else return true
11835 */
11836static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11837 tCsrRoamProfile *roam_profile)
11838{
11839 hdd_context_t *hdd_ctx;
11840 hdd_adapter_t *ap_adapter;
11841 hdd_ap_ctx_t *hdd_ap_ctx;
11842 hdd_hostapd_state_t *hostapd_state;
11843 uint8_t channel = 0;
11844 QDF_STATUS status;
11845
11846 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11847 if (!hdd_ctx) {
11848 hdd_err("HDD context is NULL");
11849 return true;
11850 }
11851
11852 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11853 /* probably no sap running, no handling required */
11854 if (ap_adapter == NULL)
11855 return true;
11856
11857 /*
11858 * sap is not in started state, so it is fine to go ahead with sta.
11859 * if sap is currently doing CAC then don't allow sta to go further.
11860 */
11861 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11862 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11863 return true;
11864
11865 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11866 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11867 return false;
11868 }
11869
11870 /*
11871 * log and return error, if we allow STA to go through, we don't
11872 * know what is going to happen better stop sta connection
11873 */
11874 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11875 if (NULL == hdd_ap_ctx) {
11876 hdd_err("AP context not found");
11877 return false;
11878 }
11879
11880 /* sap is on non-dfs channel, nothing to handle */
11881 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11882 hdd_info("sap is on non-dfs channel, sta is allowed");
11883 return true;
11884 }
11885 /*
11886 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011887 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011888 */
11889 status = cds_get_channel_from_scan_result(adapter,
11890 roam_profile, &channel);
11891
Nitesh Shah59774522016-09-16 15:14:21 +053011892 /*
11893 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11894 * channels for roaming case.
11895 */
11896 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11897 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11898 return true;
11899 }
11900
11901 /*
11902 * If channel is 0 or DFS then better to call pcl and find out the
11903 * best channel. If channel is non-dfs 5 GHz then better move SAP
11904 * to STA's channel to make scc, so we have room for 3port MCC
11905 * scenario.
11906 */
11907 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011908 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11909 true);
11910
11911 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11912 qdf_event_reset(&hostapd_state->qdf_event);
11913 status = wlansap_set_channel_change_with_csa(
11914 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11915 hdd_ap_ctx->sapConfig.ch_width_orig);
11916
11917 if (QDF_STATUS_SUCCESS != status) {
11918 hdd_err("Set channel with CSA IE failed, can't allow STA");
11919 return false;
11920 }
11921
11922 /*
11923 * wait here for SAP to finish the channel switch. When channel
11924 * switch happens, SAP sends few beacons with CSA_IE. After
11925 * successfully Transmission of those beacons, it will move its
11926 * state from started to disconnected and move to new channel.
11927 * once it moves to new channel, sap again moves its state
11928 * machine from disconnected to started and set this event.
11929 * wait for 10 secs to finish this.
11930 */
11931 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11932 if (!QDF_IS_STATUS_SUCCESS(status)) {
11933 hdd_err("wait for qdf_event failed, STA not allowed!!");
11934 return false;
11935 }
11936
11937 return true;
11938}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011939
Krunal Soni31949422016-07-29 17:17:53 -070011940/**
11941 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011943 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011944 * @ssid_len: Length of ssid
11945 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011946 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011948 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011949 *
11950 * This function is used to start the association process
11951 *
11952 * Return: 0 for success, non-zero for failure
11953 */
Krunal Soni31949422016-07-29 17:17:53 -070011954static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011956 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011957 u8 operatingChannel,
11958 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011959{
11960 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080011961 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011962 hdd_wext_state_t *pWextState;
11963 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011964 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011965 uint32_t roamId;
11966 tCsrRoamProfile *pRoamProfile;
11967 eCsrAuthType RSNAuthType;
11968 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011969 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011970
11971 ENTER();
11972
11973 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11974 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011975 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011976
11977 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011978 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011979 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011980
11981 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011982 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011983 return -EINVAL;
11984 }
11985
11986 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011987 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11988 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011989
11990 if (pRoamProfile) {
11991 hdd_station_ctx_t *pHddStaCtx;
11992 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11993
11994 if (HDD_WMM_USER_MODE_NO_QOS ==
11995 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11996 /*QoS not enabled in cfg file */
11997 pRoamProfile->uapsd_mask = 0;
11998 } else {
11999 /*QoS enabled, update uapsd mask from cfg file */
12000 pRoamProfile->uapsd_mask =
12001 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12002 }
12003
12004 pRoamProfile->SSIDs.numOfSSIDs = 1;
12005 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012006 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012007 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012008 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012009 ssid, ssid_len);
12010
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012011 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012012 /* cleanup bssid hint */
12013 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12014 QDF_MAC_ADDR_SIZE);
12015 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12016 QDF_MAC_ADDR_SIZE);
12017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012018 if (bssid) {
12019 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012020 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012021 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012022 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012023 /*
12024 * Save BSSID in seperate variable as
12025 * pRoamProfile's BSSID is getting zeroed out in the
12026 * association process. In case of join failure
12027 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012029 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012030 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012031 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012032 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012033 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12034 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012035 /*
12036 * Save BSSID in a separate variable as
12037 * pRoamProfile's BSSID is getting zeroed out in the
12038 * association process. In case of join failure
12039 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012041 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012042 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012043 hdd_info("bssid_hint is given by upper layer %pM",
12044 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 }
12046
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012047 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012048 pRoamProfile->SSIDs.SSIDList->SSID.length,
12049 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12050 operatingChannel);
12051
12052 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12053 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012054 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012055 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12056 }
12057#ifdef FEATURE_WLAN_WAPI
12058 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012059 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012060 switch (pAdapter->wapi_info.wapiAuthMode) {
12061 case WAPI_AUTH_MODE_PSK:
12062 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012063 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012064 pAdapter->wapi_info.wapiAuthMode);
12065 pRoamProfile->AuthType.authType[0] =
12066 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12067 break;
12068 }
12069 case WAPI_AUTH_MODE_CERT:
12070 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012071 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072 pAdapter->wapi_info.wapiAuthMode);
12073 pRoamProfile->AuthType.authType[0] =
12074 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12075 break;
12076 }
12077 } /* End of switch */
12078 if (pAdapter->wapi_info.wapiAuthMode ==
12079 WAPI_AUTH_MODE_PSK
12080 || pAdapter->wapi_info.wapiAuthMode ==
12081 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012082 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012083 pRoamProfile->AuthType.numEntries = 1;
12084 pRoamProfile->EncryptionType.numEntries = 1;
12085 pRoamProfile->EncryptionType.encryptionType[0] =
12086 eCSR_ENCRYPT_TYPE_WPI;
12087 pRoamProfile->mcEncryptionType.numEntries = 1;
12088 pRoamProfile->mcEncryptionType.
12089 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12090 }
12091 }
Krunal Soni31949422016-07-29 17:17:53 -070012092#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012093#ifdef WLAN_FEATURE_GTK_OFFLOAD
12094 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080012095 if ((QDF_STA_MODE == pAdapter->device_mode) ||
12096 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012097 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
12098 sizeof(tSirGtkOffloadParams));
12099 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12100 GTK_OFFLOAD_DISABLE;
12101 }
12102#endif
12103 pRoamProfile->csrPersona = pAdapter->device_mode;
12104
12105 if (operatingChannel) {
12106 pRoamProfile->ChannelInfo.ChannelList =
12107 &operatingChannel;
12108 pRoamProfile->ChannelInfo.numOfChannels = 1;
12109 } else {
12110 pRoamProfile->ChannelInfo.ChannelList = NULL;
12111 pRoamProfile->ChannelInfo.numOfChannels = 0;
12112 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012113 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012114 && operatingChannel) {
12115 /*
12116 * Need to post the IBSS power save parameters
12117 * to WMA. WMA will configure this parameters
12118 * to firmware if power save is enabled by the
12119 * firmware.
12120 */
12121 status = hdd_set_ibss_power_save_params(pAdapter);
12122
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012123 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012124 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012125 return -EINVAL;
12126 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012127 pRoamProfile->ch_params.ch_width =
12128 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053012129 /*
12130 * In IBSS mode while operating in 2.4 GHz,
12131 * the device supports only 20 MHz.
12132 */
12133 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
12134 pRoamProfile->ch_params.ch_width =
12135 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012136 hdd_select_cbmode(pAdapter, operatingChannel,
12137 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012138 }
Abhishek Singh99bce862016-06-20 15:10:51 +053012139 /*
12140 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12141 * or pmf=2 is an explicit configuration in the supplicant
12142 * configuration, drop the connection request.
12143 */
12144 if (pWextState->roamProfile.MFPEnabled &&
12145 !(pWextState->roamProfile.MFPRequired ||
12146 pWextState->roamProfile.MFPCapable)) {
12147 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12148 pWextState->roamProfile.MFPEnabled,
12149 pWextState->roamProfile.MFPRequired,
12150 pWextState->roamProfile.MFPCapable);
12151 return -EINVAL;
12152 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012153
Krunal Soni3091bcc2016-06-23 12:28:21 -070012154 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 hdd_err("Connection refused: conn in progress");
12156 return -EINVAL;
12157 }
12158
Krunal Soni31949422016-07-29 17:17:53 -070012159 /*
12160 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012161 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070012162 * enhancements, the supplicant is not issuing the scan command
12163 * now. So the unicast frames which are sent from the host are
12164 * not having the additional IEs. If it is P2P CLIENT and there
12165 * is no additional IE present in roamProfile, then use the
12166 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167 */
12168
Krunal Sonib4326f22016-03-10 13:05:51 -080012169 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012170 (!pRoamProfile->pAddIEScan)) {
12171 pRoamProfile->pAddIEScan =
12172 &pAdapter->scan_info.scanAddIE.addIEdata[0];
12173 pRoamProfile->nAddIEScanLength =
12174 pAdapter->scan_info.scanAddIE.length;
12175 }
12176 /*
12177 * When policy manager is enabled from ini file, we shouldn't
12178 * check for other concurrency rules.
12179 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070012180 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080012181 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012182 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012183 pAdapter, pRoamProfile, &roamId))
12184 return 0;
12185 }
12186
Krunal Soni3091bcc2016-06-23 12:28:21 -070012187 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012188 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
12189 pRoamProfile))) {
12190 hdd_err("sap-sta conc will fail, can't allow sta");
12191 hdd_conn_set_connection_state(pAdapter,
12192 eConnectionState_NotConnected);
12193 return -ENOMEM;
12194 }
12195
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012196 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012197 if (!sme_config) {
12198 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012199 hdd_conn_set_connection_state(pAdapter,
12200 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012201 return -ENOMEM;
12202 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012203 sme_get_config_param(pHddCtx->hHal, sme_config);
12204 /* These values are not sessionized. So, any change in these SME
12205 * configs on an older or parallel interface will affect the
12206 * cb mode. So, restoring the default INI params before starting
12207 * interfaces such as sta, cli etc.,
12208 */
12209 sme_config->csrConfig.channelBondingMode5GHz =
12210 pHddCtx->config->nChannelBondingMode5GHz;
12211 sme_config->csrConfig.channelBondingMode24GHz =
12212 pHddCtx->config->nChannelBondingMode24GHz;
12213 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012214 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053012215 /*
12216 * Change conn_state to connecting before sme_roam_connect(),
12217 * because sme_roam_connect() has a direct path to call
12218 * hdd_sme_roam_callback(), which will change the conn_state
12219 * If direct path, conn_state will be accordingly changed to
12220 * NotConnected or Associated by either
12221 * hdd_association_completion_handler() or
12222 * hdd_dis_connect_handler() in sme_RoamCallback()if
12223 * sme_RomConnect is to be queued,
12224 * Connecting state will remain until it is completed.
12225 *
12226 * If connection state is not changed, connection state will
12227 * remain in eConnectionState_NotConnected state.
12228 * In hdd_association_completion_handler, "hddDisconInProgress"
12229 * is set to true if conn state is
12230 * eConnectionState_NotConnected.
12231 * If "hddDisconInProgress" is set to true then cfg80211 layer
12232 * is not informed of connect result indication which
12233 * is an issue.
12234 */
12235 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053012236 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053012237 hdd_conn_set_connection_state(pAdapter,
12238 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012239
Komal Seelama89be8d2016-09-29 11:09:26 +053012240 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
12241 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080012242 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012243 pAdapter->sessionId, pRoamProfile,
12244 &roamId);
12245
Rajeev Kumard31e1542017-01-13 14:37:42 -080012246 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080012247 (QDF_STA_MODE == pAdapter->device_mode ||
12248 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012249 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080012250 "qdf_status %d. -> NotConnected",
12251 pAdapter->sessionId, qdf_status);
12252 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012253 /* change back to NotAssociated */
12254 hdd_conn_set_connection_state(pAdapter,
12255 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053012256 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
12257 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012258 }
12259
12260 pRoamProfile->ChannelInfo.ChannelList = NULL;
12261 pRoamProfile->ChannelInfo.numOfChannels = 0;
12262
Nitesh Shah044fd672016-10-13 18:53:25 +053012263 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080012264 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053012265 cds_get_channel_from_scan_result(pAdapter,
12266 pRoamProfile, &channel);
12267 if (channel)
12268 cds_checkn_update_hw_mode_single_mac_mode
12269 (channel);
12270 }
12271
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012272 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012273 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274 return -EINVAL;
12275 }
12276 EXIT();
12277 return status;
12278}
12279
12280/**
12281 * wlan_hdd_cfg80211_set_auth_type() - set auth type
12282 * @pAdapter: Pointer to adapter
12283 * @auth_type: Auth type
12284 *
12285 * This function is used to set the authentication type (OPEN/SHARED).
12286 *
12287 * Return: 0 for success, non-zero for failure
12288 */
12289static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
12290 enum nl80211_auth_type auth_type)
12291{
12292 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12293 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295 /*set authentication type */
12296 switch (auth_type) {
12297 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012298 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
12300 break;
12301
12302 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012303 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012304 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12306 break;
12307
12308 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012309 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
12311 break;
12312#ifdef FEATURE_WLAN_ESE
12313 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012314 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012315 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
12316 break;
12317#endif
12318
12319 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012320 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012321 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
12322 return -EINVAL;
12323 }
12324
12325 pWextState->roamProfile.AuthType.authType[0] =
12326 pHddStaCtx->conn_info.authType;
12327 return 0;
12328}
12329
12330/**
12331 * wlan_hdd_set_akm_suite() - set key management type
12332 * @pAdapter: Pointer to adapter
12333 * @key_mgmt: Key management type
12334 *
12335 * This function is used to set the key mgmt type(PSK/8021x).
12336 *
12337 * Return: 0 for success, non-zero for failure
12338 */
12339static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
12340{
12341 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12342
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
12344#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
12345 /*set key mgmt type */
12346 switch (key_mgmt) {
12347 case WLAN_AKM_SUITE_PSK:
12348 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012349 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012350 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012351 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
12352 break;
12353
12354 case WLAN_AKM_SUITE_8021X_SHA256:
12355 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012357 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012358 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12359 break;
12360#ifdef FEATURE_WLAN_ESE
12361#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
12362#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
12363 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012364 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012365 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
12366 break;
12367#endif
12368#ifndef WLAN_AKM_SUITE_OSEN
12369#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
12370#endif
12371 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012372 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12374 break;
12375
12376 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012377 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012378 return -EINVAL;
12379
12380 }
12381 return 0;
12382}
12383
12384/**
12385 * wlan_hdd_cfg80211_set_cipher() - set encryption type
12386 * @pAdapter: Pointer to adapter
12387 * @cipher: Cipher type
12388 * @ucast: Unicast flag
12389 *
12390 * This function is used to set the encryption type
12391 * (NONE/WEP40/WEP104/TKIP/CCMP).
12392 *
12393 * Return: 0 for success, non-zero for failure
12394 */
12395static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
12396 u32 cipher, bool ucast)
12397{
12398 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12399 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12400 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012402 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012403 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12405 } else {
12406
12407 /*set encryption method */
12408 switch (cipher) {
12409 case IW_AUTH_CIPHER_NONE:
12410 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12411 break;
12412
12413 case WLAN_CIPHER_SUITE_WEP40:
12414 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
12415 break;
12416
12417 case WLAN_CIPHER_SUITE_WEP104:
12418 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
12419 break;
12420
12421 case WLAN_CIPHER_SUITE_TKIP:
12422 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
12423 break;
12424
12425 case WLAN_CIPHER_SUITE_CCMP:
12426 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12427 break;
12428#ifdef FEATURE_WLAN_WAPI
12429 case WLAN_CIPHER_SUITE_SMS4:
12430 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
12431 break;
12432#endif
12433
12434#ifdef FEATURE_WLAN_ESE
12435 case WLAN_CIPHER_SUITE_KRK:
12436 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
12437 break;
12438#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12439 case WLAN_CIPHER_SUITE_BTK:
12440 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
12441 break;
12442#endif
12443#endif
12444 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012445 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012446 return -EOPNOTSUPP;
12447 }
12448 }
12449
12450 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012451 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012452 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12453 pWextState->roamProfile.EncryptionType.numEntries = 1;
12454 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12455 encryptionType;
12456 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012457 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
12459 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
12460 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
12461 encryptionType;
12462 }
12463
12464 return 0;
12465}
12466
12467/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012468 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
12469 * @wext_state: Pointer to wext state
12470 * @gen_ie: Pointer to IE data
12471 * @len: length of IE data
12472 *
12473 * Return: 0 for success, non-zero for failure
12474 */
12475static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
12476 const uint8_t *gen_ie, uint16_t len)
12477{
12478 uint16_t cur_add_ie_len =
12479 wext_state->assocAddIE.length;
12480
12481 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12482 (wext_state->assocAddIE.length + len)) {
12483 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12484 QDF_ASSERT(0);
12485 return -ENOMEM;
12486 }
12487 memcpy(wext_state->assocAddIE.addIEdata +
12488 cur_add_ie_len, gen_ie, len);
12489 wext_state->assocAddIE.length += len;
12490
12491 wext_state->roamProfile.pAddIEAssoc =
12492 wext_state->assocAddIE.addIEdata;
12493 wext_state->roamProfile.nAddIEAssocLength =
12494 wext_state->assocAddIE.length;
12495 return 0;
12496}
12497
12498/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012499 * wlan_hdd_cfg80211_set_ie() - set IEs
12500 * @pAdapter: Pointer to adapter
12501 * @ie: Pointer ot ie
12502 * @ie: IE length
12503 *
12504 * Return: 0 for success, non-zero for failure
12505 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012506static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012507 size_t ie_len)
12508{
12509 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12510 const uint8_t *genie = ie;
12511 uint16_t remLen = ie_len;
12512#ifdef FEATURE_WLAN_WAPI
12513 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12514 u16 *tmp;
12515 uint16_t akmsuiteCount;
12516 int *akmlist;
12517#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012518 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519
12520 /* clear previous assocAddIE */
12521 pWextState->assocAddIE.length = 0;
12522 pWextState->roamProfile.bWPSAssociation = false;
12523 pWextState->roamProfile.bOSENAssociation = false;
12524
12525 while (remLen >= 2) {
12526 uint16_t eLen = 0;
12527 uint8_t elementId;
12528 elementId = *genie++;
12529 eLen = *genie++;
12530 remLen -= 2;
12531
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012532 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533
12534 switch (elementId) {
12535 case DOT11F_EID_WPA:
12536 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 -070012537 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012538 return -EINVAL;
12539 } else if (0 ==
12540 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12541 uint16_t curAddIELen =
12542 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012543 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012544
12545 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12546 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012547 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012548 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 return -ENOMEM;
12550 }
12551 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12552 memcpy(pWextState->assocAddIE.addIEdata +
12553 curAddIELen, genie - 2, eLen + 2);
12554 pWextState->assocAddIE.length += eLen + 2;
12555
12556 pWextState->roamProfile.bWPSAssociation = true;
12557 pWextState->roamProfile.pAddIEAssoc =
12558 pWextState->assocAddIE.addIEdata;
12559 pWextState->roamProfile.nAddIEAssocLength =
12560 pWextState->assocAddIE.length;
12561 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012562 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563 memset(pWextState->WPARSNIE, 0,
12564 MAX_WPA_RSN_IE_LEN);
12565 memcpy(pWextState->WPARSNIE, genie - 2,
12566 (eLen + 2));
12567 pWextState->roamProfile.pWPAReqIE =
12568 pWextState->WPARSNIE;
12569 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12570 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12571 P2P_OUI_TYPE_SIZE))) {
12572 uint16_t curAddIELen =
12573 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012574 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575
12576 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12577 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012578 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012579 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012580 return -ENOMEM;
12581 }
12582 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12583 memcpy(pWextState->assocAddIE.addIEdata +
12584 curAddIELen, genie - 2, eLen + 2);
12585 pWextState->assocAddIE.length += eLen + 2;
12586
12587 pWextState->roamProfile.pAddIEAssoc =
12588 pWextState->assocAddIE.addIEdata;
12589 pWextState->roamProfile.nAddIEAssocLength =
12590 pWextState->assocAddIE.length;
12591 }
12592#ifdef WLAN_FEATURE_WFD
12593 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12594 WFD_OUI_TYPE_SIZE)) &&
12595 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012596 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012597 pAdapter->device_mode)) {
12598 uint16_t curAddIELen =
12599 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012600 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012601
12602 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12603 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012604 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012605 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012606 return -ENOMEM;
12607 }
12608 /* WFD IE is saved to Additional IE ; it should
12609 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012610 * WFD IE
12611 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 memcpy(pWextState->assocAddIE.addIEdata +
12613 curAddIELen, genie - 2, eLen + 2);
12614 pWextState->assocAddIE.length += eLen + 2;
12615
12616 pWextState->roamProfile.pAddIEAssoc =
12617 pWextState->assocAddIE.addIEdata;
12618 pWextState->roamProfile.nAddIEAssocLength =
12619 pWextState->assocAddIE.length;
12620 }
12621#endif
12622 /* Appending HS 2.0 Indication Element in Assiciation Request */
12623 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12624 HS20_OUI_TYPE_SIZE))) {
12625 uint16_t curAddIELen =
12626 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012627 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012628
12629 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12630 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012631 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012632 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 return -ENOMEM;
12634 }
12635 memcpy(pWextState->assocAddIE.addIEdata +
12636 curAddIELen, genie - 2, eLen + 2);
12637 pWextState->assocAddIE.length += eLen + 2;
12638
12639 pWextState->roamProfile.pAddIEAssoc =
12640 pWextState->assocAddIE.addIEdata;
12641 pWextState->roamProfile.nAddIEAssocLength =
12642 pWextState->assocAddIE.length;
12643 }
12644 /* Appending OSEN Information Element in Assiciation Request */
12645 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12646 OSEN_OUI_TYPE_SIZE))) {
12647 uint16_t curAddIELen =
12648 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012649 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012650
12651 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12652 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012653 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012654 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012655 return -ENOMEM;
12656 }
12657 memcpy(pWextState->assocAddIE.addIEdata +
12658 curAddIELen, genie - 2, eLen + 2);
12659 pWextState->assocAddIE.length += eLen + 2;
12660
12661 pWextState->roamProfile.bOSENAssociation = true;
12662 pWextState->roamProfile.pAddIEAssoc =
12663 pWextState->assocAddIE.addIEdata;
12664 pWextState->roamProfile.nAddIEAssocLength =
12665 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012666 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12667 MBO_OUI_TYPE_SIZE))){
12668 hdd_info("Set MBO IE(len %d)", eLen + 2);
12669 status = wlan_hdd_add_assoc_ie(pWextState,
12670 genie - 2, eLen + 2);
12671 if (status)
12672 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012673 } else {
12674 uint16_t add_ie_len =
12675 pWextState->assocAddIE.length;
12676
12677 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12678
12679 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12680 (pWextState->assocAddIE.length + eLen)) {
12681 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012682 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012683 return -ENOMEM;
12684 }
12685
12686 memcpy(pWextState->assocAddIE.addIEdata +
12687 add_ie_len, genie - 2, eLen + 2);
12688 pWextState->assocAddIE.length += eLen + 2;
12689
12690 pWextState->roamProfile.pAddIEAssoc =
12691 pWextState->assocAddIE.addIEdata;
12692 pWextState->roamProfile.nAddIEAssocLength =
12693 pWextState->assocAddIE.length;
12694 }
12695 break;
12696 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012697 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012698 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12699 memcpy(pWextState->WPARSNIE, genie - 2,
12700 (eLen + 2));
12701 pWextState->roamProfile.pRSNReqIE =
12702 pWextState->WPARSNIE;
12703 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12704 break;
12705 /*
12706 * Appending Extended Capabilities with Interworking bit set
12707 * in Assoc Req.
12708 *
12709 * In assoc req this EXT Cap will only be taken into account if
12710 * interworkingService bit is set to 1. Currently
12711 * driver is only interested in interworkingService capability
12712 * from supplicant. If in future any other EXT Cap info is
12713 * required from supplicat, it needs to be handled while
12714 * sending Assoc Req in LIM.
12715 */
12716 case DOT11F_EID_EXTCAP:
12717 {
12718 uint16_t curAddIELen =
12719 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012720 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721
12722 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12723 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012724 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012725 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012726 return -ENOMEM;
12727 }
12728 memcpy(pWextState->assocAddIE.addIEdata +
12729 curAddIELen, genie - 2, eLen + 2);
12730 pWextState->assocAddIE.length += eLen + 2;
12731
12732 pWextState->roamProfile.pAddIEAssoc =
12733 pWextState->assocAddIE.addIEdata;
12734 pWextState->roamProfile.nAddIEAssocLength =
12735 pWextState->assocAddIE.length;
12736 break;
12737 }
12738#ifdef FEATURE_WLAN_WAPI
12739 case WLAN_EID_WAPI:
12740 /* Setting WAPI Mode to ON=1 */
12741 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012742 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012743 tmp = (u16 *) ie;
12744 tmp = tmp + 2; /* Skip element Id and Len, Version */
12745 akmsuiteCount = WPA_GET_LE16(tmp);
12746 tmp = tmp + 1;
12747 akmlist = (int *)(tmp);
12748 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12749 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12750 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012751 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012752 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012753 return -EINVAL;
12754 }
12755
12756 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012757 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012758 pAdapter->wapi_info.wapiAuthMode =
12759 WAPI_AUTH_MODE_PSK;
12760 }
12761 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012762 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012763 pAdapter->wapi_info.wapiAuthMode =
12764 WAPI_AUTH_MODE_CERT;
12765 }
12766 break;
12767#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012768 case DOT11F_EID_SUPPOPERATINGCLASSES:
12769 {
12770 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12771 status = wlan_hdd_add_assoc_ie(pWextState,
12772 genie - 2, eLen + 2);
12773 if (status)
12774 return status;
12775 break;
12776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012778 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012779 /* when Unknown IE is received we break
12780 * and continue to the next IE in the buffer
12781 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 break;
12783 }
12784 genie += eLen;
12785 remLen -= eLen;
12786 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012787 return 0;
12788}
12789
12790/**
12791 * hdd_is_wpaie_present() - check for WPA ie
12792 * @ie: Pointer to ie
12793 * @ie_len: Ie length
12794 *
12795 * Parse the received IE to find the WPA IE
12796 *
12797 * Return: true if wpa ie is found else false
12798 */
12799static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12800{
12801 uint8_t eLen = 0;
12802 uint16_t remLen = ie_len;
12803 uint8_t elementId = 0;
12804
12805 while (remLen >= 2) {
12806 elementId = *ie++;
12807 eLen = *ie++;
12808 remLen -= 2;
12809 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012810 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012811 return false;
12812 }
12813 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12814 /* OUI - 0x00 0X50 0XF2
12815 * WPA Information Element - 0x01
12816 * WPA version - 0x01
12817 */
12818 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12819 return true;
12820 }
12821 ie += eLen;
12822 remLen -= eLen;
12823 }
12824 return false;
12825}
12826
12827/**
12828 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12829 * @pAdapter: Pointer to adapter
12830 * @req: Pointer to security parameters
12831 *
12832 * Return: 0 for success, non-zero for failure
12833 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012834static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12835 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012836{
12837 int status = 0;
12838 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12839 ENTER();
12840
12841 /*set wpa version */
12842 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12843
12844 if (req->crypto.wpa_versions) {
12845 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12846 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12847 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12848 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12849 }
12850 }
12851
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012852 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012853
12854 /*set authentication type */
12855 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12856
12857 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012858 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012859 return status;
12860 }
12861
12862 /*set key mgmt type */
12863 if (req->crypto.n_akm_suites) {
12864 status =
12865 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12866 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012867 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012868 return status;
12869 }
12870 }
12871
12872 /*set pairwise cipher type */
12873 if (req->crypto.n_ciphers_pairwise) {
12874 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12875 req->crypto.
12876 ciphers_pairwise[0],
12877 true);
12878 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012879 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012880 return status;
12881 }
12882 } else {
12883 /*Reset previous cipher suite to none */
12884 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12885 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012886 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012887 return status;
12888 }
12889 }
12890
12891 /*set group cipher type */
12892 status =
12893 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12894 false);
12895
12896 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012897 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898 return status;
12899 }
12900#ifdef WLAN_FEATURE_11W
12901 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12902#endif
12903
12904 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12905 if (req->ie_len) {
12906 status =
12907 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12908 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012909 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012910 return status;
12911 }
12912 }
12913
12914 /*incase of WEP set default key information */
12915 if (req->key && req->key_len) {
12916 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12917 || (WLAN_CIPHER_SUITE_WEP104 ==
12918 req->crypto.ciphers_pairwise[0])
12919 ) {
12920 if (IW_AUTH_KEY_MGMT_802_1X
12921 ==
12922 (pWextState->
12923 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012924 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012925 return -EOPNOTSUPP;
12926 } else {
12927 u8 key_len = req->key_len;
12928 u8 key_idx = req->key_idx;
12929
12930 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12931 key_len)
12932 && (CSR_MAX_NUM_KEY > key_idx)
12933 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012934 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012936 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012937 Keys.
12938 KeyMaterial[key_idx][0],
12939 req->key, key_len);
12940 pWextState->roamProfile.Keys.
12941 KeyLength[key_idx] = (u8) key_len;
12942 pWextState->roamProfile.Keys.
12943 defaultIndex = (u8) key_idx;
12944 }
12945 }
12946 }
12947 }
12948
12949 return status;
12950}
12951
12952/**
12953 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12954 * @pAdapter: Pointer to adapter
12955 *
12956 * This function is used to disconnect from previous connection
12957 *
12958 * Return: 0 for success, non-zero for failure
12959 */
12960static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12961{
12962 unsigned long rc;
12963 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012964 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965
12966 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12967
Jeff Johnson9edf9572016-10-03 15:24:49 -070012968 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012969 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12970 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12971 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012972 hdd_conn_set_connection_state(pAdapter,
12973 eConnectionState_Disconnecting);
12974 /* Issue disconnect to CSR */
12975 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012976
12977 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12978 pAdapter->sessionId,
12979 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12980 /*
12981 * Wait here instead of returning directly, this will block the
12982 * next connect command and allow processing of the scan for
12983 * ssid and the previous connect command in CSR. Else we might
12984 * hit some race conditions leading to SME and HDD out of sync.
12985 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012986 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012987 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12988 } else if (0 != status) {
12989 hdd_err("csrRoamDisconnect failure, returned %d",
12990 (int)status);
12991 pHddStaCtx->staDebugState = status;
12992 result = -EINVAL;
12993 goto disconnected;
12994 }
12995
12996 rc = wait_for_completion_timeout(
12997 &pAdapter->disconnect_comp_var,
12998 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012999 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013000 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13001 pAdapter->sessionId, pHddStaCtx->staDebugState);
13002 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013003 }
13004 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013005 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013006 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013007 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013009 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013011 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013012 }
13013 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013014disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013015 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13016 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013017}
13018
13019/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013020 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13021 * @adapter: Pointer to the HDD adapter
13022 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013023 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013024 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013025 * This function will start reassociation if prev_bssid is set and bssid/
13026 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013027 *
Naveen Rawat07332902016-07-27 09:13:17 -070013028 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013029 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013030#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13031 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013032static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13033 struct cfg80211_connect_params *req,
13034 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013035{
Naveen Rawat07332902016-07-27 09:13:17 -070013036 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013037 const uint8_t *bssid = NULL;
13038 uint16_t channel = 0;
13039
13040 if (req->bssid)
13041 bssid = req->bssid;
13042 else if (req->bssid_hint)
13043 bssid = req->bssid_hint;
13044
13045 if (req->channel)
13046 channel = req->channel->hw_value;
13047 else if (req->channel_hint)
13048 channel = req->channel_hint->hw_value;
13049
13050 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013051 reassoc = true;
13052 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013053 channel, MAC_ADDR_ARRAY(bssid));
13054 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013055 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013056 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013057 }
Naveen Rawat07332902016-07-27 09:13:17 -070013058 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013059}
13060#else
Naveen Rawat07332902016-07-27 09:13:17 -070013061static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13062 struct cfg80211_connect_params *req,
13063 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013064{
Naveen Rawat07332902016-07-27 09:13:17 -070013065 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013066}
13067#endif
13068
13069/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13071 * @wiphy: Pointer to wiphy
13072 * @dev: Pointer to network device
13073 * @req: Pointer to cfg80211 connect request
13074 *
13075 * This function is used to start the association process
13076 *
13077 * Return: 0 for success, non-zero for failure
13078 */
13079static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13080 struct net_device *ndev,
13081 struct cfg80211_connect_params *req)
13082{
13083 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013084 u16 channel;
13085#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13086 const u8 *bssid_hint = req->bssid_hint;
13087#else
13088 const u8 *bssid_hint = NULL;
13089#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13091 hdd_context_t *pHddCtx;
13092
13093 ENTER();
13094
Anurag Chouhan6d760662016-02-20 16:05:43 +053013095 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013096 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013097 return -EINVAL;
13098 }
13099
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013100 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13101 hdd_err("invalid session id: %d", pAdapter->sessionId);
13102 return -EINVAL;
13103 }
13104
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013105 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 TRACE_CODE_HDD_CFG80211_CONNECT,
13107 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013108 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 hdd_device_mode_to_string(pAdapter->device_mode),
13110 pAdapter->device_mode);
13111
Krunal Sonib4326f22016-03-10 13:05:51 -080013112 if (pAdapter->device_mode != QDF_STA_MODE &&
13113 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013114 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013115 hdd_device_mode_to_string(pAdapter->device_mode),
13116 pAdapter->device_mode);
13117 return -EINVAL;
13118 }
13119
13120 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13121 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013122 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 return -EINVAL;
13124 }
13125
13126 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013127 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013128 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013129
Naveen Rawat07332902016-07-27 09:13:17 -070013130 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013131 return status;
13132
Agrawal Ashishf156e942016-08-04 14:54:47 +053013133 /* Try disconnecting if already in connected state */
13134 status = wlan_hdd_try_disconnect(pAdapter);
13135 if (0 > status) {
13136 hdd_err("Failed to disconnect the existing connection");
13137 return -EALREADY;
13138 }
13139
13140 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013141 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013142 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013143 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 pAdapter->device_mode),
13145 req->channel->hw_value, HW_MODE_20_MHZ)) {
13146 hdd_err("This concurrency combination is not allowed");
13147 return -ECONNREFUSED;
13148 }
13149 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013150 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013151 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013152 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
13153 hdd_err("This concurrency combination is not allowed");
13154 return -ECONNREFUSED;
13155 }
13156 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013158 /*initialise security parameters */
13159 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
13160
13161 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013162 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163 return status;
13164 }
13165
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013166 if (req->channel)
13167 channel = req->channel->hw_value;
13168 else
13169 channel = 0;
13170 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
13171 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013172 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013173 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013174 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 return status;
13176 }
13177 EXIT();
13178 return status;
13179}
13180
13181/**
13182 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
13183 * @wiphy: Pointer to wiphy
13184 * @dev: Pointer to network device
13185 * @req: Pointer to cfg80211 connect request
13186 *
13187 * Return: 0 for success, non-zero for failure
13188 */
13189static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13190 struct net_device *ndev,
13191 struct cfg80211_connect_params *req)
13192{
13193 int ret;
13194 cds_ssr_protect(__func__);
13195 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
13196 cds_ssr_unprotect(__func__);
13197
13198 return ret;
13199}
13200
13201/**
13202 * wlan_hdd_disconnect() - hdd disconnect api
13203 * @pAdapter: Pointer to adapter
13204 * @reason: Disconnect reason code
13205 *
13206 * This function is used to issue a disconnect request to SME
13207 *
13208 * Return: 0 for success, non-zero for failure
13209 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013210static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211{
13212 int status, result = 0;
13213 unsigned long rc;
13214 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13215 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13216
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013217 ENTER();
13218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013219 status = wlan_hdd_validate_context(pHddCtx);
13220
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013221 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013222 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223
13224 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013225 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013226 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
13227 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013228 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
13230 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13231
13232 /*issue disconnect */
13233
13234 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13235 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053013236 /*
13237 * Wait here instead of returning directly, this will block the next
13238 * connect command and allow processing of the scan for ssid and
13239 * the previous connect command in CSR. Else we might hit some
13240 * race conditions leading to SME and HDD out of sync.
13241 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013242 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013243 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013244 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013245 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013246 (int)status);
13247 pHddStaCtx->staDebugState = status;
13248 result = -EINVAL;
13249 goto disconnected;
13250 }
13251 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13252 msecs_to_jiffies
13253 (WLAN_WAIT_TIME_DISCONNECT));
13254
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013255 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013256 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013257 result = -ETIMEDOUT;
13258 }
13259disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013260 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13261#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
13262 /* Sending disconnect event to userspace for kernel version < 3.11
13263 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
13264 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013265 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053013266 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
13267 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268#endif
13269
13270 return result;
13271}
13272
13273/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013274 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
13275 * @reason: ieee80211 reason code.
13276 *
13277 * This utility function helps log string conversion of reason code.
13278 *
13279 * Return: string conversion of reason code, if match found;
13280 * "Unknown" otherwise.
13281 */
13282static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
13283{
13284 switch (reason) {
13285 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
13286 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
13287 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
13288 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
13289 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
13290 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13291 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
13292 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
13293 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
13294 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
13295 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
13296 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
13297 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
13298 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
13299 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
13300 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
13301 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
13302 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
13303 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
13304 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
13305 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
13306 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
13307 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
13308 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
13309 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
13310 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
13311 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
13312 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
13313 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
13314 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
13315 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
13316 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
13317 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
13318 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
13319 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
13320 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
13321 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
13322 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
13323 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
13324 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
13325 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
13326 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
13327 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
13328 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
13329 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
13330 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
13331 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
13332 default:
13333 return "Unknown";
13334 }
13335}
13336
13337/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13339 * @wiphy: Pointer to wiphy
13340 * @dev: Pointer to network device
13341 * @reason: Disconnect reason code
13342 *
13343 * This function is used to issue a disconnect request to SME
13344 *
13345 * Return: 0 for success, non-zero for failure
13346 */
13347static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13348 struct net_device *dev, u16 reason)
13349{
13350 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13351 int status;
13352 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13353 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13354#ifdef FEATURE_WLAN_TDLS
13355 uint8_t staIdx;
13356#endif
13357
13358 ENTER();
13359
Anurag Chouhan6d760662016-02-20 16:05:43 +053013360 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013361 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013362 return -EINVAL;
13363 }
13364
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013365 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13366 hdd_err("invalid session id: %d", pAdapter->sessionId);
13367 return -EINVAL;
13368 }
13369
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013370 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 TRACE_CODE_HDD_CFG80211_DISCONNECT,
13372 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013373 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013374 hdd_device_mode_to_string(pAdapter->device_mode),
13375 pAdapter->device_mode, reason);
13376
13377 status = wlan_hdd_validate_context(pHddCtx);
13378
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080013379 if (hdd_is_roaming_in_progress()) {
13380 hdd_err("Roaming In Progress. Ignore!!!");
13381 return -EAGAIN;
13382 }
13383
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013384 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013385 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013386
13387 /* Issue disconnect request to SME, if station is in connected state */
13388 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
13389 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
13390 eCsrRoamDisconnectReason reasonCode =
13391 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13392 hdd_scaninfo_t *pScanInfo;
13393
13394 switch (reason) {
13395 case WLAN_REASON_MIC_FAILURE:
13396 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
13397 break;
13398
13399 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
13400 case WLAN_REASON_DISASSOC_AP_BUSY:
13401 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
13402 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
13403 break;
13404
13405 case WLAN_REASON_PREV_AUTH_NOT_VALID:
13406 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
13407 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
13408 break;
13409
13410 case WLAN_REASON_DEAUTH_LEAVING:
13411 reasonCode =
13412 pHddCtx->config->
13413 gEnableDeauthToDisassocMap ?
13414 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
13415 eCSR_DISCONNECT_REASON_DEAUTH;
13416 break;
13417 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
13418 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
13419 break;
13420 default:
13421 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
13422 break;
13423 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013424 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013426 pScanInfo = &pAdapter->scan_info;
13427 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013428 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053013430 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013431 eCSR_SCAN_ABORT_DEFAULT);
13432 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053013433 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013434#ifdef FEATURE_WLAN_TDLS
13435 /* First clean up the tdls peers if any */
13436 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
13437 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
13438 pAdapter->sessionId)
13439 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
13440 uint8_t *mac;
13441 mac =
13442 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013443 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
13444 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445 pHddCtx->tdlsConnInfo[staIdx].staId,
13446 pAdapter->sessionId,
13447 MAC_ADDR_ARRAY(mac));
13448 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
13449 (pAdapter),
13450 pAdapter->sessionId, mac);
13451 }
13452 }
13453#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013454 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013456 hdd_info("Disconnect request from user space with reason: %s",
13457 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013458 status = wlan_hdd_disconnect(pAdapter, reasonCode);
13459 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013460 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013461 return -EINVAL;
13462 }
13463 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013464 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013465 pHddStaCtx->conn_info.connState);
13466 }
13467
13468 return status;
13469}
13470
13471/**
13472 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13473 * @wiphy: Pointer to wiphy
13474 * @dev: Pointer to network device
13475 * @reason: Disconnect reason code
13476 *
13477 * Return: 0 for success, non-zero for failure
13478 */
13479static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13480 struct net_device *dev, u16 reason)
13481{
13482 int ret;
13483 cds_ssr_protect(__func__);
13484 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13485 cds_ssr_unprotect(__func__);
13486
13487 return ret;
13488}
13489
13490/**
13491 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13492 * @pAdapter: Pointer to adapter
13493 * @param: Pointer to IBSS parameters
13494 *
13495 * This function is used to initialize the security settings in IBSS mode
13496 *
13497 * Return: 0 for success, non-zero for failure
13498 */
13499static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13500 struct cfg80211_ibss_params
13501 *params)
13502{
13503 int status = 0;
13504 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13505 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13506 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13507
13508 ENTER();
13509
13510 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013511 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013512 pHddStaCtx->ibss_enc_key_installed = 0;
13513
13514 if (params->ie_len && (NULL != params->ie)) {
13515 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13516 params->ie_len, WLAN_EID_RSN)) {
13517 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13518 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13519 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13520 tDot11fIEWPA dot11WPAIE;
13521 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13522 u8 *ie;
13523
13524 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13525 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13526 params->ie_len,
13527 DOT11F_EID_WPA);
13528 if (NULL != ie) {
13529 pWextState->wpaVersion =
13530 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013531 /* Unpack the WPA IE
13532 * Skip past the EID byte and length byte
13533 * and four byte WiFi OUI
13534 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013535 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13536 &ie[2 + 4],
13537 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013538 /* Extract the multicast cipher, the
13539 * encType for unicast cipher for
13540 * wpa-none is none
13541 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013542 encryptionType =
13543 hdd_translate_wpa_to_csr_encryption_type
13544 (dot11WPAIE.multicast_cipher);
13545 }
13546 }
13547
13548 status =
13549 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13550 params->ie_len);
13551
13552 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013553 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 return status;
13555 }
13556 }
13557
13558 pWextState->roamProfile.AuthType.authType[0] =
13559 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13560
13561 if (params->privacy) {
13562 /* Security enabled IBSS, At this time there is no information
13563 * available about the security paramters, so initialise the
13564 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13565 * The correct security parameters will be updated later in
13566 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13567 * set inorder enable privacy bit in beacons
13568 */
13569
13570 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13571 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013572 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13574 pWextState->roamProfile.EncryptionType.numEntries = 1;
13575 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13576 encryptionType;
13577 return status;
13578}
13579
13580/**
13581 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13582 * @wiphy: Pointer to wiphy
13583 * @dev: Pointer to network device
13584 * @param: Pointer to IBSS join parameters
13585 *
13586 * This function is used to create/join an IBSS network
13587 *
13588 * Return: 0 for success, non-zero for failure
13589 */
13590static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13591 struct net_device *dev,
13592 struct cfg80211_ibss_params *params)
13593{
13594 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13595 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13596 tCsrRoamProfile *pRoamProfile;
13597 int status;
13598 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13599 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013600 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013602
13603 ENTER();
13604
Anurag Chouhan6d760662016-02-20 16:05:43 +053013605 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013606 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 return -EINVAL;
13608 }
13609
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013610 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13611 hdd_err("invalid session id: %d", pAdapter->sessionId);
13612 return -EINVAL;
13613 }
13614
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013615 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013616 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13617 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013618 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013619 hdd_device_mode_to_string(pAdapter->device_mode),
13620 pAdapter->device_mode);
13621
13622 status = wlan_hdd_validate_context(pHddCtx);
13623
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013624 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013625 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626
13627 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013628 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013629 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13630 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13631 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13632 int indx;
13633
13634 /* Get channel number */
13635 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013636 params->
13637 chandef.
13638 chan->
13639 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640
13641 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13642 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013643 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644 return -EOPNOTSUPP;
13645 }
13646
13647 for (indx = 0; indx < numChans; indx++) {
13648 if (channelNum == validChan[indx]) {
13649 break;
13650 }
13651 }
13652 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013653 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654 return -EINVAL;
13655 }
13656 }
13657
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013658 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 HW_MODE_20_MHZ)) {
13660 hdd_err("This concurrency combination is not allowed");
13661 return -ECONNREFUSED;
13662 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663
Krunal Soni3091bcc2016-06-23 12:28:21 -070013664 status = qdf_reset_connection_update();
13665 if (!QDF_IS_STATUS_SUCCESS(status))
13666 hdd_err("ERR: clear event failed");
13667
13668 status = cds_current_connections_update(pAdapter->sessionId,
13669 channelNum,
13670 SIR_UPDATE_REASON_JOIN_IBSS);
13671 if (QDF_STATUS_E_FAILURE == status) {
13672 hdd_err("ERROR: connections update failed!!");
13673 return -EINVAL;
13674 }
13675
13676 if (QDF_STATUS_SUCCESS == status) {
13677 status = qdf_wait_for_connection_update();
13678 if (!QDF_IS_STATUS_SUCCESS(status)) {
13679 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013680 return -EINVAL;
13681 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013682 }
13683
13684 /*Try disconnecting if already in connected state */
13685 status = wlan_hdd_try_disconnect(pAdapter);
13686 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013687 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013688 return -EALREADY;
13689 }
13690
13691 pRoamProfile = &pWextState->roamProfile;
13692
13693 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013694 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013695 return -EINVAL;
13696 }
13697
13698 /* enable selected protection checks in IBSS mode */
13699 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13700
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013701 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13703 pHddCtx->config->
13704 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013705 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706 }
13707
13708 /* BSSID is provided by upper layers hence no need to AUTO generate */
13709 if (NULL != params->bssid) {
13710 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013711 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013712 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 return -EIO;
13714 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013715 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13717 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013718 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013719 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720 return -EIO;
13721 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013722 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 }
13724 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13725 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13726 pRoamProfile->beaconInterval = params->beacon_interval;
13727 else {
13728 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013729 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013730 params->beacon_interval, pRoamProfile->beaconInterval);
13731 }
13732
13733 /* Set Channel */
13734 if (channelNum) {
13735 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013736 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013737 pRoamProfile->ChannelInfo.numOfChannels = 1;
13738 pHddStaCtx->conn_info.operationChannel = channelNum;
13739 pRoamProfile->ChannelInfo.ChannelList =
13740 &pHddStaCtx->conn_info.operationChannel;
13741 }
13742
13743 /* Initialize security parameters */
13744 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13745 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013746 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013747 return status;
13748 }
13749
13750 /* Issue connect start */
13751 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13752 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013753 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013754 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013755 operationChannel,
13756 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013757
13758 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013759 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760 return status;
13761 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013762 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013763 return 0;
13764}
13765
13766/**
13767 * wlan_hdd_cfg80211_join_ibss() - join ibss
13768 * @wiphy: Pointer to wiphy
13769 * @dev: Pointer to network device
13770 * @param: Pointer to IBSS join parameters
13771 *
13772 * This function is used to create/join an IBSS network
13773 *
13774 * Return: 0 for success, non-zero for failure
13775 */
13776static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13777 struct net_device *dev,
13778 struct cfg80211_ibss_params *params)
13779{
13780 int ret = 0;
13781
13782 cds_ssr_protect(__func__);
13783 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13784 cds_ssr_unprotect(__func__);
13785
13786 return ret;
13787}
13788
13789/**
13790 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13791 * @wiphy: Pointer to wiphy
13792 * @dev: Pointer to network device
13793 *
13794 * This function is used to leave an IBSS network
13795 *
13796 * Return: 0 for success, non-zero for failure
13797 */
13798static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13799 struct net_device *dev)
13800{
13801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13802 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13803 tCsrRoamProfile *pRoamProfile;
13804 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13805 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013806 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013807 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013808 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013809
13810 ENTER();
13811
Anurag Chouhan6d760662016-02-20 16:05:43 +053013812 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013813 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013814 return -EINVAL;
13815 }
13816
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013817 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13818 hdd_err("invalid session id: %d", pAdapter->sessionId);
13819 return -EINVAL;
13820 }
13821
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013822 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013823 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13824 pAdapter->sessionId,
13825 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13826 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013827 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013828 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013830 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 hdd_device_mode_to_string(pAdapter->device_mode),
13832 pAdapter->device_mode);
13833 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013834 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835 return -EIO;
13836 }
13837
13838 pRoamProfile = &pWextState->roamProfile;
13839
13840 /* Issue disconnect only if interface type is set to IBSS */
13841 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013842 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013843 return -EINVAL;
13844 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013845 /* Clearing add IE of beacon */
13846 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13847 sizeof(tSirMacAddr));
13848 updateIE.smeSessionId = pAdapter->sessionId;
13849 updateIE.ieBufferlength = 0;
13850 updateIE.pAdditionIEBuffer = NULL;
13851 updateIE.append = true;
13852 updateIE.notify = true;
13853 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13854 &updateIE,
13855 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013856 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013857 }
13858
13859 /* Reset WNI_CFG_PROBE_RSP Flags */
13860 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013861
13862 /* Issue Disconnect request */
13863 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13864 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13865 pAdapter->sessionId,
13866 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013867 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013868 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013869 hal_status);
13870 return -EAGAIN;
13871 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013872
13873 /* wait for mc thread to cleanup and then return to upper stack
13874 * so by the time upper layer calls the change interface, we are
13875 * all set to proceed further
13876 */
13877 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13878 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13879 if (!rc) {
13880 hdd_err("Failed to disconnect, timed out");
13881 return -ETIMEDOUT;
13882 }
13883
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013884 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 return 0;
13886}
13887
13888/**
13889 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13890 * @wiphy: Pointer to wiphy
13891 * @dev: Pointer to network device
13892 *
13893 * This function is used to leave an IBSS network
13894 *
13895 * Return: 0 for success, non-zero for failure
13896 */
13897static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13898 struct net_device *dev)
13899{
13900 int ret = 0;
13901
13902 cds_ssr_protect(__func__);
13903 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13904 cds_ssr_unprotect(__func__);
13905
13906 return ret;
13907}
13908
13909/**
13910 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13911 * @wiphy: Pointer to wiphy
13912 * @changed: Parameters changed
13913 *
13914 * This function is used to set the phy parameters. RTS Threshold/FRAG
13915 * Threshold/Retry Count etc.
13916 *
13917 * Return: 0 for success, non-zero for failure
13918 */
13919static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13920 u32 changed)
13921{
13922 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13923 tHalHandle hHal = pHddCtx->hHal;
13924 int status;
13925
13926 ENTER();
13927
Anurag Chouhan6d760662016-02-20 16:05:43 +053013928 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013929 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013930 return -EINVAL;
13931 }
13932
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013933 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013934 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13935 NO_SESSION, wiphy->rts_threshold));
13936 status = wlan_hdd_validate_context(pHddCtx);
13937
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013938 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013940
13941 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13942 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13943 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13944
13945 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13946 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013947 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013948 rts_threshold);
13949 return -EINVAL;
13950 }
13951
13952 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13953 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013954 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013955 rts_threshold);
13956 return -EIO;
13957 }
13958
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013959 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960 }
13961
13962 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13963 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13964 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13965 wiphy->frag_threshold;
13966
13967 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13968 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013969 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013970 frag_threshold);
13971 return -EINVAL;
13972 }
13973
13974 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13975 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013976 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013977 frag_threshold);
13978 return -EIO;
13979 }
13980
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013981 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013982 }
13983
13984 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13985 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13986 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13987 wiphy->retry_short : wiphy->retry_long;
13988
13989 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13990 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013991 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013992 return -EINVAL;
13993 }
13994
13995 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13996 if (0 != sme_cfg_set_int(hHal,
13997 WNI_CFG_LONG_RETRY_LIMIT,
13998 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013999 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014000 retry_value);
14001 return -EIO;
14002 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014003 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14005 if (0 != sme_cfg_set_int(hHal,
14006 WNI_CFG_SHORT_RETRY_LIMIT,
14007 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014008 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 retry_value);
14010 return -EIO;
14011 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014012 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 }
14014 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014015 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014016 return 0;
14017}
14018
14019/**
14020 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14021 * @wiphy: Pointer to wiphy
14022 * @changed: Parameters changed
14023 *
14024 * Return: 0 for success, non-zero for failure
14025 */
14026static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14027{
14028 int ret;
14029
14030 cds_ssr_protect(__func__);
14031 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14032 cds_ssr_unprotect(__func__);
14033
14034 return ret;
14035}
14036
14037/**
14038 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14039 * key
14040 * @wiphy: Pointer to wiphy
14041 * @dev: Pointer to network device
14042 * @key_index: Key index
14043 *
14044 * Return: 0
14045 */
14046static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14047 struct net_device *netdev,
14048 u8 key_index)
14049{
14050 ENTER();
14051 return 0;
14052}
14053
14054/**
14055 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14056 * wlan_hdd_set_default_mgmt_key
14057 * @wiphy: pointer to wiphy
14058 * @netdev: pointer to net_device structure
14059 * @key_index: key index
14060 *
14061 * Return: 0 on success, error number on failure
14062 */
14063static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14064 struct net_device *netdev,
14065 u8 key_index)
14066{
14067 int ret;
14068
14069 cds_ssr_protect(__func__);
14070 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14071 cds_ssr_unprotect(__func__);
14072
14073 return ret;
14074}
14075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076/**
14077 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14078 * @wiphy: Pointer to wiphy
14079 * @dev: Pointer to network device
14080 * @params: Pointer to tx queue parameters
14081 *
14082 * Return: 0
14083 */
14084static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14085 struct net_device *dev,
14086 struct ieee80211_txq_params *params)
14087{
14088 ENTER();
14089 return 0;
14090}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014091
14092/**
14093 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
14094 * @wiphy: pointer to wiphy
14095 * @netdev: pointer to net_device structure
14096 * @params: pointer to ieee80211_txq_params
14097 *
14098 * Return: 0 on success, error number on failure
14099 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014100static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14101 struct net_device *dev,
14102 struct ieee80211_txq_params *params)
14103{
14104 int ret;
14105
14106 cds_ssr_protect(__func__);
14107 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14108 cds_ssr_unprotect(__func__);
14109
14110 return ret;
14111}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014112
14113/**
14114 * __wlan_hdd_cfg80211_del_station() - delete station v2
14115 * @wiphy: Pointer to wiphy
14116 * @param: Pointer to delete station parameter
14117 *
14118 * Return: 0 for success, non-zero for failure
14119 */
14120static
14121int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14122 struct net_device *dev,
14123 struct tagCsrDelStaParams *pDelStaParams)
14124{
14125 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14126 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014127 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014128 hdd_hostapd_state_t *hapd_state;
14129 int status;
14130 uint8_t staId;
14131 uint8_t *mac;
14132
14133 ENTER();
14134
Anurag Chouhan6d760662016-02-20 16:05:43 +053014135 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014136 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014137 return -EINVAL;
14138 }
14139
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014140 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14141 hdd_err("invalid session id: %d", pAdapter->sessionId);
14142 return -EINVAL;
14143 }
14144
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014145 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 TRACE_CODE_HDD_CFG80211_DEL_STA,
14147 pAdapter->sessionId, pAdapter->device_mode));
14148
14149 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14150 status = wlan_hdd_validate_context(pHddCtx);
14151
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014152 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014153 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014154
14155 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
14156
Krunal Sonib4326f22016-03-10 13:05:51 -080014157 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
14158 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159
14160 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14161 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014162 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014163 return 0;
14164 }
14165
Anurag Chouhanc5548422016-02-24 18:33:27 +053014166 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014167 uint16_t i;
14168 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
14169 if ((pAdapter->aStaInfo[i].isUsed) &&
14170 (!pAdapter->aStaInfo[i].
14171 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014172 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014173 mac,
14174 pAdapter->aStaInfo[i].
14175 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014176 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014177 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14178 hdd_ipa_wlan_evt(pAdapter,
14179 pAdapter->
14180 aStaInfo[i].
14181 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014182 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183 mac);
14184 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014185 hdd_notice("Delete STA with MAC::"
14186 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014187 MAC_ADDR_ARRAY(mac));
14188
14189 if (pHddCtx->dev_dfs_cac_status ==
14190 DFS_CAC_IN_PROGRESS)
14191 goto fn_end;
14192
Wei Song2f76f642016-11-18 16:32:53 +080014193 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053014195 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014196 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 hdd_softap_sta_deauth(pAdapter,
14198 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014199 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 pAdapter->aStaInfo[i].
14201 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014202 qdf_status =
14203 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014204 &hapd_state->
14205 qdf_sta_disassoc_event,
14206 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014207 if (!QDF_IS_STATUS_SUCCESS(
14208 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014209 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210 }
14211 }
14212 }
14213 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014214 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014216 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014218 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014219 hdd_notice("Skip DEL STA as this is not used::"
14220 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014221 MAC_ADDR_ARRAY(mac));
14222 return -ENOENT;
14223 }
14224
14225 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14226 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014227 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228 }
14229
14230 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
14231 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014232 hdd_notice("Skip DEL STA as deauth is in progress::"
14233 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234 MAC_ADDR_ARRAY(mac));
14235 return -ENOENT;
14236 }
14237
14238 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
14239
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014240 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241 MAC_ADDR_ARRAY(mac));
14242
14243 /* Case: SAP in ACS selected DFS ch and client connected
14244 * Now Radar detected. Then if random channel is another
14245 * DFS ch then new CAC is initiated and no TX allowed.
14246 * So do not send any mgmt frames as it will timeout
14247 * during CAC.
14248 */
14249
14250 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
14251 goto fn_end;
14252
Wei Song2f76f642016-11-18 16:32:53 +080014253 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053014254 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
14255 (pAdapter), pAdapter->sessionId,
14256 (uint8_t *)&pDelStaParams->peerMacAddr,
14257 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014258 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014260 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 pAdapter->aStaInfo[staId].isDeauthInProgress =
14262 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014263 hdd_notice("STA removal failed for ::"
14264 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014265 MAC_ADDR_ARRAY(mac));
14266 return -ENOENT;
14267 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053014268 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014269 &hapd_state->
14270 qdf_sta_disassoc_event,
14271 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014272 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014273 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274 }
14275 }
14276 }
14277
14278fn_end:
14279 EXIT();
14280 return 0;
14281}
14282
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014283#if defined(USE_CFG80211_DEL_STA_V2)
14284/**
14285 * wlan_hdd_del_station() - delete station wrapper
14286 * @adapter: pointer to the hdd adapter
14287 *
14288 * Return: None
14289 */
14290void wlan_hdd_del_station(hdd_adapter_t *adapter)
14291{
14292 struct station_del_parameters del_sta;
14293 del_sta.mac = NULL;
14294 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
14295 del_sta.reason_code = eCsrForcedDeauthSta;
14296
14297 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
14298 &del_sta);
14299}
14300#else
14301void wlan_hdd_del_station(hdd_adapter_t *adapter)
14302{
14303 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
14304}
14305#endif
14306
14307#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014308/**
14309 * wlan_hdd_cfg80211_del_station() - delete station v2
14310 * @wiphy: Pointer to wiphy
14311 * @param: Pointer to delete station parameter
14312 *
14313 * Return: 0 for success, non-zero for failure
14314 */
14315int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14316 struct net_device *dev,
14317 struct station_del_parameters *param)
14318#else
14319/**
14320 * wlan_hdd_cfg80211_del_station() - delete station
14321 * @wiphy: Pointer to wiphy
14322 * @mac: Pointer to station mac address
14323 *
14324 * Return: 0 for success, non-zero for failure
14325 */
14326#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14327int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14328 struct net_device *dev,
14329 const uint8_t *mac)
14330#else
14331int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14332 struct net_device *dev,
14333 uint8_t *mac)
14334#endif
14335#endif
14336{
14337 int ret;
14338 struct tagCsrDelStaParams delStaParams;
14339
14340 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014341#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014343 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 return -EINVAL;
14345 }
14346 wlansap_populate_del_sta_params(param->mac, param->reason_code,
14347 param->subtype, &delStaParams);
14348#else
14349 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14350 (SIR_MAC_MGMT_DEAUTH >> 4),
14351 &delStaParams);
14352#endif
14353 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
14354 cds_ssr_unprotect(__func__);
14355
14356 return ret;
14357}
14358
14359/**
14360 * __wlan_hdd_cfg80211_add_station() - add station
14361 * @wiphy: Pointer to wiphy
14362 * @mac: Pointer to station mac address
14363 * @pmksa: Pointer to add station parameter
14364 *
14365 * Return: 0 for success, non-zero for failure
14366 */
14367static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14368 struct net_device *dev,
14369 const uint8_t *mac,
14370 struct station_parameters *params)
14371{
14372 int status = -EPERM;
14373#ifdef FEATURE_WLAN_TDLS
14374 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14375 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14376 u32 mask, set;
14377
14378 ENTER();
14379
Anurag Chouhan6d760662016-02-20 16:05:43 +053014380 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014381 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 return -EINVAL;
14383 }
14384
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014385 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14386 hdd_err("invalid session id: %d", pAdapter->sessionId);
14387 return -EINVAL;
14388 }
14389
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014390 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014391 TRACE_CODE_HDD_CFG80211_ADD_STA,
14392 pAdapter->sessionId, params->listen_interval));
14393
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014394 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014395 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014396
14397 mask = params->sta_flags_mask;
14398
14399 set = params->sta_flags_set;
14400
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014401 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014402 MAC_ADDR_ARRAY(mac));
14403
14404 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14405 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14406 status =
14407 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
14408 }
14409 }
14410#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014411 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014412 return status;
14413}
14414
14415/**
14416 * wlan_hdd_cfg80211_add_station() - add station
14417 * @wiphy: Pointer to wiphy
14418 * @mac: Pointer to station mac address
14419 * @pmksa: Pointer to add station parameter
14420 *
14421 * Return: 0 for success, non-zero for failure
14422 */
14423#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14424static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14425 struct net_device *dev,
14426 const uint8_t *mac,
14427 struct station_parameters *params)
14428#else
14429static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14430 struct net_device *dev, uint8_t *mac,
14431 struct station_parameters *params)
14432#endif
14433{
14434 int ret;
14435
14436 cds_ssr_protect(__func__);
14437 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
14438 cds_ssr_unprotect(__func__);
14439
14440 return ret;
14441}
14442
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014443/**
14444 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
14445 * @wiphy: Pointer to wiphy
14446 * @dev: Pointer to network device
14447 * @pmksa: Pointer to set pmksa parameter
14448 *
14449 * Return: 0 for success, non-zero for failure
14450 */
14451static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14452 struct net_device *dev,
14453 struct cfg80211_pmksa *pmksa)
14454{
14455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14456 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14457 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014458 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014459 int status;
14460 tPmkidCacheInfo pmk_id;
14461
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014462 ENTER();
14463
Anurag Chouhan6d760662016-02-20 16:05:43 +053014464 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014465 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014466 return -EINVAL;
14467 }
14468
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014469 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14470 hdd_err("invalid session id: %d", pAdapter->sessionId);
14471 return -EINVAL;
14472 }
14473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014475 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476 return -EINVAL;
14477 }
14478
14479 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014480 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481 pmksa->bssid, pmksa->pmkid);
14482 return -EINVAL;
14483 }
14484
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014485 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 MAC_ADDR_ARRAY(pmksa->bssid));
14487
14488 status = wlan_hdd_validate_context(pHddCtx);
14489
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014490 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014491 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014492
14493 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14494
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014495 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14496 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014497
14498 /* Add to the PMKSA ID Cache in CSR */
14499 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14500 &pmk_id, 1, false);
14501
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014502 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014503 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14504 pAdapter->sessionId, result));
14505
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014506 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014507 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014508}
14509
14510/**
14511 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14512 * @wiphy: Pointer to wiphy
14513 * @dev: Pointer to network device
14514 * @pmksa: Pointer to set pmksa parameter
14515 *
14516 * Return: 0 for success, non-zero for failure
14517 */
14518static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14519 struct net_device *dev,
14520 struct cfg80211_pmksa *pmksa)
14521{
14522 int ret;
14523
14524 cds_ssr_protect(__func__);
14525 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14526 cds_ssr_unprotect(__func__);
14527
14528 return ret;
14529}
14530
14531/**
14532 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14533 * @wiphy: Pointer to wiphy
14534 * @dev: Pointer to network device
14535 * @pmksa: Pointer to pmksa parameter
14536 *
14537 * Return: 0 for success, non-zero for failure
14538 */
14539static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14540 struct net_device *dev,
14541 struct cfg80211_pmksa *pmksa)
14542{
14543 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14544 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14545 tHalHandle halHandle;
14546 int status = 0;
14547
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014548 ENTER();
14549
Anurag Chouhan6d760662016-02-20 16:05:43 +053014550 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014551 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 return -EINVAL;
14553 }
14554
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014555 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14556 hdd_err("invalid session id: %d", pAdapter->sessionId);
14557 return -EINVAL;
14558 }
14559
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014560 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014561 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 return -EINVAL;
14563 }
14564
14565 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014566 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 return -EINVAL;
14568 }
14569
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014570 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014571 MAC_ADDR_ARRAY(pmksa->bssid));
14572
14573 status = wlan_hdd_validate_context(pHddCtx);
14574
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014575 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014576 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014577
14578 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14579
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014580 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014581 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14582 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014583 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014584 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014585 sme_roam_del_pmkid_from_cache(halHandle,
14586 pAdapter->sessionId, pmksa->bssid,
14587 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014588 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014589 MAC_ADDR_ARRAY(pmksa->bssid));
14590 status = -EINVAL;
14591 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014592 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014593 return status;
14594}
14595
14596/**
14597 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14598 * @wiphy: Pointer to wiphy
14599 * @dev: Pointer to network device
14600 * @pmksa: Pointer to pmksa parameter
14601 *
14602 * Return: 0 for success, non-zero for failure
14603 */
14604static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14605 struct net_device *dev,
14606 struct cfg80211_pmksa *pmksa)
14607{
14608 int ret;
14609
14610 cds_ssr_protect(__func__);
14611 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14612 cds_ssr_unprotect(__func__);
14613
14614 return ret;
14615
14616}
14617
14618/**
14619 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14620 * @wiphy: Pointer to wiphy
14621 * @dev: Pointer to network device
14622 *
14623 * Return: 0 for success, non-zero for failure
14624 */
14625static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14626 struct net_device *dev)
14627{
14628 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14629 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14630 tHalHandle halHandle;
14631 int status = 0;
14632
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014633 ENTER();
14634
Anurag Chouhan6d760662016-02-20 16:05:43 +053014635 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014636 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014637 return -EINVAL;
14638 }
14639
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014640 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14641 hdd_err("invalid session id: %d", pAdapter->sessionId);
14642 return -EINVAL;
14643 }
14644
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014645 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014646
14647 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14648 status = wlan_hdd_validate_context(pHddCtx);
14649
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014650 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014651 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014652
14653 /* Retrieve halHandle */
14654 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14655
14656 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014657 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014658 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14659 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014660 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014661 status = -EINVAL;
14662 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014663 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014664 return status;
14665}
14666
14667/**
14668 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14669 * @wiphy: Pointer to wiphy
14670 * @dev: Pointer to network device
14671 *
14672 * Return: 0 for success, non-zero for failure
14673 */
14674static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14675 struct net_device *dev)
14676{
14677 int ret;
14678
14679 cds_ssr_protect(__func__);
14680 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14681 cds_ssr_unprotect(__func__);
14682
14683 return ret;
14684}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014686#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687/**
14688 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14689 * @wiphy: Pointer to wiphy
14690 * @dev: Pointer to network device
14691 * @ftie: Pointer to fast transition ie parameter
14692 *
14693 * Return: 0 for success, non-zero for failure
14694 */
14695static int
14696__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14697 struct net_device *dev,
14698 struct cfg80211_update_ft_ies_params *ftie)
14699{
14700 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14701 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14702 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14703 int status;
14704
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014705 ENTER();
14706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014707 status = wlan_hdd_validate_context(hdd_ctx);
14708 if (status)
14709 return status;
14710
Anurag Chouhan6d760662016-02-20 16:05:43 +053014711 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014712 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 return -EINVAL;
14714 }
14715
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014716 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14717 hdd_err("invalid session id: %d", pAdapter->sessionId);
14718 return -EINVAL;
14719 }
14720
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014721 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14723 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14724 /* Added for debug on reception of Re-assoc Req. */
14725 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014726 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014727 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014728 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014729 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014730 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014732
14733 /* Pass the received FT IEs to SME */
14734 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14735 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014736 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014737 return 0;
14738}
14739
14740/**
14741 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14742 * @wiphy: Pointer to wiphy
14743 * @dev: Pointer to network device
14744 * @ftie: Pointer to fast transition ie parameter
14745 *
14746 * Return: 0 for success, non-zero for failure
14747 */
14748static int
14749wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14750 struct net_device *dev,
14751 struct cfg80211_update_ft_ies_params *ftie)
14752{
14753 int ret;
14754
14755 cds_ssr_protect(__func__);
14756 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14757 cds_ssr_unprotect(__func__);
14758
14759 return ret;
14760}
14761#endif
14762
14763#ifdef WLAN_FEATURE_GTK_OFFLOAD
14764/**
14765 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14766 * @callbackContext: Callback context
14767 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14768 *
14769 * Callback rountine called upon receiving response for get offload info
14770 *
14771 * Return: none
14772 */
14773void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14774 tpSirGtkOffloadGetInfoRspParams
14775 pGtkOffloadGetInfoRsp)
14776{
14777 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14778 uint8_t tempReplayCounter[8];
14779 hdd_station_ctx_t *pHddStaCtx;
14780
14781 ENTER();
14782
14783 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014784 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014785 return;
14786 }
14787
14788 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014789 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014790 return;
14791 }
14792
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014793 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014794 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014795 return;
14796 }
14797
14798 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14799 /* Update replay counter */
14800 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14801 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14802
14803 {
14804 /* changing from little to big endian since supplicant
14805 * works on big endian format
14806 */
14807 int i;
14808 uint8_t *p =
14809 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14810
14811 for (i = 0; i < 8; i++) {
14812 tempReplayCounter[7 - i] = (uint8_t) p[i];
14813 }
14814 }
14815
14816 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014817 cfg80211_gtk_rekey_notify(pAdapter->dev,
14818 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014819 tempReplayCounter, GFP_KERNEL);
14820}
14821
14822/**
14823 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14824 * @wiphy: Pointer to wiphy
14825 * @dev: Pointer to network device
14826 * @data: Pointer to rekey data
14827 *
14828 * This function is used to offload GTK rekeying job to the firmware.
14829 *
14830 * Return: 0 for success, non-zero for failure
14831 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014832static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014833int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14834 struct net_device *dev,
14835 struct cfg80211_gtk_rekey_data *data)
14836{
14837 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14838 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14839 hdd_station_ctx_t *pHddStaCtx;
14840 tHalHandle hHal;
14841 int result;
14842 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014843 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014844
14845 ENTER();
14846
Anurag Chouhan6d760662016-02-20 16:05:43 +053014847 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014848 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 return -EINVAL;
14850 }
14851
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014852 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14853 hdd_err("invalid session id: %d", pAdapter->sessionId);
14854 return -EINVAL;
14855 }
14856
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014857 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014858 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14859 pAdapter->sessionId, pAdapter->device_mode));
14860
14861 result = wlan_hdd_validate_context(pHddCtx);
14862
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014863 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014864 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014865
14866 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14867 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14868 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014869 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014870 return -EAGAIN;
14871 }
14872
14873 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14874 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14875 NL80211_KCK_LEN);
14876 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14877 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014878 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014879 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014880 {
14881 /* changing from big to little endian since driver
14882 * works on little endian format
14883 */
14884 uint8_t *p =
14885 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14886 ullKeyReplayCounter;
14887 int i;
14888
14889 for (i = 0; i < 8; i++) {
14890 p[7 - i] = data->replay_ctr[i];
14891 }
14892 }
14893
14894 if (true == pHddCtx->hdd_wlan_suspended) {
14895 /* if wlan is suspended, enable GTK offload directly from here */
14896 memcpy(&hddGtkOffloadReqParams,
14897 &pHddStaCtx->gtkOffloadReqParams,
14898 sizeof(tSirGtkOffloadParams));
14899 status =
14900 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14901 pAdapter->sessionId);
14902
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014903 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014904 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014905 status);
14906 return -EINVAL;
14907 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014908 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014909 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014910 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014912 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014913 return result;
14914}
14915
14916/**
14917 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14918 * @wiphy: Pointer to wiphy
14919 * @dev: Pointer to network device
14920 * @data: Pointer to rekey data
14921 *
14922 * This function is used to offload GTK rekeying job to the firmware.
14923 *
14924 * Return: 0 for success, non-zero for failure
14925 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014926static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014927int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14928 struct net_device *dev,
14929 struct cfg80211_gtk_rekey_data *data)
14930{
14931 int ret;
14932
14933 cds_ssr_protect(__func__);
14934 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14935 cds_ssr_unprotect(__func__);
14936
14937 return ret;
14938}
14939#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14940
14941/**
14942 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14943 * @wiphy: Pointer to wiphy
14944 * @dev: Pointer to network device
14945 * @param: Pointer to access control parameter
14946 *
14947 * Return: 0 for success, non-zero for failure
14948 */
14949static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14950 struct net_device *dev,
14951 const struct cfg80211_acl_data *params)
14952{
14953 int i;
14954 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14955 hdd_hostapd_state_t *pHostapdState;
14956 tsap_Config_t *pConfig;
14957 v_CONTEXT_t p_cds_context = NULL;
14958 hdd_context_t *pHddCtx;
14959 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014960 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014961
14962 ENTER();
14963
Anurag Chouhan6d760662016-02-20 16:05:43 +053014964 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014965 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014966 return -EINVAL;
14967 }
14968
14969 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014970 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014971 return -EINVAL;
14972 }
14973
14974 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14975 status = wlan_hdd_validate_context(pHddCtx);
14976
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014977 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014979
14980 p_cds_context = pHddCtx->pcds_context;
14981 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14982
14983 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014984 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014985 return -EINVAL;
14986 }
14987
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014988 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014989 params->n_acl_entries);
14990
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014991 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014992 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14993 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014994 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014995 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14996
14997 /* default value */
14998 pConfig->num_accept_mac = 0;
14999 pConfig->num_deny_mac = 0;
15000
15001 /**
15002 * access control policy
15003 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15004 * listed in hostapd.deny file.
15005 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15006 * listed in hostapd.accept file.
15007 */
15008 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15009 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15010 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15011 params->acl_policy) {
15012 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15013 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015014 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015015 params->acl_policy);
15016 return -ENOTSUPP;
15017 }
15018
15019 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15020 pConfig->num_accept_mac = params->n_acl_entries;
15021 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015022 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15023 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024 MAC_ADDR_ARRAY(
15025 params->mac_addrs[i].addr));
15026
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015027 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015028 params->mac_addrs[i].addr,
15029 sizeof(qcmacaddr));
15030 }
15031 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15032 pConfig->num_deny_mac = params->n_acl_entries;
15033 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015034 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15035 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 MAC_ADDR_ARRAY(
15037 params->mac_addrs[i].addr));
15038
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015039 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015040 params->mac_addrs[i].addr,
15041 sizeof(qcmacaddr));
15042 }
15043 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015044 qdf_status = wlansap_set_mac_acl(
15045 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015046 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015047 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015048 return -EINVAL;
15049 }
15050 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015051 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 hdd_device_mode_to_string(pAdapter->device_mode),
15053 pAdapter->device_mode);
15054 return -EINVAL;
15055 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015056 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015057 return 0;
15058}
15059
15060/**
15061 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15062 * __wlan_hdd_cfg80211_set_mac_acl
15063 * @wiphy: pointer to wiphy structure
15064 * @dev: pointer to net_device
15065 * @params: pointer to cfg80211_acl_data
15066 *
15067 * Return; 0 on success, error number otherwise
15068 */
15069static int
15070wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15071 struct net_device *dev,
15072 const struct cfg80211_acl_data *params)
15073{
15074 int ret;
15075
15076 cds_ssr_protect(__func__);
15077 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15078 cds_ssr_unprotect(__func__);
15079
15080 return ret;
15081}
15082
15083#ifdef WLAN_NL80211_TESTMODE
15084#ifdef FEATURE_WLAN_LPHB
15085/**
15086 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15087 * @pHddCtx: Pointer to hdd context
15088 * @lphbInd: Pointer to low power heart beat indication parameter
15089 *
15090 * Return: none
15091 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015092static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15093 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015094{
15095 struct sk_buff *skb;
15096
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015097 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015098
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015099 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015100 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015101
15102 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015103 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 return;
15105 }
15106
15107 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15108 wiphy, sizeof(tSirLPHBInd),
15109 GFP_ATOMIC);
15110 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015111 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015112 return;
15113 }
15114
15115 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015116 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015117 goto nla_put_failure;
15118 }
15119 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015120 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015121 goto nla_put_failure;
15122 }
15123 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015124 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125 goto nla_put_failure;
15126 }
15127 cfg80211_testmode_event(skb, GFP_ATOMIC);
15128 return;
15129
15130nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015131 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015132 kfree_skb(skb);
15133
15134 return;
15135}
15136#endif /* FEATURE_WLAN_LPHB */
15137
15138/**
15139 * __wlan_hdd_cfg80211_testmode() - test mode
15140 * @wiphy: Pointer to wiphy
15141 * @data: Data pointer
15142 * @len: Data length
15143 *
15144 * Return: 0 for success, non-zero for failure
15145 */
15146static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15147 void *data, int len)
15148{
15149 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
15150 int err;
15151 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15152
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015153 ENTER();
15154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015155 err = wlan_hdd_validate_context(pHddCtx);
15156 if (err)
15157 return err;
15158
15159 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
15160 len, wlan_hdd_tm_policy);
15161 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015162 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163 return err;
15164 }
15165
15166 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015167 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015168 return -EINVAL;
15169 }
15170
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015171 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015172 TRACE_CODE_HDD_CFG80211_TESTMODE,
15173 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015174 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
15175#ifdef FEATURE_WLAN_LPHB
15176 /* Low Power Heartbeat configuration request */
15177 case WLAN_HDD_TM_CMD_WLAN_HB:
15178 {
15179 int buf_len;
15180 void *buf;
15181 tSirLPHBReq *hb_params = NULL;
15182 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015183 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015184
15185 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015186 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 return -EINVAL;
15188 }
15189
15190 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15191 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15192
15193 hb_params_temp = (tSirLPHBReq *) buf;
15194 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
15195 && (hb_params_temp->params.lphbTcpParamReq.
15196 timePeriodSec == 0))
15197 return -EINVAL;
15198
15199 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015200 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015201 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015202 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015203 return -ENOMEM;
15204 }
15205
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015206 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015207 smeStatus =
15208 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
15209 hb_params,
15210 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015211 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015212 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015213 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015214 }
15215 return 0;
15216 }
15217#endif /* FEATURE_WLAN_LPHB */
15218
15219#if defined(QCA_WIFI_FTM)
15220 case WLAN_HDD_TM_CMD_WLAN_FTM:
15221 {
15222 int buf_len;
15223 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015224 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015225 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015226 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015227 return -EINVAL;
15228 }
15229
15230 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15231 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15232
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015233 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015234
15235 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
15236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015237 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015238 err = -EBUSY;
15239 break;
15240 }
15241#endif
15242
15243 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015244 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015245 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
15246 return -EOPNOTSUPP;
15247 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015248 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015249 return err;
15250}
15251
15252/**
15253 * wlan_hdd_cfg80211_testmode() - test mode
15254 * @wiphy: Pointer to wiphy
15255 * @dev: Pointer to network device
15256 * @data: Data pointer
15257 * @len: Data length
15258 *
15259 * Return: 0 for success, non-zero for failure
15260 */
15261static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15262#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
15263 struct wireless_dev *wdev,
15264#endif
15265 void *data, int len)
15266{
15267 int ret;
15268
15269 cds_ssr_protect(__func__);
15270 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
15271 cds_ssr_unprotect(__func__);
15272
15273 return ret;
15274}
15275
15276#if defined(QCA_WIFI_FTM)
15277/**
15278 * wlan_hdd_testmode_rx_event() - test mode rx event handler
15279 * @buf: Pointer to buffer
15280 * @buf_len: Buffer length
15281 *
15282 * Return: none
15283 */
15284void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
15285{
15286 struct sk_buff *skb;
15287 hdd_context_t *hdd_ctx;
15288
15289 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015290 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291 return;
15292 }
15293
Anurag Chouhan6d760662016-02-20 16:05:43 +053015294 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015296 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015297 return;
15298 }
15299
15300 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
15301 buf_len, GFP_KERNEL);
15302 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015303 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 return;
15305 }
15306
15307 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
15308 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
15309 goto nla_put_failure;
15310
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015311 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015312
15313 cfg80211_testmode_event(skb, GFP_KERNEL);
15314 return;
15315
15316nla_put_failure:
15317 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015318 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015319}
15320#endif
15321#endif /* CONFIG_NL80211_TESTMODE */
15322
15323#ifdef QCA_HT_2040_COEX
15324/**
15325 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15326 * @wiphy: Pointer to wiphy
15327 * @dev: Pointer to network device
15328 * @chandef: Pointer to channel definition parameter
15329 *
15330 * Return: 0 for success, non-zero for failure
15331 */
15332static int
15333__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15334 struct net_device *dev,
15335 struct cfg80211_chan_def *chandef)
15336{
15337 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15338 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015339 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015340 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053015341 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015342
Anurag Chouhan6d760662016-02-20 16:05:43 +053015343 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015344 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015345 return -EINVAL;
15346 }
15347
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015348 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15349 hdd_err("invalid session id: %d", pAdapter->sessionId);
15350 return -EINVAL;
15351 }
15352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015353 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15354 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053015355 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015357
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015358 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015359 sme_get_config_param(pHddCtx->hHal, &sme_config);
15360 switch (chandef->width) {
15361 case NL80211_CHAN_WIDTH_20:
15362 if (sme_config.csrConfig.channelBondingMode24GHz !=
15363 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15364 sme_config.csrConfig.channelBondingMode24GHz =
15365 eCSR_INI_SINGLE_CHANNEL_CENTERED;
15366 sme_update_config(pHddCtx->hHal, &sme_config);
15367 cbModeChange = true;
15368 }
15369 break;
15370
15371 case NL80211_CHAN_WIDTH_40:
15372 if (sme_config.csrConfig.channelBondingMode24GHz ==
15373 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15374 if (NL80211_CHAN_HT40MINUS ==
15375 cfg80211_get_chandef_type(chandef))
15376 sme_config.csrConfig.channelBondingMode24GHz =
15377 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
15378 else
15379 sme_config.csrConfig.channelBondingMode24GHz =
15380 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
15381 sme_update_config(pHddCtx->hHal, &sme_config);
15382 cbModeChange = true;
15383 }
15384 break;
15385
15386 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015387 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015388 return -EINVAL;
15389 }
15390
15391 if (!cbModeChange)
15392 return 0;
15393
Krunal Sonib4326f22016-03-10 13:05:51 -080015394 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015395 return 0;
15396
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015397 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015398 sme_config.csrConfig.channelBondingMode24GHz);
15399
15400 /* Change SAP ht2040 mode */
15401 status = hdd_set_sap_ht2040_mode(pAdapter,
15402 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015403 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015404 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015405 return -EINVAL;
15406 }
15407
15408 return 0;
15409}
15410
15411/**
15412 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15413 * @wiphy: Pointer to wiphy
15414 * @dev: Pointer to network device
15415 * @chandef: Pointer to channel definition parameter
15416 *
15417 * Return: 0 for success, non-zero for failure
15418 */
15419static int
15420wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15421 struct net_device *dev,
15422 struct cfg80211_chan_def *chandef)
15423{
15424 int ret;
15425
15426 cds_ssr_protect(__func__);
15427 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
15428 cds_ssr_unprotect(__func__);
15429
15430 return ret;
15431}
15432#endif
15433
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015434#ifdef CHANNEL_SWITCH_SUPPORTED
15435/**
15436 * __wlan_hdd_cfg80211_channel_switch()- function to switch
15437 * channel in SAP/GO
15438 * @wiphy: wiphy pointer
15439 * @dev: dev pointer.
15440 * @csa_params: Change channel params
15441 *
15442 * This function is called to switch channel in SAP/GO
15443 *
15444 * Return: 0 if success else return non zero
15445 */
15446static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15447 struct net_device *dev,
15448 struct cfg80211_csa_settings *csa_params)
15449{
15450 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15451 hdd_context_t *hdd_ctx;
15452 uint8_t channel;
15453 uint16_t freq;
15454 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080015455 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015456
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015457 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015458 csa_params->chandef.chan->center_freq);
15459
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015460 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
15461 hdd_err("invalid session id: %d", adapter->sessionId);
15462 return -EINVAL;
15463 }
15464
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015465 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15466 ret = wlan_hdd_validate_context(hdd_ctx);
15467
15468 if (0 != ret)
15469 return ret;
15470
Krunal Sonib4326f22016-03-10 13:05:51 -080015471 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
15472 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015473 return -ENOTSUPP;
15474
15475 freq = csa_params->chandef.chan->center_freq;
15476 channel = cds_freq_to_chan(freq);
15477
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053015478 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
15479
15480 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015481 return ret;
15482}
15483
15484/**
15485 * wlan_hdd_cfg80211_channel_switch()- function to switch
15486 * channel in SAP/GO
15487 * @wiphy: wiphy pointer
15488 * @dev: dev pointer.
15489 * @csa_params: Change channel params
15490 *
15491 * This function is called to switch channel in SAP/GO
15492 *
15493 * Return: 0 if success else return non zero
15494 */
15495static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15496 struct net_device *dev,
15497 struct cfg80211_csa_settings *csa_params)
15498{
15499 int ret;
15500
15501 cds_ssr_protect(__func__);
15502 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15503 cds_ssr_unprotect(__func__);
15504 return ret;
15505}
15506#endif
15507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015508/**
15509 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15510 * translation from NL to policy manager type
15511 * @type: Generic connection mode type defined in NL
15512 *
15513 *
15514 * This function provides the type translation
15515 *
15516 * Return: cds_con_mode enum
15517 */
15518enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15519 enum nl80211_iftype type)
15520{
15521 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15522 switch (type) {
15523 case NL80211_IFTYPE_STATION:
15524 mode = CDS_STA_MODE;
15525 break;
15526 case NL80211_IFTYPE_P2P_CLIENT:
15527 mode = CDS_P2P_CLIENT_MODE;
15528 break;
15529 case NL80211_IFTYPE_P2P_GO:
15530 mode = CDS_P2P_GO_MODE;
15531 break;
15532 case NL80211_IFTYPE_AP:
15533 mode = CDS_SAP_MODE;
15534 break;
15535 case NL80211_IFTYPE_ADHOC:
15536 mode = CDS_IBSS_MODE;
15537 break;
15538 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015539 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015540 type);
15541 }
15542 return mode;
15543}
15544
15545/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015546 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15547 * @wiphy: Handle to struct wiphy to get handle to module context.
15548 * @chandef: Contains information about the capture channel to be set.
15549 *
15550 * This interface is called if and only if monitor mode interface alone is
15551 * active.
15552 *
15553 * Return: 0 success or error code on failure.
15554 */
15555static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15556 struct cfg80211_chan_def *chandef)
15557{
15558 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15559 hdd_adapter_t *adapter;
15560 hdd_station_ctx_t *sta_ctx;
15561 struct hdd_mon_set_ch_info *ch_info;
15562 QDF_STATUS status;
15563 tHalHandle hal_hdl;
15564 struct qdf_mac_addr bssid;
15565 tCsrRoamProfile roam_profile;
15566 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015567 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015568 int ret;
15569 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15570
15571 ENTER();
15572
15573 ret = wlan_hdd_validate_context(hdd_ctx);
15574 if (ret)
15575 return ret;
15576
15577 hal_hdl = hdd_ctx->hHal;
15578
15579 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15580 if (!adapter)
15581 return -EIO;
15582
15583 hdd_info("%s: set monitor mode Channel %d and freq %d",
15584 adapter->dev->name, chan_num, chandef->chan->center_freq);
15585
15586 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15587 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015588 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15589 roam_profile.ChannelInfo.numOfChannels = 1;
15590 roam_profile.phyMode = ch_info->phy_mode;
15591 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015592 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015593
15594 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15595 QDF_MAC_ADDR_SIZE);
15596
15597 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015598 /*
15599 * CDS api expects secondary channel for calculating
15600 * the channel params
15601 */
15602 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15603 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15604 if (chan_num >= 1 && chan_num <= 5)
15605 sec_ch = chan_num + 4;
15606 else if (chan_num >= 6 && chan_num <= 13)
15607 sec_ch = chan_num - 4;
15608 }
15609 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015610 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15611 &roam_profile);
15612 if (status) {
15613 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15614 status);
15615 ret = qdf_status_to_os_return(status);
15616 return ret;
15617 }
15618 EXIT();
15619 return 0;
15620}
15621
15622/**
15623 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15624 * @wiphy: Handle to struct wiphy to get handle to module context.
15625 * @chandef: Contains information about the capture channel to be set.
15626 *
15627 * This interface is called if and only if monitor mode interface alone is
15628 * active.
15629 *
15630 * Return: 0 success or error code on failure.
15631 */
15632static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15633 struct cfg80211_chan_def *chandef)
15634{
15635 int ret;
15636
15637 cds_ssr_protect(__func__);
15638 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15639 cds_ssr_unprotect(__func__);
15640 return ret;
15641}
15642
15643/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015644 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15645 * @adapter: pointer to adapter
15646 *
15647 * Wrapper function to clear link layer stats.
15648 * return - void
15649 */
15650void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15651{
15652 tSirLLStatsClearReq link_layer_stats_clear_req;
15653 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15654
Mukul Sharma491021c2016-09-29 21:39:19 +053015655 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15656 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015657 link_layer_stats_clear_req.stopReq = 0;
15658 link_layer_stats_clear_req.reqId = 1;
15659 link_layer_stats_clear_req.staId = adapter->sessionId;
15660 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15661
15662 return;
15663}
15664
15665/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015666 * struct cfg80211_ops - cfg80211_ops
15667 *
15668 * @add_virtual_intf: Add virtual interface
15669 * @del_virtual_intf: Delete virtual interface
15670 * @change_virtual_intf: Change virtual interface
15671 * @change_station: Change station
15672 * @add_beacon: Add beacon in sap mode
15673 * @del_beacon: Delete beacon in sap mode
15674 * @set_beacon: Set beacon in sap mode
15675 * @start_ap: Start ap
15676 * @change_beacon: Change beacon
15677 * @stop_ap: Stop ap
15678 * @change_bss: Change bss
15679 * @add_key: Add key
15680 * @get_key: Get key
15681 * @del_key: Delete key
15682 * @set_default_key: Set default key
15683 * @set_channel: Set channel
15684 * @scan: Scan
15685 * @connect: Connect
15686 * @disconnect: Disconnect
15687 * @join_ibss = Join ibss
15688 * @leave_ibss = Leave ibss
15689 * @set_wiphy_params = Set wiphy params
15690 * @set_tx_power = Set tx power
15691 * @get_tx_power = get tx power
15692 * @remain_on_channel = Remain on channel
15693 * @cancel_remain_on_channel = Cancel remain on channel
15694 * @mgmt_tx = Tx management frame
15695 * @mgmt_tx_cancel_wait = Cancel management tx wait
15696 * @set_default_mgmt_key = Set default management key
15697 * @set_txq_params = Set tx queue parameters
15698 * @get_station = Get station
15699 * @set_power_mgmt = Set power management
15700 * @del_station = Delete station
15701 * @add_station = Add station
15702 * @set_pmksa = Set pmksa
15703 * @del_pmksa = Delete pmksa
15704 * @flush_pmksa = Flush pmksa
15705 * @update_ft_ies = Update FT IEs
15706 * @tdls_mgmt = Tdls management
15707 * @tdls_oper = Tdls operation
15708 * @set_rekey_data = Set rekey data
15709 * @sched_scan_start = Scheduled scan start
15710 * @sched_scan_stop = Scheduled scan stop
15711 * @resume = Resume wlan
15712 * @suspend = Suspend wlan
15713 * @set_mac_acl = Set mac acl
15714 * @testmode_cmd = Test mode command
15715 * @set_ap_chanwidth = Set AP channel bandwidth
15716 * @dump_survey = Dump survey
15717 * @key_mgmt_set_pmk = Set pmk key management
15718 */
15719static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15720 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15721 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15722 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15723 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015724 .start_ap = wlan_hdd_cfg80211_start_ap,
15725 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15726 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015727 .change_bss = wlan_hdd_cfg80211_change_bss,
15728 .add_key = wlan_hdd_cfg80211_add_key,
15729 .get_key = wlan_hdd_cfg80211_get_key,
15730 .del_key = wlan_hdd_cfg80211_del_key,
15731 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15732 .scan = wlan_hdd_cfg80211_scan,
15733 .connect = wlan_hdd_cfg80211_connect,
15734 .disconnect = wlan_hdd_cfg80211_disconnect,
15735 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15736 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15737 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15738 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15739 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15740 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15741 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15742 .mgmt_tx = wlan_hdd_mgmt_tx,
15743 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15744 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15745 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015746 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015747 .get_station = wlan_hdd_cfg80211_get_station,
15748 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15749 .del_station = wlan_hdd_cfg80211_del_station,
15750 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15752 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15753 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015754#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015755 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15756#endif
15757#ifdef FEATURE_WLAN_TDLS
15758 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15759 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15760#endif
15761#ifdef WLAN_FEATURE_GTK_OFFLOAD
15762 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15763#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15764#ifdef FEATURE_WLAN_SCAN_PNO
15765 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15766 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15767#endif /*FEATURE_WLAN_SCAN_PNO */
15768 .resume = wlan_hdd_cfg80211_resume_wlan,
15769 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15770 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15771#ifdef WLAN_NL80211_TESTMODE
15772 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15773#endif
15774#ifdef QCA_HT_2040_COEX
15775 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15776#endif
15777 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015778#ifdef CHANNEL_SWITCH_SUPPORTED
15779 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15780#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015781 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015782#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15783 defined(CFG80211_ABORT_SCAN)
15784 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15785#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015786};