blob: ef26677fea0e52fadae836bba9781a6dc7dbd45e [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
Ravi Joshideb5a8d2015-11-09 19:11:43 -080096#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053097#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070098#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070099#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530100#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800101
Leo Changfdb45c32016-10-28 11:09:23 -0700102#include <cdp_txrx_cmn.h>
103#include <cdp_txrx_misc.h>
104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define g_mode_rates_size (12)
106#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
108 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
109
110/*
111 * Android CTS verifier needs atleast this much wait time (in msec)
112 */
113#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
114
115/*
116 * Refer @tCfgProtection structure for definition of the bit map.
117 * below value is obtained by setting the following bit-fields.
118 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
119 */
120#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
121
122#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700123 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 .center_freq = (freq), \
125 .hw_value = (chan), \
126 .flags = (flag), \
127 .max_antenna_gain = 0, \
128 .max_power = 30, \
129}
130
131#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
137 .max_power = 30, \
138}
139
140#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
141 { \
142 .bitrate = rate, \
143 .hw_value = rate_id, \
144 .flags = flag, \
145 }
146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
148#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
150#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
Agrawal Ashish65634612016-08-18 13:24:32 +0530152#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
153 mode <= DFS_MODE_DEPRIORITIZE))
154#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
155 || (channel >= 36 && channel <= 184))
156
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530158#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160static const u32 hdd_cipher_suites[] = {
161 WLAN_CIPHER_SUITE_WEP40,
162 WLAN_CIPHER_SUITE_WEP104,
163 WLAN_CIPHER_SUITE_TKIP,
164#ifdef FEATURE_WLAN_ESE
165#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
166#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
167 WLAN_CIPHER_SUITE_BTK,
168 WLAN_CIPHER_SUITE_KRK,
169 WLAN_CIPHER_SUITE_CCMP,
170#else
171 WLAN_CIPHER_SUITE_CCMP,
172#endif
173#ifdef FEATURE_WLAN_WAPI
174 WLAN_CIPHER_SUITE_SMS4,
175#endif
176#ifdef WLAN_FEATURE_11W
177 WLAN_CIPHER_SUITE_AES_CMAC,
178#endif
179};
180
Abhishek Singhf512bf32016-05-04 16:47:46 +0530181static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 HDD2GHZCHAN(2412, 1, 0),
183 HDD2GHZCHAN(2417, 2, 0),
184 HDD2GHZCHAN(2422, 3, 0),
185 HDD2GHZCHAN(2427, 4, 0),
186 HDD2GHZCHAN(2432, 5, 0),
187 HDD2GHZCHAN(2437, 6, 0),
188 HDD2GHZCHAN(2442, 7, 0),
189 HDD2GHZCHAN(2447, 8, 0),
190 HDD2GHZCHAN(2452, 9, 0),
191 HDD2GHZCHAN(2457, 10, 0),
192 HDD2GHZCHAN(2462, 11, 0),
193 HDD2GHZCHAN(2467, 12, 0),
194 HDD2GHZCHAN(2472, 13, 0),
195 HDD2GHZCHAN(2484, 14, 0),
196};
197
Abhishek Singhf512bf32016-05-04 16:47:46 +0530198static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 HDD5GHZCHAN(5180, 36, 0),
200 HDD5GHZCHAN(5200, 40, 0),
201 HDD5GHZCHAN(5220, 44, 0),
202 HDD5GHZCHAN(5240, 48, 0),
203 HDD5GHZCHAN(5260, 52, 0),
204 HDD5GHZCHAN(5280, 56, 0),
205 HDD5GHZCHAN(5300, 60, 0),
206 HDD5GHZCHAN(5320, 64, 0),
207 HDD5GHZCHAN(5500, 100, 0),
208 HDD5GHZCHAN(5520, 104, 0),
209 HDD5GHZCHAN(5540, 108, 0),
210 HDD5GHZCHAN(5560, 112, 0),
211 HDD5GHZCHAN(5580, 116, 0),
212 HDD5GHZCHAN(5600, 120, 0),
213 HDD5GHZCHAN(5620, 124, 0),
214 HDD5GHZCHAN(5640, 128, 0),
215 HDD5GHZCHAN(5660, 132, 0),
216 HDD5GHZCHAN(5680, 136, 0),
217 HDD5GHZCHAN(5700, 140, 0),
218 HDD5GHZCHAN(5720, 144, 0),
219 HDD5GHZCHAN(5745, 149, 0),
220 HDD5GHZCHAN(5765, 153, 0),
221 HDD5GHZCHAN(5785, 157, 0),
222 HDD5GHZCHAN(5805, 161, 0),
223 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 HDD5GHZCHAN(5852, 170, 0),
225 HDD5GHZCHAN(5855, 171, 0),
226 HDD5GHZCHAN(5860, 172, 0),
227 HDD5GHZCHAN(5865, 173, 0),
228 HDD5GHZCHAN(5870, 174, 0),
229 HDD5GHZCHAN(5875, 175, 0),
230 HDD5GHZCHAN(5880, 176, 0),
231 HDD5GHZCHAN(5885, 177, 0),
232 HDD5GHZCHAN(5890, 178, 0),
233 HDD5GHZCHAN(5895, 179, 0),
234 HDD5GHZCHAN(5900, 180, 0),
235 HDD5GHZCHAN(5905, 181, 0),
236 HDD5GHZCHAN(5910, 182, 0),
237 HDD5GHZCHAN(5915, 183, 0),
238 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239};
240
241static struct ieee80211_rate g_mode_rates[] = {
242 HDD_G_MODE_RATETAB(10, 0x1, 0),
243 HDD_G_MODE_RATETAB(20, 0x2, 0),
244 HDD_G_MODE_RATETAB(55, 0x4, 0),
245 HDD_G_MODE_RATETAB(110, 0x8, 0),
246 HDD_G_MODE_RATETAB(60, 0x10, 0),
247 HDD_G_MODE_RATETAB(90, 0x20, 0),
248 HDD_G_MODE_RATETAB(120, 0x40, 0),
249 HDD_G_MODE_RATETAB(180, 0x80, 0),
250 HDD_G_MODE_RATETAB(240, 0x100, 0),
251 HDD_G_MODE_RATETAB(360, 0x200, 0),
252 HDD_G_MODE_RATETAB(480, 0x400, 0),
253 HDD_G_MODE_RATETAB(540, 0x800, 0),
254};
255
256static struct ieee80211_rate a_mode_rates[] = {
257 HDD_G_MODE_RATETAB(60, 0x10, 0),
258 HDD_G_MODE_RATETAB(90, 0x20, 0),
259 HDD_G_MODE_RATETAB(120, 0x40, 0),
260 HDD_G_MODE_RATETAB(180, 0x80, 0),
261 HDD_G_MODE_RATETAB(240, 0x100, 0),
262 HDD_G_MODE_RATETAB(360, 0x200, 0),
263 HDD_G_MODE_RATETAB(480, 0x400, 0),
264 HDD_G_MODE_RATETAB(540, 0x800, 0),
265};
266
267static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530268 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700270 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
278 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
279 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
280 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
281 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
282 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
283 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
284};
285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530287 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700289 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290 .bitrates = a_mode_rates,
291 .n_bitrates = a_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
297 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
298 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
299 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
300 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
301 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
302 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
303 .vht_cap.vht_supported = 1,
304};
305
306/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800307 * TX/RX direction for each kind of interface
308 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309static const struct ieee80211_txrx_stypes
310 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
311 [NL80211_IFTYPE_STATION] = {
312 .tx = 0xffff,
313 .rx = BIT(SIR_MAC_MGMT_ACTION) |
314 BIT(SIR_MAC_MGMT_PROBE_REQ),
315 },
316 [NL80211_IFTYPE_AP] = {
317 .tx = 0xffff,
318 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
319 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_PROBE_REQ) |
321 BIT(SIR_MAC_MGMT_DISASSOC) |
322 BIT(SIR_MAC_MGMT_AUTH) |
323 BIT(SIR_MAC_MGMT_DEAUTH) |
324 BIT(SIR_MAC_MGMT_ACTION),
325 },
326 [NL80211_IFTYPE_ADHOC] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_P2P_CLIENT] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ACTION) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ),
340 },
341 [NL80211_IFTYPE_P2P_GO] = {
342 /* This is also same as for SoftAP */
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ) |
347 BIT(SIR_MAC_MGMT_DISASSOC) |
348 BIT(SIR_MAC_MGMT_AUTH) |
349 BIT(SIR_MAC_MGMT_DEAUTH) |
350 BIT(SIR_MAC_MGMT_ACTION),
351 },
352};
353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354/* Interface limits and combinations registered by the driver */
355
356/* STA ( + STA ) combination */
357static const struct ieee80211_iface_limit
358 wlan_hdd_sta_iface_limit[] = {
359 {
360 .max = 3, /* p2p0 is a STA as well */
361 .types = BIT(NL80211_IFTYPE_STATION),
362 },
363};
364
365/* ADHOC (IBSS) limit */
366static const struct ieee80211_iface_limit
367 wlan_hdd_adhoc_iface_limit[] = {
368 {
369 .max = 1,
370 .types = BIT(NL80211_IFTYPE_STATION),
371 },
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_ADHOC),
375 },
376};
377
378/* AP ( + AP ) combination */
379static const struct ieee80211_iface_limit
380 wlan_hdd_ap_iface_limit[] = {
381 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530382 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 .types = BIT(NL80211_IFTYPE_AP),
384 },
385};
386
387/* P2P limit */
388static const struct ieee80211_iface_limit
389 wlan_hdd_p2p_iface_limit[] = {
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
393 },
394 {
395 .max = 1,
396 .types = BIT(NL80211_IFTYPE_P2P_GO),
397 },
398};
399
400static const struct ieee80211_iface_limit
401 wlan_hdd_sta_ap_iface_limit[] = {
402 {
403 /* We need 1 extra STA interface for OBSS scan when SAP starts
404 * with HT40 in STA+SAP concurrency mode
405 */
406 .max = (1 + SAP_MAX_OBSS_STA_CNT),
407 .types = BIT(NL80211_IFTYPE_STATION),
408 },
409 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530410 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 .types = BIT(NL80211_IFTYPE_AP),
412 },
413};
414
415/* STA + P2P combination */
416static const struct ieee80211_iface_limit
417 wlan_hdd_sta_p2p_iface_limit[] = {
418 {
419 /* One reserved for dedicated P2PDEV usage */
420 .max = 2,
421 .types = BIT(NL80211_IFTYPE_STATION)
422 },
423 {
424 /* Support for two identical (GO + GO or CLI + CLI)
425 * or dissimilar (GO + CLI) P2P interfaces
426 */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
429 },
430};
431
432/* STA + AP + P2PGO combination */
433static const struct ieee80211_iface_limit
434wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
435 /* Support for AP+P2PGO interfaces */
436 {
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_STATION)
439 },
440 {
441 .max = 1,
442 .types = BIT(NL80211_IFTYPE_P2P_GO)
443 },
444 {
445 .max = 1,
446 .types = BIT(NL80211_IFTYPE_AP)
447 }
448};
449
450/* SAP + P2P combination */
451static const struct ieee80211_iface_limit
452wlan_hdd_sap_p2p_iface_limit[] = {
453 {
454 /* 1 dedicated for p2p0 which is a STA type */
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_STATION)
457 },
458 {
459 /* The p2p interface in SAP+P2P can be GO/CLI.
460 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
461 */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
464 },
465 {
466 /* SAP+GO to support only one SAP interface */
467 .max = 1,
468 .types = BIT(NL80211_IFTYPE_AP)
469 }
470};
471
472/* P2P + P2P combination */
473static const struct ieee80211_iface_limit
474wlan_hdd_p2p_p2p_iface_limit[] = {
475 {
476 /* 1 dedicated for p2p0 which is a STA type */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_STATION)
479 },
480 {
481 /* The p2p interface in P2P+P2P can be GO/CLI.
482 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
483 */
484 .max = 2,
485 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
486 },
487};
488
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700489static const struct ieee80211_iface_limit
490 wlan_hdd_mon_iface_limit[] = {
491 {
492 .max = 3, /* Monitor interface */
493 .types = BIT(NL80211_IFTYPE_MONITOR),
494 },
495};
496
497static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800498 wlan_hdd_iface_combination[] = {
499 /* STA */
500 {
501 .limits = wlan_hdd_sta_iface_limit,
502 .num_different_channels = 2,
503 .max_interfaces = 3,
504 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
505 },
506 /* ADHOC */
507 {
508 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700509 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 .max_interfaces = 2,
511 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
512 },
513 /* AP */
514 {
515 .limits = wlan_hdd_ap_iface_limit,
516 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530517 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
519 },
520 /* P2P */
521 {
522 .limits = wlan_hdd_p2p_iface_limit,
523 .num_different_channels = 2,
524 .max_interfaces = 2,
525 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
526 },
527 /* STA + AP */
528 {
529 .limits = wlan_hdd_sta_ap_iface_limit,
530 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
533 .beacon_int_infra_match = true,
534 },
535 /* STA + P2P */
536 {
537 .limits = wlan_hdd_sta_p2p_iface_limit,
538 .num_different_channels = 2,
539 /* one interface reserved for P2PDEV dedicated usage */
540 .max_interfaces = 4,
541 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
542 .beacon_int_infra_match = true,
543 },
544 /* STA + P2P GO + SAP */
545 {
546 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
547 /* we can allow 3 channels for three different persona
548 * but due to firmware limitation, allow max 2 concrnt channels.
549 */
550 .num_different_channels = 2,
551 /* one interface reserved for P2PDEV dedicated usage */
552 .max_interfaces = 4,
553 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
554 .beacon_int_infra_match = true,
555 },
556 /* SAP + P2P */
557 {
558 .limits = wlan_hdd_sap_p2p_iface_limit,
559 .num_different_channels = 2,
560 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
561 .max_interfaces = 3,
562 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
563 .beacon_int_infra_match = true,
564 },
565 /* P2P + P2P */
566 {
567 .limits = wlan_hdd_p2p_p2p_iface_limit,
568 .num_different_channels = 2,
569 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
570 .max_interfaces = 3,
571 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
572 .beacon_int_infra_match = true,
573 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530574 /* Monitor */
575 {
576 .limits = wlan_hdd_mon_iface_limit,
577 .max_interfaces = 3,
578 .num_different_channels = 2,
579 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
580 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530584struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586#ifdef WLAN_NL80211_TESTMODE
587enum wlan_hdd_tm_attr {
588 WLAN_HDD_TM_ATTR_INVALID = 0,
589 WLAN_HDD_TM_ATTR_CMD = 1,
590 WLAN_HDD_TM_ATTR_DATA = 2,
591 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
592 WLAN_HDD_TM_ATTR_TYPE = 4,
593 /* keep last */
594 WLAN_HDD_TM_ATTR_AFTER_LAST,
595 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
596};
597
598enum wlan_hdd_tm_cmd {
599 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
600 WLAN_HDD_TM_CMD_WLAN_HB = 1,
601};
602
603#define WLAN_HDD_TM_DATA_MAX_LEN 5000
604
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530605enum wlan_hdd_vendor_ie_access_policy {
606 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
607 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
608};
609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
611 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
612 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
613 .len = WLAN_HDD_TM_DATA_MAX_LEN},
614};
615#endif /* WLAN_NL80211_TESTMODE */
616
617#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
618static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
619 .flags = WIPHY_WOWLAN_MAGIC_PKT,
620 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
621 .pattern_min_len = 1,
622 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
623};
624#endif
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530627 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
628 * @flags: Pointer to the flags to Add channel switch flag.
629 *
630 * This Function adds Channel Switch support flag, if channel switch is
631 * supported by kernel.
632 * Return: void.
633 */
634#ifdef CHANNEL_SWITCH_SUPPORTED
635static inline void hdd_add_channel_switch_support(uint32_t *flags)
636{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800637 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530638 return;
639}
640#else
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
643 return;
644}
645#endif
646
Manikandan Mohan22b83722015-12-15 15:03:23 -0800647#ifdef FEATURE_WLAN_TDLS
648
649/* TDLS capabilities params */
650#define PARAM_MAX_TDLS_SESSION \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
652#define PARAM_TDLS_FEATURE_SUPPORT \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
654
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
657 * @wiphy: WIPHY structure pointer
658 * @wdev: Wireless device structure pointer
659 * @data: Pointer to the data received
660 * @data_len: Length of the data received
661 *
662 * This function provides TDLS capabilities
663 *
664 * Return: 0 on success and errno on failure
665 */
666static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
667 struct wireless_dev *wdev,
668 const void *data,
669 int data_len)
670{
671 int status;
672 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
673 struct sk_buff *skb;
674 uint32_t set = 0;
675
Jeff Johnson1f61b612016-02-12 16:28:33 -0800676 ENTER_DEV(wdev->netdev);
677
Anurag Chouhan6d760662016-02-20 16:05:43 +0530678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 hdd_err("Command not allowed in FTM mode");
680 return -EPERM;
681 }
682
683 status = wlan_hdd_validate_context(hdd_ctx);
684 if (status)
685 return status;
686
687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
688 NLMSG_HDRLEN);
689 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700690 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 goto fail;
692 }
693
694 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
697 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701 } else {
702 set = set | WIFI_TDLS_SUPPORT;
703 set = set | (hdd_ctx->config->fTDLSExternalControl ?
704 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
705 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
706 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
709 hdd_ctx->max_num_tdls_sta) ||
710 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
711 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700712 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 goto fail;
714 }
715 }
716 return cfg80211_vendor_cmd_reply(skb);
717fail:
718 if (skb)
719 kfree_skb(skb);
720 return -EINVAL;
721}
722
723/**
724 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
725 * @wiphy: WIPHY structure pointer
726 * @wdev: Wireless device structure pointer
727 * @data: Pointer to the data received
728 * @data_len: Length of the data received
729 *
730 * This function provides TDLS capabilities
731 *
732 * Return: 0 on success and errno on failure
733 */
734static int
735wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
736 struct wireless_dev *wdev,
737 const void *data,
738 int data_len)
739{
740 int ret;
741
742 cds_ssr_protect(__func__);
743 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
744 data, data_len);
745 cds_ssr_unprotect(__func__);
746
747 return ret;
748}
749#endif
750
751#ifdef QCA_HT_2040_COEX
752static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
753#endif
754
755#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
756/*
757 * FUNCTION: wlan_hdd_send_avoid_freq_event
758 * This is called when wlan driver needs to send vendor specific
759 * avoid frequency range event to userspace
760 */
761int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
762 tHddAvoidFreqList *pAvoidFreqList)
763{
764 struct sk_buff *vendor_event;
765
766 ENTER();
767
768 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700769 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 return -EINVAL;
771 }
772
773 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700774 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return -EINVAL;
776 }
777
778 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
779 NULL,
780 sizeof(tHddAvoidFreqList),
781 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
782 GFP_KERNEL);
783 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700784 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 return -EINVAL;
786 }
787
788 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
789 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
790
791 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
792
793 EXIT();
794 return 0;
795}
796#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
797
798/* vendor specific events */
799static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
800#ifdef FEATURE_WLAN_CH_AVOID
801 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
806 },
807#endif /* FEATURE_WLAN_CH_AVOID */
808
809#ifdef WLAN_FEATURE_NAN
810 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_NAN
815 },
816#endif
817
818#ifdef WLAN_FEATURE_STATS_EXT
819 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
824 },
825#endif /* WLAN_FEATURE_STATS_EXT */
826#ifdef FEATURE_WLAN_EXTSCAN
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
832 },
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
840 .
841 vendor_id
842 =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .
853 subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd
863 =
864 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
865 },
866 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
867 .
868 vendor_id
869 =
870 QCA_NL80211_VENDOR_ID,
871 .subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
875 .vendor_id =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
881 .
882 vendor_id
883 =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .
912 subcmd =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd
922 =
923 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
924 },
925 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
926 .
927 vendor_id
928 =
929 QCA_NL80211_VENDOR_ID,
930 .
931 subcmd
932 =
933 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
938 },
939 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
940 .vendor_id = QCA_NL80211_VENDOR_ID,
941 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
942 },
943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
982#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
983 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
990 .vendor_id = QCA_NL80211_VENDOR_ID,
991 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
992 },
993#ifdef WLAN_FEATURE_ROAM_OFFLOAD
994 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
999 },
1000#endif
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1030 },
1031#ifdef FEATURE_WLAN_EXTSCAN
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1047 },
1048 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1051 },
1052#endif /* FEATURE_WLAN_EXTSCAN */
1053 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1056 },
1057#ifdef WLAN_FEATURE_MEMDUMP
1058 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1061 },
1062#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001063#ifdef WLAN_FEATURE_TSF
1064 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1067 },
1068#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1072 },
1073 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1076 },
1077 /* OCB events */
1078 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1081 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001082#ifdef FEATURE_LFR_SUBNET_DETECTION
1083 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1084 .vendor_id = QCA_NL80211_VENDOR_ID,
1085 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1086 },
1087#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001088
1089#ifdef WLAN_FEATURE_NAN_DATAPATH
1090 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1093 },
1094#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001095
1096 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1099 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301100 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1101 .vendor_id = QCA_NL80211_VENDOR_ID,
1102 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1103 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001104#ifdef WLAN_UMAC_CONVERGENCE
1105 COMMON_VENDOR_EVENTS
1106#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107};
1108
1109/**
1110 * __is_driver_dfs_capable() - get driver DFS capability
1111 * @wiphy: pointer to wireless wiphy structure.
1112 * @wdev: pointer to wireless_dev structure.
1113 * @data: Pointer to the data to be passed via vendor interface
1114 * @data_len:Length of the data to be passed
1115 *
1116 * This function is called by userspace to indicate whether or not
1117 * the driver supports DFS offload.
1118 *
1119 * Return: 0 on success, negative errno on failure
1120 */
1121static int __is_driver_dfs_capable(struct wiphy *wiphy,
1122 struct wireless_dev *wdev,
1123 const void *data,
1124 int data_len)
1125{
1126 u32 dfs_capability = 0;
1127 struct sk_buff *temp_skbuff;
1128 int ret_val;
1129 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1130
Jeff Johnson1f61b612016-02-12 16:28:33 -08001131 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132
1133 ret_val = wlan_hdd_validate_context(hdd_ctx);
1134 if (ret_val)
1135 return ret_val;
1136
Anurag Chouhan6d760662016-02-20 16:05:43 +05301137 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138 hdd_err("Command not allowed in FTM mode");
1139 return -EPERM;
1140 }
1141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143
1144 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1145 NLMSG_HDRLEN);
1146
1147 if (temp_skbuff != NULL) {
1148 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1149 dfs_capability);
1150 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001151 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 kfree_skb(temp_skbuff);
1153
1154 return ret_val;
1155 }
1156
1157 return cfg80211_vendor_cmd_reply(temp_skbuff);
1158 }
1159
Jeff Johnson020db452016-06-29 14:37:26 -07001160 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 return -ENOMEM;
1162}
1163
1164/**
1165 * is_driver_dfs_capable() - get driver DFS capability
1166 * @wiphy: pointer to wireless wiphy structure.
1167 * @wdev: pointer to wireless_dev structure.
1168 * @data: Pointer to the data to be passed via vendor interface
1169 * @data_len:Length of the data to be passed
1170 *
1171 * This function is called by userspace to indicate whether or not
1172 * the driver supports DFS offload. This is an SSR-protected
1173 * wrapper function.
1174 *
1175 * Return: 0 on success, negative errno on failure
1176 */
1177static int is_driver_dfs_capable(struct wiphy *wiphy,
1178 struct wireless_dev *wdev,
1179 const void *data,
1180 int data_len)
1181{
1182 int ret;
1183
1184 cds_ssr_protect(__func__);
1185 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1186 cds_ssr_unprotect(__func__);
1187
1188 return ret;
1189}
1190
1191/**
1192 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1193 *
1194 * @adapter: SAP adapter pointer
1195 *
1196 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1197 * radio. So in case of DFS MCC scenario override current SAP given config
1198 * to follow concurrent SAP DFS config
1199 *
1200 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1201 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1203{
1204 hdd_adapter_t *con_sap_adapter;
1205 tsap_Config_t *sap_config, *con_sap_config;
1206 int con_ch;
1207
1208 /*
1209 * Check if AP+AP case, once primary AP chooses a DFS
1210 * channel secondary AP should always follow primary APs channel
1211 */
1212 if (!cds_concurrent_beaconing_sessions_running())
1213 return 0;
1214
1215 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1216 if (!con_sap_adapter)
1217 return 0;
1218
1219 sap_config = &adapter->sessionCtx.ap.sapConfig;
1220 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1221 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1222
1223 if (!CDS_IS_DFS_CH(con_ch))
1224 return 0;
1225
Jeff Johnson020db452016-06-29 14:37:26 -07001226 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 sap_config->channel = con_ch;
1230
1231 if (con_sap_config->acs_cfg.acs_mode == true) {
1232 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1233 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001234 hdd_err("Primary AP channel config error");
1235 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 con_ch, con_sap_config->acs_cfg.pri_ch,
1237 con_sap_config->acs_cfg.ht_sec_ch);
1238 return -EINVAL;
1239 }
1240 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1241 * MCC restriction. So free ch list allocated in do_acs
1242 * func for Sec AP and realloc for Pri AP ch list size
1243 */
1244 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301245 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301247 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 &con_sap_config->acs_cfg,
1249 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301250 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 sizeof(uint8_t) *
1252 con_sap_config->acs_cfg.ch_list_count);
1253 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001254 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 return -ENOMEM;
1256 }
1257
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301258 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 con_sap_config->acs_cfg.ch_list,
1260 con_sap_config->acs_cfg.ch_list_count);
1261
1262 } else {
1263 sap_config->acs_cfg.pri_ch = con_ch;
1264 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1265 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1266 }
1267
1268 return con_ch;
1269}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001270
1271/**
1272 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1273 * @sap_cfg: pointer to SAP config struct
1274 *
1275 * This function sets the default ACS start and end channel for the given band
1276 * and also parses the given ACS channel list.
1277 *
1278 * Return: None
1279 */
1280
1281static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1282 bool vht_enabled)
1283{
1284 int i;
1285 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001287 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1288 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 }
1302
1303 if (ht_enabled)
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1305
1306 if (vht_enabled)
1307 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1308
1309
1310 /* Parse ACS Chan list from hostapd */
1311 if (!sap_cfg->acs_cfg.ch_list)
1312 return;
1313
1314 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1315 sap_cfg->acs_cfg.end_ch =
1316 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1317 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301318 /* avoid channel as start channel */
1319 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1320 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001321 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1322 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1323 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1324 }
1325}
1326
1327
1328static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1329
1330/**
1331 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1332 * @adapter: pointer to SAP adapter struct
1333 *
1334 * This function starts the ACS procedure if there are no
1335 * constraints like MBSSID DFS restrictions.
1336 *
1337 * Return: Status of ACS Start procedure
1338 */
1339
1340static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1341{
1342
1343 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1344 tsap_Config_t *sap_config;
1345 tpWLAN_SAPEventCB acs_event_callback;
1346 int status;
1347
1348 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301349 if (hdd_ctx->acs_policy.acs_channel)
1350 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1351 else
1352 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353
1354 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1355 if (status < 0) {
1356 return status;
1357 } else {
1358 if (status > 0) {
1359 /*notify hostapd about channel override */
1360 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1361 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1362 return 0;
1363 }
1364 }
1365 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1366 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001367 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 return -EINVAL;
1369 }
1370
1371 acs_event_callback = hdd_hostapd_sap_event_cb;
1372
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301373 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301374 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001375 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 acs_event_callback, sap_config, adapter->dev);
1379
1380
1381 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001382 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 return -EINVAL;
1384 }
1385 sap_config->acs_cfg.acs_mode = true;
1386 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1387
1388 return 0;
1389}
1390
1391/**
1392 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1393 * @wiphy: Linux wiphy struct pointer
1394 * @wdev: Linux wireless device struct pointer
1395 * @data: ACS information from hostapd
1396 * @data_len: ACS information length
1397 *
1398 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1399 * and starts ACS procedure.
1400 *
1401 * Return: ACS procedure start status
1402 */
1403
1404static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1405 struct wireless_dev *wdev,
1406 const void *data, int data_len)
1407{
1408 struct net_device *ndev = wdev->netdev;
1409 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1410 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1411 tsap_Config_t *sap_config;
1412 struct sk_buff *temp_skbuff;
1413 int status = -EINVAL, i = 0;
1414 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1415 bool ht_enabled, ht40_enabled, vht_enabled;
1416 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301417 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418
1419 /* ***Note*** Donot set SME config related to ACS operation here because
1420 * ACS operation is not synchronouse and ACS for Second AP may come when
1421 * ACS operation for first AP is going on. So only do_acs is split to
1422 * seperate start_acs routine. Also SME-PMAC struct that is used to
1423 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1424 * config shall be set only from start_acs.
1425 */
1426
1427 /* nla_policy Policy template. Policy not applied as some attributes are
1428 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1429 *
1430 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1431 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1432 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1433 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1434 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1435 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1436 */
1437
Jeff Johnson1f61b612016-02-12 16:28:33 -08001438 ENTER_DEV(ndev);
1439
Anurag Chouhan6d760662016-02-20 16:05:43 +05301440 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 hdd_err("Command not allowed in FTM mode");
1442 return -EPERM;
1443 }
1444
1445 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001446 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 return -EPERM;
1448 }
1449
1450 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301451 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001452 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301453
Naveen Rawat64e477e2016-05-20 10:34:56 -07001454 if (cds_is_sub_20_mhz_enabled()) {
1455 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1456 status = -EINVAL;
1457 goto out;
1458 }
1459
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301461 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462
1463 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1464 NULL);
1465 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001466 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467 goto out;
1468 }
1469
1470 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001471 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472 goto out;
1473 }
1474 sap_config->acs_cfg.hw_mode = nla_get_u8(
1475 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1476
1477 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1478 ht_enabled =
1479 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1480 else
1481 ht_enabled = 0;
1482
1483 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1484 ht40_enabled =
1485 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1486 else
1487 ht40_enabled = 0;
1488
1489 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1490 vht_enabled =
1491 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1492 else
1493 vht_enabled = 0;
1494
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301495 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1496 vht_enabled = 0;
1497 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1498 }
1499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1501 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1502 } else {
1503 if (ht_enabled && ht40_enabled)
1504 ch_width = 40;
1505 else
1506 ch_width = 20;
1507 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301508
1509 /* this may be possible, when sap_force_11n_for_11ac is set */
1510 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1511 if (ht_enabled && ht40_enabled)
1512 ch_width = 40;
1513 else
1514 ch_width = 20;
1515 }
1516
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001517 if (ch_width == 80)
1518 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1519 else if (ch_width == 40)
1520 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1521 else
1522 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1523
1524 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1525 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1526 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1527 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1528 * since it contains the frequency values of the channels in
1529 * the channel list.
1530 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1531 * is present
1532 */
1533 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1534 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1535 sap_config->acs_cfg.ch_list_count = nla_len(
1536 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1537 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301538 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 sizeof(uint8_t) *
1540 sap_config->acs_cfg.ch_list_count);
1541 if (sap_config->acs_cfg.ch_list == NULL)
1542 goto out;
1543
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301544 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 sap_config->acs_cfg.ch_list_count);
1546 }
1547 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1548 uint32_t *freq =
1549 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1550 sap_config->acs_cfg.ch_list_count = nla_len(
1551 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1552 sizeof(uint32_t);
1553 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301554 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555 sap_config->acs_cfg.ch_list_count);
1556 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001557 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 status = -ENOMEM;
1559 goto out;
1560 }
1561
1562 /* convert frequency to channel */
1563 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1564 sap_config->acs_cfg.ch_list[i] =
1565 ieee80211_frequency_to_channel(freq[i]);
1566 }
1567 }
1568
1569 hdd_debug("get pcl for DO_ACS vendor command");
1570
1571 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001572 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301573 sap_config->acs_cfg.pcl_channels,
1574 &sap_config->acs_cfg.pcl_ch_count,
1575 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301576 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001577 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001578
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301580 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1581 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001582 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583 vht_enabled = 1;
1584 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1585 sap_config->acs_cfg.ch_width =
1586 hdd_ctx->config->vhtChannelWidth;
1587 /* No VHT80 in 2.4G so perform ACS accordingly */
1588 if (sap_config->acs_cfg.end_ch <= 14 &&
1589 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1590 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1591 }
1592
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301593 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1594
Jeff Johnson020db452016-06-29 14:37:26 -07001595 hdd_notice("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1597 ch_width, ht_enabled, vht_enabled,
1598 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1599
1600 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001601 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001602 sap_config->acs_cfg.ch_list_count);
1603 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001604 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001605 }
1606 sap_config->acs_cfg.acs_mode = true;
1607 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001608 /* ***Note*** Completion variable usage is not allowed
1609 * here since ACS scan operation may take max 2.2 sec
1610 * for 5G band:
1611 * 9 Active channel X 40 ms active scan time +
1612 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1614 * for this long. So we split up the scanning part.
1615 */
1616 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001617 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001618 status = 0;
1619 } else {
1620 status = wlan_hdd_cfg80211_start_acs(adapter);
1621 }
1622
1623out:
1624 if (0 == status) {
1625 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1626 NLMSG_HDRLEN);
1627 if (temp_skbuff != NULL)
1628 return cfg80211_vendor_cmd_reply(temp_skbuff);
1629 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001630 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001631 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1632
1633 return status;
1634}
1635
Jeff Johnsonf3826e12017-01-12 09:49:40 -08001636/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001637 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1638 * @wiphy: Linux wiphy struct pointer
1639 * @wdev: Linux wireless device struct pointer
1640 * @data: ACS information from hostapd
1641 * @data_len: ACS information len
1642 *
1643 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1644 * and starts ACS procedure.
1645 *
1646 * Return: ACS procedure start status
1647 */
1648
1649static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1650 struct wireless_dev *wdev,
1651 const void *data, int data_len)
1652{
1653 int ret;
1654
1655 cds_ssr_protect(__func__);
1656 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1657 cds_ssr_unprotect(__func__);
1658
1659 return ret;
1660}
1661
1662/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001663 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1664 * @adapter: Pointer to adapter struct
1665 *
1666 * This function handle cleanup of what was done in DO_ACS, including free
1667 * memory.
1668 *
1669 * Return: void
1670 */
1671
1672void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1673{
1674 if (adapter == NULL)
1675 return;
1676 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1677 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1678 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1679 }
1680}
1681
1682/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001683 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1684 * @work: Linux workqueue struct pointer for ACS work
1685 *
1686 * This function starts the ACS procedure which was marked pending when an ACS
1687 * procedure was in progress for a concurrent SAP interface.
1688 *
1689 * Return: None
1690 */
1691
1692static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1693{
1694 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1695 acs_pending_work.work);
1696 wlan_hdd_cfg80211_start_acs(adapter);
1697}
1698
1699/**
1700 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1701 * @adapter: Pointer to SAP adapter struct
1702 * @pri_channel: SAP ACS procedure selected Primary channel
1703 * @sec_channel: SAP ACS procedure selected secondary channel
1704 *
1705 * This is a callback function from SAP module on ACS procedure is completed.
1706 * This function send the ACS selected channel information to hostapd
1707 *
1708 * Return: None
1709 */
1710
1711void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1712{
1713 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1714 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1715 struct sk_buff *vendor_event;
1716 int ret_val;
1717 hdd_adapter_t *con_sap_adapter;
1718 uint16_t ch_width;
1719
1720 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001721 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1723 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1724 GFP_KERNEL);
1725
1726 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001727 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 return;
1729 }
1730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001731 ret_val = nla_put_u8(vendor_event,
1732 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1733 sap_cfg->acs_cfg.pri_ch);
1734 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001735 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 kfree_skb(vendor_event);
1737 return;
1738 }
1739
1740 ret_val = nla_put_u8(vendor_event,
1741 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1742 sap_cfg->acs_cfg.ht_sec_ch);
1743 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001744 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001745 kfree_skb(vendor_event);
1746 return;
1747 }
1748
1749 ret_val = nla_put_u8(vendor_event,
1750 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1751 sap_cfg->acs_cfg.vht_seg0_center_ch);
1752 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001753 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754 kfree_skb(vendor_event);
1755 return;
1756 }
1757
1758 ret_val = nla_put_u8(vendor_event,
1759 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1760 sap_cfg->acs_cfg.vht_seg1_center_ch);
1761 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001762 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763 kfree_skb(vendor_event);
1764 return;
1765 }
1766
1767 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1768 ch_width = 80;
1769 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1770 ch_width = 40;
1771 else
1772 ch_width = 20;
1773
1774 ret_val = nla_put_u16(vendor_event,
1775 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1776 ch_width);
1777 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001778 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 kfree_skb(vendor_event);
1780 return;
1781 }
1782 if (sap_cfg->acs_cfg.pri_ch > 14)
1783 ret_val = nla_put_u8(vendor_event,
1784 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1785 QCA_ACS_MODE_IEEE80211A);
1786 else
1787 ret_val = nla_put_u8(vendor_event,
1788 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1789 QCA_ACS_MODE_IEEE80211G);
1790
1791 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001792 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001793 kfree_skb(vendor_event);
1794 return;
1795 }
1796
Jeff Johnson46b40792016-06-29 14:03:14 -07001797 hdd_notice("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1799 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1800 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1801
1802 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1803 /* ***Note*** As already mentioned Completion variable usage is not
1804 * allowed here since ACS scan operation may take max 2.2 sec.
1805 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1806 * operation.
1807 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1808 * when Primary AP ACS is complete and secondary AP ACS is started here
1809 * immediately, Primary AP start_bss may come inbetween ACS operation
1810 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1811 * delay. This path and below constraint will be removed on sessionizing
1812 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1813 * As per design constraint user space control application must take
1814 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1815 * this code path. Sec AP hostapd should be started after Primary AP
1816 * start beaconing which can be confirmed by getchannel iwpriv command
1817 */
1818
1819 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1820 if (con_sap_adapter &&
1821 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1823 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 /* Lets give 500ms for OBSS + START_BSS to complete */
1825 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1826 msecs_to_jiffies(500));
1827 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1828 }
1829
1830 return;
1831}
1832
1833static int
1834__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1835 struct wireless_dev *wdev,
1836 const void *data,
1837 int data_len)
1838{
1839 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1840 struct sk_buff *skb = NULL;
1841 uint32_t fset = 0;
1842 int ret;
1843
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001844 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301845
Anurag Chouhan6d760662016-02-20 16:05:43 +05301846 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 hdd_err("Command not allowed in FTM mode");
1848 return -EPERM;
1849 }
1850
1851 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301852 if (ret)
1853 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001854
1855 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001856 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857 fset |= WIFI_FEATURE_INFRA;
1858 }
1859 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001860 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 fset |= WIFI_FEATURE_INFRA_5G;
1862 }
1863#ifdef WLAN_FEATURE_P2P
1864 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1865 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001866 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 fset |= WIFI_FEATURE_P2P;
1868 }
1869#endif
1870 fset |= WIFI_FEATURE_SOFT_AP;
1871
1872 /* HOTSPOT is a supplicant feature, enable it by default */
1873 fset |= WIFI_FEATURE_HOTSPOT;
1874
1875#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301876 if (pHddCtx->config->extscan_enabled &&
1877 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001878 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1880 }
1881#endif
1882 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001883 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 fset |= WIFI_FEATURE_NAN;
1885 }
1886 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001887 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 fset |= WIFI_FEATURE_D2D_RTT;
1889 fset |= WIFI_FEATURE_D2AP_RTT;
1890 }
1891#ifdef FEATURE_WLAN_SCAN_PNO
1892 if (pHddCtx->config->configPNOScanSupport &&
1893 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001894 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 fset |= WIFI_FEATURE_PNO;
1896 }
1897#endif
1898 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1899#ifdef FEATURE_WLAN_TDLS
1900 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1901 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 fset |= WIFI_FEATURE_TDLS;
1904 }
1905 if (sme_is_feature_supported_by_fw(TDLS) &&
1906 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1907 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001908 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1910 }
1911#endif
1912#ifdef WLAN_AP_STA_CONCURRENCY
1913 fset |= WIFI_FEATURE_AP_STA;
1914#endif
1915 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001916 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001917
1918 if (hdd_link_layer_stats_supported())
1919 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1920
1921 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1922 NLMSG_HDRLEN);
1923 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001924 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001925 return -EINVAL;
1926 }
Jeff Johnson020db452016-06-29 14:37:26 -07001927 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001929 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 goto nla_put_failure;
1931 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301932 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301933 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934nla_put_failure:
1935 kfree_skb(skb);
1936 return -EINVAL;
1937}
1938
1939/**
1940 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1941 * @wiphy: pointer to wireless wiphy structure.
1942 * @wdev: pointer to wireless_dev structure.
1943 * @data: Pointer to the data to be passed via vendor interface
1944 * @data_len:Length of the data to be passed
1945 *
1946 * Return: Return the Success or Failure code.
1947 */
1948static int
1949wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1950 struct wireless_dev *wdev,
1951 const void *data, int data_len)
1952{
1953 int ret = 0;
1954
1955 cds_ssr_protect(__func__);
1956 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1957 data, data_len);
1958 cds_ssr_unprotect(__func__);
1959
1960 return ret;
1961}
1962
1963/**
1964 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1965 * @wiphy: pointer to wireless wiphy structure.
1966 * @wdev: pointer to wireless_dev structure.
1967 * @data: Pointer to the data to be passed via vendor interface
1968 * @data_len:Length of the data to be passed
1969 *
1970 * Set the MAC address that is to be used for scanning.
1971 *
1972 * Return: Return the Success or Failure code.
1973 */
1974static int
1975__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1976 struct wireless_dev *wdev,
1977 const void *data,
1978 int data_len)
1979{
1980 tpSirScanMacOui pReqMsg = NULL;
1981 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1982 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301983 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 int ret;
1985
Jeff Johnson1f61b612016-02-12 16:28:33 -08001986 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987
Anurag Chouhan6d760662016-02-20 16:05:43 +05301988 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 hdd_err("Command not allowed in FTM mode");
1990 return -EPERM;
1991 }
1992
1993 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301994 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996
1997 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001998 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001999 return -ENOTSUPP;
2000 }
2001
2002 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2003 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002004 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 return -EINVAL;
2006 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302007 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002009 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 return -ENOMEM;
2011 }
2012 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002013 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 goto fail;
2015 }
2016 nla_memcpy(&pReqMsg->oui[0],
2017 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2018 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002019 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 pReqMsg->oui[1], pReqMsg->oui[2]);
2021 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302022 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002023 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 goto fail;
2025 }
2026 return 0;
2027fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302028 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002029 return -EINVAL;
2030}
2031
2032/**
2033 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2034 * @wiphy: pointer to wireless wiphy structure.
2035 * @wdev: pointer to wireless_dev structure.
2036 * @data: Pointer to the data to be passed via vendor interface
2037 * @data_len:Length of the data to be passed
2038 *
2039 * Set the MAC address that is to be used for scanning. This is an
2040 * SSR-protecting wrapper function.
2041 *
2042 * Return: Return the Success or Failure code.
2043 */
2044static int
2045wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2046 struct wireless_dev *wdev,
2047 const void *data,
2048 int data_len)
2049{
2050 int ret;
2051
2052 cds_ssr_protect(__func__);
2053 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2054 data, data_len);
2055 cds_ssr_unprotect(__func__);
2056
2057 return ret;
2058}
2059
2060/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302061 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2062 * @wiphy: pointer phy adapter
2063 * @wdev: pointer to wireless device structure
2064 * @data: pointer to data buffer
2065 * @data_len: length of data
2066 *
2067 * This routine will give concurrency matrix
2068 *
2069 * Return: int status code
2070 */
2071static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2072 struct wireless_dev *wdev,
2073 const void *data,
2074 int data_len)
2075{
2076 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2077 uint8_t i, feature_sets, max_feature_sets;
2078 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2079 struct sk_buff *reply_skb;
2080 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2081 int ret;
2082
2083 ENTER_DEV(wdev->netdev);
2084
2085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2086 hdd_err("Command not allowed in FTM mode");
2087 return -EPERM;
2088 }
2089
2090 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302091 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302092 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302093
2094 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2095 data, data_len, NULL)) {
2096 hdd_err("Invalid ATTR");
2097 return -EINVAL;
2098 }
2099
2100 /* Parse and fetch max feature set */
2101 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2102 hdd_err("Attr max feature set size failed");
2103 return -EINVAL;
2104 }
2105 max_feature_sets = nla_get_u32(tb[
2106 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2107 hdd_info("Max feature set size: %d", max_feature_sets);
2108
2109 /* Fill feature combination matrix */
2110 feature_sets = 0;
2111 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002112 WIFI_FEATURE_P2P;
2113 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2114 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302115 /* Add more feature combinations here */
2116
2117 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002118 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302119 hdd_info("Feature set matrix");
2120 for (i = 0; i < feature_sets; i++)
2121 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2122
2123 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2124 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2125 if (!reply_skb) {
2126 hdd_err("Feature set matrix: buffer alloc fail");
2127 return -ENOMEM;
2128 }
2129
2130 if (nla_put_u32(reply_skb,
2131 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2132 feature_sets) ||
2133 nla_put(reply_skb,
2134 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2135 sizeof(u32) * feature_sets,
2136 feature_set_matrix)) {
2137 hdd_err("nla put fail");
2138 kfree_skb(reply_skb);
2139 return -EINVAL;
2140 }
2141 return cfg80211_vendor_cmd_reply(reply_skb);
2142}
2143
2144/**
2145 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2146 * @wiphy: pointer to wireless wiphy structure.
2147 * @wdev: pointer to wireless_dev structure.
2148 * @data: Pointer to the data to be passed via vendor interface
2149 * @data_len:Length of the data to be passed
2150 *
2151 * Retrieves the concurrency feature set matrix
2152 *
2153 * Return: 0 on success, negative errno on failure
2154 */
2155static int
2156wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2157 struct wireless_dev *wdev,
2158 const void *data,
2159 int data_len)
2160{
2161 int ret;
2162
2163 cds_ssr_protect(__func__);
2164 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2165 data, data_len);
2166 cds_ssr_unprotect(__func__);
2167
2168 return ret;
2169}
2170
2171/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2173 * @feature_flags: pointer to the byte array of features.
2174 * @feature: Feature to be turned ON in the byte array.
2175 *
2176 * Return: None
2177 *
2178 * This is called to turn ON or SET the feature flag for the requested feature.
2179 **/
2180#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002181static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2182 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183{
2184 uint32_t index;
2185 uint8_t bit_mask;
2186
2187 index = feature / NUM_BITS_IN_BYTE;
2188 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2189 feature_flags[index] |= bit_mask;
2190}
2191
2192/**
2193 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2194 * @wiphy: pointer to wireless wiphy structure.
2195 * @wdev: pointer to wireless_dev structure.
2196 * @data: Pointer to the data to be passed via vendor interface
2197 * @data_len:Length of the data to be passed
2198 *
2199 * This is called when wlan driver needs to send supported feature set to
2200 * supplicant upon a request/query from the supplicant.
2201 *
2202 * Return: Return the Success or Failure code.
2203 **/
2204#define MAX_CONCURRENT_CHAN_ON_24G 2
2205#define MAX_CONCURRENT_CHAN_ON_5G 2
2206static int
2207__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2208 struct wireless_dev *wdev,
2209 const void *data, int data_len)
2210{
2211 struct sk_buff *skb = NULL;
2212 uint32_t dbs_capability = 0;
2213 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302214 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215 int ret_val;
2216
2217 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2218 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2219
Jeff Johnson1f61b612016-02-12 16:28:33 -08002220 ENTER_DEV(wdev->netdev);
2221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2223 if (ret_val)
2224 return ret_val;
2225
Anurag Chouhan6d760662016-02-20 16:05:43 +05302226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 hdd_err("Command not allowed in FTM mode");
2228 return -EPERM;
2229 }
2230
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002231 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002232 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 wlan_hdd_cfg80211_set_feature(feature_flags,
2234 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2235 }
2236
2237 wlan_hdd_cfg80211_set_feature(feature_flags,
2238 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2239 if (wma_is_scan_simultaneous_capable())
2240 wlan_hdd_cfg80211_set_feature(feature_flags,
2241 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002242
2243 if (wma_is_p2p_lo_capable())
2244 wlan_hdd_cfg80211_set_feature(feature_flags,
2245 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2246
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2248 NLMSG_HDRLEN);
2249
2250 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002251 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002252 return -ENOMEM;
2253 }
2254
2255 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2256 sizeof(feature_flags), feature_flags))
2257 goto nla_put_failure;
2258
2259 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302260 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002261 if (one_by_one_dbs)
2262 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2263
2264 if (two_by_two_dbs)
2265 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2266
2267 if (!one_by_one_dbs && !two_by_two_dbs)
2268 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2269 } else {
2270 hdd_err("wma_get_dbs_hw_mode failed");
2271 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2272 }
2273
2274 hdd_info("dbs_capability is %d", dbs_capability);
2275
2276 if (nla_put_u32(skb,
2277 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2278 MAX_CONCURRENT_CHAN_ON_24G))
2279 goto nla_put_failure;
2280
2281 if (nla_put_u32(skb,
2282 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2283 MAX_CONCURRENT_CHAN_ON_5G))
2284 goto nla_put_failure;
2285
2286 return cfg80211_vendor_cmd_reply(skb);
2287
2288nla_put_failure:
2289 kfree_skb(skb);
2290 return -EINVAL;
2291}
2292
2293/**
2294 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2295 * @wiphy: pointer to wireless wiphy structure.
2296 * @wdev: pointer to wireless_dev structure.
2297 * @data: Pointer to the data to be passed via vendor interface
2298 * @data_len:Length of the data to be passed
2299 *
2300 * This is called when wlan driver needs to send supported feature set to
2301 * supplicant upon a request/query from the supplicant.
2302 *
2303 * Return: Return the Success or Failure code.
2304 */
2305static int
2306wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2307 struct wireless_dev *wdev,
2308 const void *data, int data_len)
2309{
2310 int ret;
2311
2312 cds_ssr_protect(__func__);
2313 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2314 data, data_len);
2315 cds_ssr_unprotect(__func__);
2316
2317 return ret;
2318}
2319
2320
2321/**
2322 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2323 * @wiphy: The wiphy structure
2324 * @wdev: The wireless device
2325 * @data: Data passed by framework
2326 * @data_len: Parameters to be configured passed as data
2327 *
2328 * The roaming related parameters are configured by the framework
2329 * using this interface.
2330 *
2331 * Return: Return either success or failure code.
2332 */
2333static int
2334__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2335 struct wireless_dev *wdev, const void *data, int data_len)
2336{
2337 struct net_device *dev = wdev->netdev;
2338 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2339 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2340 uint8_t session_id;
2341 struct roam_ext_params roam_params;
2342 uint32_t cmd_type, req_id;
2343 struct nlattr *curr_attr;
2344 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2345 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2346 int rem, i;
2347 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002348 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 int ret;
2350
Jeff Johnson1f61b612016-02-12 16:28:33 -08002351 ENTER_DEV(dev);
2352
Anurag Chouhan6d760662016-02-20 16:05:43 +05302353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 hdd_err("Command not allowed in FTM mode");
2355 return -EPERM;
2356 }
2357
2358 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302359 if (ret)
2360 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361
2362 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2363 data, data_len,
2364 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002365 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366 return -EINVAL;
2367 }
2368 /* Parse and fetch Command Type*/
2369 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002370 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 goto fail;
2372 }
2373 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302374 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2376 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 goto fail;
2379 }
2380 req_id = nla_get_u32(
2381 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002382 hdd_debug("Req Id (%d)", req_id);
2383 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 switch (cmd_type) {
2385 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2386 i = 0;
2387 nla_for_each_nested(curr_attr,
2388 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2389 rem) {
2390 if (nla_parse(tb2,
2391 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2392 nla_data(curr_attr), nla_len(curr_attr),
2393 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002394 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 goto fail;
2396 }
2397 /* Parse and Fetch allowed SSID list*/
2398 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002399 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 goto fail;
2401 }
2402 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2403 /*
2404 * Upper Layers include a null termination character.
2405 * Check for the actual permissible length of SSID and
2406 * also ensure not to copy the NULL termination
2407 * character to the driver buffer.
2408 */
2409 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2410 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2411 nla_memcpy(
2412 roam_params.ssid_allowed_list[i].ssId,
2413 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2414 buf_len - 1);
2415 roam_params.ssid_allowed_list[i].length =
2416 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002417 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 roam_params.ssid_allowed_list[i].length,
2419 roam_params.ssid_allowed_list[i].ssId,
2420 roam_params.ssid_allowed_list[i].length);
2421 i++;
2422 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002423 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 }
2425 }
2426 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002427 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 roam_params.num_ssid_allowed_list);
2429 sme_update_roam_params(pHddCtx->hHal, session_id,
2430 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2431 break;
2432 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2433 /* Parse and fetch 5G Boost Threshold */
2434 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002435 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 goto fail;
2437 }
2438 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2439 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002440 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 roam_params.raise_rssi_thresh_5g);
2442 /* Parse and fetch 5G Penalty Threshold */
2443 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002444 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 goto fail;
2446 }
2447 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2448 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002449 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 roam_params.drop_rssi_thresh_5g);
2451 /* Parse and fetch 5G Boost Factor */
2452 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 goto fail;
2455 }
2456 roam_params.raise_factor_5g = nla_get_u32(
2457 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002458 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 roam_params.raise_factor_5g);
2460 /* Parse and fetch 5G Penalty factor */
2461 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002462 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 goto fail;
2464 }
2465 roam_params.drop_factor_5g = nla_get_u32(
2466 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002467 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 roam_params.drop_factor_5g);
2469 /* Parse and fetch 5G Max Boost */
2470 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002471 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 goto fail;
2473 }
2474 roam_params.max_raise_rssi_5g = nla_get_u32(
2475 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002476 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 roam_params.max_raise_rssi_5g);
2478 /* Parse and fetch Rssi Diff */
2479 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002480 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 goto fail;
2482 }
2483 roam_params.rssi_diff = nla_get_s32(
2484 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002485 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 roam_params.rssi_diff);
2487 /* Parse and fetch Alert Rssi Threshold */
2488 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002489 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490 goto fail;
2491 }
2492 roam_params.alert_rssi_threshold = nla_get_u32(
2493 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002494 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 roam_params.alert_rssi_threshold);
2496 sme_update_roam_params(pHddCtx->hHal, session_id,
2497 roam_params,
2498 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2499 break;
2500 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2501 /* Parse and fetch Activate Good Rssi Roam */
2502 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 goto fail;
2505 }
2506 roam_params.good_rssi_roam = nla_get_s32(
2507 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002508 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 roam_params.good_rssi_roam);
2510 sme_update_roam_params(pHddCtx->hHal, session_id,
2511 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2512 break;
2513 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2514 /* Parse and fetch number of preferred BSSID */
2515 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002516 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 goto fail;
2518 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002519 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002521 if (count > MAX_BSSID_FAVORED) {
2522 hdd_err("Preferred BSSID count %u exceeds max %u",
2523 count, MAX_BSSID_FAVORED);
2524 goto fail;
2525 }
2526 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 i = 0;
2528 nla_for_each_nested(curr_attr,
2529 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2530 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002531
2532 if (i == count) {
2533 hdd_warn("Ignoring excess Preferred BSSID");
2534 break;
2535 }
2536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 if (nla_parse(tb2,
2538 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2539 nla_data(curr_attr), nla_len(curr_attr),
2540 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002541 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 goto fail;
2543 }
2544 /* Parse and fetch MAC address */
2545 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002546 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 goto fail;
2548 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002549 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302551 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002552 hdd_debug(MAC_ADDRESS_STR,
2553 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 /* Parse and fetch preference factor*/
2555 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002556 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 goto fail;
2558 }
2559 roam_params.bssid_favored_factor[i] = nla_get_u32(
2560 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002561 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 roam_params.bssid_favored_factor[i]);
2563 i++;
2564 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002565 if (i < count)
2566 hdd_warn("Num Preferred BSSID %u less than expected %u",
2567 i, count);
2568 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 sme_update_roam_params(pHddCtx->hHal, session_id,
2570 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2571 break;
2572 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2573 /* Parse and fetch number of blacklist BSSID */
2574 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002575 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002576 goto fail;
2577 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002578 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002580 if (count > MAX_BSSID_AVOID_LIST) {
2581 hdd_err("Blacklist BSSID count %u exceeds max %u",
2582 count, MAX_BSSID_AVOID_LIST);
2583 goto fail;
2584 }
2585 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 i = 0;
2587 nla_for_each_nested(curr_attr,
2588 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2589 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002590
2591 if (i == count) {
2592 hdd_warn("Ignoring excess Blacklist BSSID");
2593 break;
2594 }
2595
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596 if (nla_parse(tb2,
2597 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2598 nla_data(curr_attr), nla_len(curr_attr),
2599 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002600 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601 goto fail;
2602 }
2603 /* Parse and fetch MAC address */
2604 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002605 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 goto fail;
2607 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002608 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302610 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002611 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002613 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614 i++;
2615 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002616 if (i < count)
2617 hdd_warn("Num Blacklist BSSID %u less than expected %u",
2618 i, count);
2619 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 sme_update_roam_params(pHddCtx->hHal, session_id,
2621 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2622 break;
2623 }
2624 return 0;
2625fail:
2626 return -EINVAL;
2627}
2628
2629/**
2630 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2631 * @wiphy: pointer to wireless wiphy structure.
2632 * @wdev: pointer to wireless_dev structure.
2633 * @data: Pointer to the data to be passed via vendor interface
2634 * @data_len:Length of the data to be passed
2635 *
2636 * Return: Return the Success or Failure code.
2637 */
2638static int
2639wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2640 struct wireless_dev *wdev,
2641 const void *data,
2642 int data_len)
2643{
2644 int ret;
2645
2646 cds_ssr_protect(__func__);
2647 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2648 data, data_len);
2649 cds_ssr_unprotect(__func__);
2650
2651 return ret;
2652}
2653
2654static const struct nla_policy
2655wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2656 +1] = {
2657 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2658};
2659
2660/**
2661 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2662 * @hdd_ctx: HDD context
2663 * @device_mode: device mode
2664 * Return: bool
2665 */
2666static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002667 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668{
2669 hdd_adapter_t *adapter;
2670 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2671 hdd_ap_ctx_t *ap_ctx;
2672 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302673 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302675 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 &adapter_node);
2677
2678 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302679 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 adapter = adapter_node->pAdapter;
2681
2682 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002683 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 ap_ctx =
2685 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2686
2687 /*
2688 * if there is SAP already running on DFS channel,
2689 * do not disable scan on dfs channels. Note that
2690 * with SAP on DFS, there cannot be conurrency on
2691 * single radio. But then we can have multiple
2692 * radios !!
2693 */
2694 if (CHANNEL_STATE_DFS ==
2695 cds_get_channel_state(
2696 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002697 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002698 return true;
2699 }
2700 }
2701
2702 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002703 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 sta_ctx =
2705 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2706
2707 /*
2708 * if STA is already connected on DFS channel,
2709 * do not disable scan on dfs channels
2710 */
2711 if (hdd_conn_is_connected(sta_ctx) &&
2712 (CHANNEL_STATE_DFS ==
2713 cds_get_channel_state(
2714 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002715 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 return true;
2717 }
2718 }
2719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302720 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 adapter_node,
2722 &next);
2723 adapter_node = next;
2724 }
2725
2726 return false;
2727}
2728
2729/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002730 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2731 * @hdd_ctx: HDD context within host driver
2732 * @adapter: Adapter pointer
2733 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2734 *
2735 * Loops through devices to see who is operating on DFS channels
2736 * and then disables/enables DFS channels by calling SME API.
2737 * Fails the disable request if any device is active on a DFS channel.
2738 *
2739 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002741
2742int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2743 hdd_adapter_t *adapter,
2744 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002746 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302747 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749
2750 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2751 if (no_dfs_flag) {
2752 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002753 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754
2755 if (true == status)
2756 return -EOPNOTSUPP;
2757
2758 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002759 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760
2761 if (true == status)
2762 return -EOPNOTSUPP;
2763 }
2764
2765 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2766
2767 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2768
2769 /*
2770 * call the SME API to tunnel down the new channel list
2771 * to the firmware
2772 */
2773 status = sme_handle_dfs_chan_scan(
2774 h_hal, hdd_ctx->config->enableDFSChnlScan);
2775
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302776 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 ret_val = 0;
2778
2779 /*
2780 * Clear the SME scan cache also. Note that the
2781 * clearing of scan results is independent of session;
2782 * so no need to iterate over
2783 * all sessions
2784 */
2785 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302786 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 ret_val = -EPERM;
2788 }
2789
2790 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002791 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002792 ret_val = 0;
2793 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002794 return ret_val;
2795}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002797/**
2798 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2799 * @wiphy: corestack handler
2800 * @wdev: wireless device
2801 * @data: data
2802 * @data_len: data length
2803 * Return: success(0) or reason code for failure
2804 */
2805static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2806 struct wireless_dev *wdev,
2807 const void *data,
2808 int data_len)
2809{
2810 struct net_device *dev = wdev->netdev;
2811 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2812 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2813 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2814 int ret_val;
2815 uint32_t no_dfs_flag = 0;
2816
Jeff Johnson1f61b612016-02-12 16:28:33 -08002817 ENTER_DEV(dev);
2818
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002819 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302820 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002821 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002822
2823 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2824 data, data_len,
2825 wlan_hdd_set_no_dfs_flag_config_policy)) {
2826 hdd_err("invalid attr");
2827 return -EINVAL;
2828 }
2829
2830 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2831 hdd_err("attr dfs flag failed");
2832 return -EINVAL;
2833 }
2834
2835 no_dfs_flag = nla_get_u32(
2836 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2837
Jeff Johnson020db452016-06-29 14:37:26 -07002838 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002839
2840 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002841 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002842 return -EINVAL;
2843 }
2844
2845 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2846 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 return ret_val;
2848}
2849
2850/**
2851 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2852 *
2853 * @wiphy: wiphy device pointer
2854 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002855 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856 * @data_len: Buffer length
2857 *
2858 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2859 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2860 *
2861 * Return: EOK or other error codes.
2862 */
2863
2864static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2865 struct wireless_dev *wdev,
2866 const void *data,
2867 int data_len)
2868{
2869 int ret;
2870
2871 cds_ssr_protect(__func__);
2872 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2873 data, data_len);
2874 cds_ssr_unprotect(__func__);
2875
2876 return ret;
2877}
2878
Manikandan Mohan80dea792016-04-28 16:36:48 -07002879static const struct nla_policy
2880wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2881 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2882};
2883
2884/**
2885 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2886 * @wiphy: wiphy device pointer
2887 * @wdev: wireless device pointer
2888 * @data: Vendor command data buffer
2889 * @data_len: Buffer length
2890 *
2891 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2892 * setup WISA Mode features.
2893 *
2894 * Return: Success(0) or reason code for failure
2895 */
2896static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2897 struct wireless_dev *wdev, const void *data, int data_len)
2898{
2899 struct net_device *dev = wdev->netdev;
2900 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2901 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2902 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2903 struct sir_wisa_params wisa;
2904 int ret_val;
2905 QDF_STATUS status;
2906 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07002907 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2908 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002909
2910 ENTER_DEV(dev);
2911 ret_val = wlan_hdd_validate_context(hdd_ctx);
2912 if (ret_val)
2913 goto err;
2914
2915 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2916 hdd_err("Command not allowed in FTM mode");
2917 return -EPERM;
2918 }
2919
2920 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2921 wlan_hdd_wisa_cmd_policy)) {
2922 hdd_err("Invalid WISA cmd attributes");
2923 ret_val = -EINVAL;
2924 goto err;
2925 }
2926 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2927 hdd_err("Invalid WISA mode");
2928 ret_val = -EINVAL;
2929 goto err;
2930 }
2931
2932 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2933 hdd_info("WISA Mode: %d", wisa_mode);
2934 wisa.mode = wisa_mode;
2935 wisa.vdev_id = adapter->sessionId;
2936 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002937 if (!QDF_IS_STATUS_SUCCESS(status)) {
2938 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002939 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002940 }
2941 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07002942 cdp_set_wisa_mode(soc,
2943 cdp_get_vdev_from_vdev_id(soc, pdev,
2944 adapter->sessionId),
2945 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002946err:
2947 EXIT();
2948 return ret_val;
2949}
2950
2951/**
2952 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2953 * @wiphy: corestack handler
2954 * @wdev: wireless device
2955 * @data: data
2956 * @data_len: data length
2957 *
2958 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2959 * setup WISA mode features.
2960 *
2961 * Return: Success(0) or reason code for failure
2962 */
2963static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2964 struct wireless_dev *wdev,
2965 const void *data,
2966 int data_len)
2967{
2968 int ret;
2969
2970 cds_ssr_protect(__func__);
2971 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2972 cds_ssr_unprotect(__func__);
2973
2974 return ret;
2975}
2976
Anurag Chouhan96919482016-07-13 16:36:57 +05302977/*
2978 * define short names for the global vendor params
2979 * used by __wlan_hdd_cfg80211_get_station_cmd()
2980 */
2981#define STATION_INVALID \
2982 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2983#define STATION_INFO \
2984 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2985#define STATION_ASSOC_FAIL_REASON \
2986 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2987#define STATION_MAX \
2988 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2989
2990static const struct nla_policy
2991hdd_get_station_policy[STATION_MAX + 1] = {
2992 [STATION_INFO] = {.type = NLA_FLAG},
2993 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2994};
2995
2996/**
2997 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2998 * @hdd_ctx: HDD context within host driver
2999 * @wdev: wireless device
3000 *
3001 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3002 * Validate cmd attributes and send the station info to upper layers.
3003 *
3004 * Return: Success(0) or reason code for failure
3005 */
3006static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3007 hdd_adapter_t *adapter)
3008{
3009 struct sk_buff *skb = NULL;
3010 uint32_t nl_buf_len;
3011 hdd_station_ctx_t *hdd_sta_ctx;
3012
3013 nl_buf_len = NLMSG_HDRLEN;
3014 nl_buf_len += sizeof(uint32_t);
3015 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3016
3017 if (!skb) {
3018 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3019 return -ENOMEM;
3020 }
3021
3022 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3023
3024 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3025 hdd_sta_ctx->conn_info.assoc_status_code)) {
3026 hdd_err("put fail");
3027 goto fail;
3028 }
3029 return cfg80211_vendor_cmd_reply(skb);
3030fail:
3031 if (skb)
3032 kfree_skb(skb);
3033 return -EINVAL;
3034}
3035
3036/**
3037 * hdd_map_auth_type() - transform auth type specific to
3038 * vendor command
3039 * @auth_type: csr auth type
3040 *
3041 * Return: Success(0) or reason code for failure
3042 */
3043static int hdd_convert_auth_type(uint32_t auth_type)
3044{
3045 uint32_t ret_val;
3046
3047 switch (auth_type) {
3048 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3049 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3050 break;
3051 case eCSR_AUTH_TYPE_SHARED_KEY:
3052 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3053 break;
3054 case eCSR_AUTH_TYPE_WPA:
3055 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3056 break;
3057 case eCSR_AUTH_TYPE_WPA_PSK:
3058 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3059 break;
3060 case eCSR_AUTH_TYPE_AUTOSWITCH:
3061 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3062 break;
3063 case eCSR_AUTH_TYPE_WPA_NONE:
3064 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3065 break;
3066 case eCSR_AUTH_TYPE_RSN:
3067 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3068 break;
3069 case eCSR_AUTH_TYPE_RSN_PSK:
3070 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3071 break;
3072 case eCSR_AUTH_TYPE_FT_RSN:
3073 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3074 break;
3075 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3076 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3077 break;
3078 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3079 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3080 break;
3081 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3082 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3083 break;
3084 case eCSR_AUTH_TYPE_CCKM_WPA:
3085 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3086 break;
3087 case eCSR_AUTH_TYPE_CCKM_RSN:
3088 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3089 break;
3090 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3091 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3092 break;
3093 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3094 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3095 break;
3096 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3097 case eCSR_AUTH_TYPE_FAILED:
3098 case eCSR_AUTH_TYPE_NONE:
3099 default:
3100 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3101 break;
3102 }
3103 return ret_val;
3104}
3105
3106/**
3107 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3108 * vendor command
3109 * @dot11mode: dot11mode
3110 *
3111 * Return: Success(0) or reason code for failure
3112 */
3113static int hdd_convert_dot11mode(uint32_t dot11mode)
3114{
3115 uint32_t ret_val;
3116
3117 switch (dot11mode) {
3118 case eCSR_CFG_DOT11_MODE_11A:
3119 ret_val = QCA_WLAN_802_11_MODE_11A;
3120 break;
3121 case eCSR_CFG_DOT11_MODE_11B:
3122 ret_val = QCA_WLAN_802_11_MODE_11B;
3123 break;
3124 case eCSR_CFG_DOT11_MODE_11G:
3125 ret_val = QCA_WLAN_802_11_MODE_11G;
3126 break;
3127 case eCSR_CFG_DOT11_MODE_11N:
3128 ret_val = QCA_WLAN_802_11_MODE_11N;
3129 break;
3130 case eCSR_CFG_DOT11_MODE_11AC:
3131 ret_val = QCA_WLAN_802_11_MODE_11AC;
3132 break;
3133 case eCSR_CFG_DOT11_MODE_AUTO:
3134 case eCSR_CFG_DOT11_MODE_ABG:
3135 default:
3136 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3137 }
3138 return ret_val;
3139}
3140
3141/**
3142 * hdd_add_tx_bitrate() - add tx bitrate attribute
3143 * @skb: pointer to sk buff
3144 * @hdd_sta_ctx: pointer to hdd station context
3145 * @idx: attribute index
3146 *
3147 * Return: Success(0) or reason code for failure
3148 */
3149static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3150 hdd_station_ctx_t *hdd_sta_ctx,
3151 int idx)
3152{
3153 struct nlattr *nla_attr;
3154 uint32_t bitrate, bitrate_compat;
3155
3156 nla_attr = nla_nest_start(skb, idx);
3157 if (!nla_attr)
3158 goto fail;
3159 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3160 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3161
3162 /* report 16-bit bitrate only if we can */
3163 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3164 if (bitrate > 0 &&
3165 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3166 hdd_err("put fail");
3167 goto fail;
3168 }
3169 if (bitrate_compat > 0 &&
3170 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3171 hdd_err("put fail");
3172 goto fail;
3173 }
3174 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3175 hdd_sta_ctx->conn_info.txrate.nss)) {
3176 hdd_err("put fail");
3177 goto fail;
3178 }
3179 nla_nest_end(skb, nla_attr);
3180 return 0;
3181fail:
3182 return -EINVAL;
3183}
3184
3185/**
3186 * hdd_add_sta_info() - add station info attribute
3187 * @skb: pointer to sk buff
3188 * @hdd_sta_ctx: pointer to hdd station context
3189 * @idx: attribute index
3190 *
3191 * Return: Success(0) or reason code for failure
3192 */
3193static int32_t hdd_add_sta_info(struct sk_buff *skb,
3194 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3195{
3196 struct nlattr *nla_attr;
3197
3198 nla_attr = nla_nest_start(skb, idx);
3199 if (!nla_attr)
3200 goto fail;
3201 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3202 (hdd_sta_ctx->conn_info.signal + 100))) {
3203 hdd_err("put fail");
3204 goto fail;
3205 }
3206 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3207 goto fail;
3208 nla_nest_end(skb, nla_attr);
3209 return 0;
3210fail:
3211 return -EINVAL;
3212}
3213
3214/**
3215 * hdd_add_survey_info() - add survey info attribute
3216 * @skb: pointer to sk buff
3217 * @hdd_sta_ctx: pointer to hdd station context
3218 * @idx: attribute index
3219 *
3220 * Return: Success(0) or reason code for failure
3221 */
3222static int32_t hdd_add_survey_info(struct sk_buff *skb,
3223 hdd_station_ctx_t *hdd_sta_ctx,
3224 int idx)
3225{
3226 struct nlattr *nla_attr;
3227
3228 nla_attr = nla_nest_start(skb, idx);
3229 if (!nla_attr)
3230 goto fail;
3231 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3232 hdd_sta_ctx->conn_info.freq) ||
3233 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3234 (hdd_sta_ctx->conn_info.noise + 100))) {
3235 hdd_err("put fail");
3236 goto fail;
3237 }
3238 nla_nest_end(skb, nla_attr);
3239 return 0;
3240fail:
3241 return -EINVAL;
3242}
3243
3244/**
3245 * hdd_add_link_standard_info() - add link info attribute
3246 * @skb: pointer to sk buff
3247 * @hdd_sta_ctx: pointer to hdd station context
3248 * @idx: attribute index
3249 *
3250 * Return: Success(0) or reason code for failure
3251 */
3252static int32_t
3253hdd_add_link_standard_info(struct sk_buff *skb,
3254 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3255{
3256 struct nlattr *nla_attr;
3257
3258 nla_attr = nla_nest_start(skb, idx);
3259 if (!nla_attr)
3260 goto fail;
3261 if (nla_put(skb,
3262 NL80211_ATTR_SSID,
3263 hdd_sta_ctx->conn_info.SSID.SSID.length,
3264 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3265 hdd_err("put fail");
3266 goto fail;
3267 }
3268 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3269 goto fail;
3270 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3271 goto fail;
3272 nla_nest_end(skb, nla_attr);
3273 return 0;
3274fail:
3275 return -EINVAL;
3276}
3277
3278/**
3279 * hdd_add_ap_standard_info() - add ap info attribute
3280 * @skb: pointer to sk buff
3281 * @hdd_sta_ctx: pointer to hdd station context
3282 * @idx: attribute index
3283 *
3284 * Return: Success(0) or reason code for failure
3285 */
3286static int32_t
3287hdd_add_ap_standard_info(struct sk_buff *skb,
3288 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3289{
3290 struct nlattr *nla_attr;
3291
3292 nla_attr = nla_nest_start(skb, idx);
3293 if (!nla_attr)
3294 goto fail;
3295 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3296 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3297 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3298 &hdd_sta_ctx->conn_info.vht_caps)) {
3299 hdd_err("put fail");
3300 goto fail;
3301 }
3302 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3303 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3304 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3305 &hdd_sta_ctx->conn_info.ht_caps)) {
3306 hdd_err("put fail");
3307 goto fail;
3308 }
3309 nla_nest_end(skb, nla_attr);
3310 return 0;
3311fail:
3312 return -EINVAL;
3313}
3314
3315/**
3316 * hdd_get_station_info() - send BSS information to supplicant
3317 * @hdd_ctx: pointer to hdd context
3318 * @adapter: pointer to adapter
3319 *
3320 * Return: 0 if success else error status
3321 */
3322static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3323 hdd_adapter_t *adapter)
3324{
3325 struct sk_buff *skb = NULL;
3326 uint8_t *tmp_hs20 = NULL;
3327 uint32_t nl_buf_len;
3328 hdd_station_ctx_t *hdd_sta_ctx;
3329
3330 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3331
3332 nl_buf_len = NLMSG_HDRLEN;
3333 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3334 sizeof(hdd_sta_ctx->conn_info.freq) +
3335 sizeof(hdd_sta_ctx->conn_info.noise) +
3336 sizeof(hdd_sta_ctx->conn_info.signal) +
3337 (sizeof(uint32_t) * 2) +
3338 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3339 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3340 sizeof(hdd_sta_ctx->conn_info.authType) +
3341 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3342 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3343 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3344 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3345 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3346 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3347 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3348 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3349 1);
3350 }
3351 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3352 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3353 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3354 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3355
3356
3357 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3358 if (!skb) {
3359 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3360 return -ENOMEM;
3361 }
3362
3363 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3364 LINK_INFO_STANDARD_NL80211_ATTR)) {
3365 hdd_err("put fail");
3366 goto fail;
3367 }
3368 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3369 AP_INFO_STANDARD_NL80211_ATTR)) {
3370 hdd_err("put fail");
3371 goto fail;
3372 }
3373 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3374 hdd_sta_ctx->conn_info.roam_count) ||
3375 nla_put_u32(skb, INFO_AKM,
3376 hdd_convert_auth_type(
3377 hdd_sta_ctx->conn_info.authType)) ||
3378 nla_put_u32(skb, WLAN802_11_MODE,
3379 hdd_convert_dot11mode(
3380 hdd_sta_ctx->conn_info.dot11Mode))) {
3381 hdd_err("put fail");
3382 goto fail;
3383 }
3384 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3385 if (nla_put(skb, HT_OPERATION,
3386 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3387 &hdd_sta_ctx->conn_info.ht_operation)) {
3388 hdd_err("put fail");
3389 goto fail;
3390 }
3391 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3392 if (nla_put(skb, VHT_OPERATION,
3393 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3394 &hdd_sta_ctx->conn_info.vht_operation)) {
3395 hdd_err("put fail");
3396 goto fail;
3397 }
3398 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3399 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3400 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3401 tmp_hs20 + 1)) {
3402 hdd_err("put fail");
3403 goto fail;
3404 }
3405
3406 return cfg80211_vendor_cmd_reply(skb);
3407fail:
3408 if (skb)
3409 kfree_skb(skb);
3410 return -EINVAL;
3411}
3412
3413/**
3414 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3415 * @wiphy: corestack handler
3416 * @wdev: wireless device
3417 * @data: data
3418 * @data_len: data length
3419 *
3420 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3421 * Validate cmd attributes and send the station info to upper layers.
3422 *
3423 * Return: Success(0) or reason code for failure
3424 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303425static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303426__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3427 struct wireless_dev *wdev,
3428 const void *data,
3429 int data_len)
3430{
3431 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3432 struct net_device *dev = wdev->netdev;
3433 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3434 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3435 int32_t status;
3436
3437 ENTER_DEV(dev);
3438 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3439 hdd_err("Command not allowed in FTM mode");
3440 status = -EPERM;
3441 goto out;
3442 }
3443
3444 status = wlan_hdd_validate_context(hdd_ctx);
3445 if (0 != status)
3446 goto out;
3447
3448
3449 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3450 data, data_len, NULL);
3451 if (status) {
3452 hdd_err("Invalid ATTR");
3453 goto out;
3454 }
3455
3456 /* Parse and fetch Command Type*/
3457 if (tb[STATION_INFO]) {
3458 status = hdd_get_station_info(hdd_ctx, adapter);
3459 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3460 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3461 } else {
3462 hdd_err("get station info cmd type failed");
3463 status = -EINVAL;
3464 goto out;
3465 }
3466 EXIT();
3467out:
3468 return status;
3469}
3470
3471/**
3472 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3473 * @wiphy: corestack handler
3474 * @wdev: wireless device
3475 * @data: data
3476 * @data_len: data length
3477 *
3478 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3479 * Validate cmd attributes and send the station info to upper layers.
3480 *
3481 * Return: Success(0) or reason code for failure
3482 */
3483static int32_t
3484hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3485 struct wireless_dev *wdev,
3486 const void *data,
3487 int data_len)
3488{
3489 int ret;
3490
3491 cds_ssr_protect(__func__);
3492 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3493 cds_ssr_unprotect(__func__);
3494
3495 return ret;
3496}
3497
3498/*
3499 * undef short names defined for get station command
3500 * used by __wlan_hdd_cfg80211_get_station_cmd()
3501 */
3502#undef STATION_INVALID
3503#undef STATION_INFO
3504#undef STATION_ASSOC_FAIL_REASON
3505#undef STATION_MAX
3506
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3508/**
3509 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3510 * @wiphy: pointer to wireless wiphy structure.
3511 * @wdev: pointer to wireless_dev structure.
3512 * @data: Pointer to the Key data
3513 * @data_len:Length of the data passed
3514 *
3515 * This is called when wlan driver needs to save the keys received via
3516 * vendor specific command.
3517 *
3518 * Return: Return the Success or Failure code.
3519 */
3520static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3521 struct wireless_dev *wdev,
3522 const void *data, int data_len)
3523{
3524 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3525 struct net_device *dev = wdev->netdev;
3526 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3527 hdd_context_t *hdd_ctx_ptr;
3528 int status;
3529
Jeff Johnson1f61b612016-02-12 16:28:33 -08003530 ENTER_DEV(dev);
3531
Anurag Chouhan6d760662016-02-20 16:05:43 +05303532 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533 hdd_err("Command not allowed in FTM mode");
3534 return -EPERM;
3535 }
3536
3537 if ((data == NULL) || (data_len == 0) ||
3538 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003539 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 return -EINVAL;
3541 }
3542
3543 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3544 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003545 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546 return -EINVAL;
3547 }
3548
3549 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303550 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3553 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003554 true,
3555 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303556 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3557 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3559 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3560 return 0;
3561}
3562
3563/**
3564 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3565 * @wiphy: pointer to wireless wiphy structure.
3566 * @wdev: pointer to wireless_dev structure.
3567 * @data: Pointer to the Key data
3568 * @data_len:Length of the data passed
3569 *
3570 * This is called when wlan driver needs to save the keys received via
3571 * vendor specific command.
3572 *
3573 * Return: Return the Success or Failure code.
3574 */
3575static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3576 struct wireless_dev *wdev,
3577 const void *data, int data_len)
3578{
3579 int ret;
3580
3581 cds_ssr_protect(__func__);
3582 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3583 cds_ssr_unprotect(__func__);
3584
3585 return ret;
3586}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003587#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588
3589static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3590 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3591 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3592 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003593 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594};
3595
3596/**
3597 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3598 * @wiphy: pointer to wireless wiphy structure.
3599 * @wdev: pointer to wireless_dev structure.
3600 * @data: Pointer to the data to be passed via vendor interface
3601 * @data_len:Length of the data to be passed
3602 *
3603 * This is called when wlan driver needs to send wifi driver related info
3604 * (driver/fw version) to the user space application upon request.
3605 *
3606 * Return: Return the Success or Failure code.
3607 */
3608static int
3609__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3610 struct wireless_dev *wdev,
3611 const void *data, int data_len)
3612{
3613 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3614 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003615 tSirVersionString driver_version;
3616 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003617 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003619 struct sk_buff *reply_skb;
3620 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621
Jeff Johnson1f61b612016-02-12 16:28:33 -08003622 ENTER_DEV(wdev->netdev);
3623
Anurag Chouhan6d760662016-02-20 16:05:43 +05303624 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 hdd_err("Command not allowed in FTM mode");
3626 return -EPERM;
3627 }
3628
3629 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303630 if (status)
3631 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632
3633 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3634 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003635 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 return -EINVAL;
3637 }
3638
3639 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003640 hdd_err("Rcvd req for Driver version");
3641 strlcpy(driver_version, QWLAN_VERSIONSTR,
3642 sizeof(driver_version));
3643 skb_len += strlen(driver_version) + 1;
3644 count++;
3645 }
3646
3647 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3648 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3650 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003651 snprintf(firmware_version, sizeof(firmware_version),
3652 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3653 skb_len += strlen(firmware_version) + 1;
3654 count++;
3655 }
3656
3657 if (count == 0) {
3658 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 return -EINVAL;
3660 }
3661
Ryan Hsu7ac88852016-04-28 10:20:34 -07003662 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3663 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003666 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667 return -ENOMEM;
3668 }
3669
Ryan Hsu7ac88852016-04-28 10:20:34 -07003670 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3671 if (nla_put_string(reply_skb,
3672 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3673 driver_version))
3674 goto error_nla_fail;
3675 }
3676
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303677 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003678 if (nla_put_string(reply_skb,
3679 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3680 firmware_version))
3681 goto error_nla_fail;
3682 }
3683
3684 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3685 if (nla_put_u32(reply_skb,
3686 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3687 hdd_ctx->radio_index))
3688 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 }
3690
3691 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003692
3693error_nla_fail:
3694 hdd_err("nla put fail");
3695 kfree_skb(reply_skb);
3696 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697}
3698
3699/**
3700 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3701 * @wiphy: pointer to wireless wiphy structure.
3702 * @wdev: pointer to wireless_dev structure.
3703 * @data: Pointer to the data to be passed via vendor interface
3704 * @data_len:Length of the data to be passed
3705 *
3706 * This is called when wlan driver needs to send wifi driver related info
3707 * (driver/fw version) to the user space application upon request.
3708 *
3709 * Return: Return the Success or Failure code.
3710 */
3711static int
3712wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3713 struct wireless_dev *wdev,
3714 const void *data, int data_len)
3715{
3716 int ret;
3717
3718 cds_ssr_protect(__func__);
3719 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3720 cds_ssr_unprotect(__func__);
3721
3722 return ret;
3723}
3724
3725/**
3726 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3727 * @wiphy: pointer to wireless wiphy structure.
3728 * @wdev: pointer to wireless_dev structure.
3729 * @data: Pointer to the data to be passed via vendor interface
3730 * @data_len:Length of the data to be passed
3731 *
3732 * This is called by userspace to know the supported logger features
3733 *
3734 * Return: Return the Success or Failure code.
3735 */
3736static int
3737__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3738 struct wireless_dev *wdev,
3739 const void *data, int data_len)
3740{
3741 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3742 int status;
3743 uint32_t features;
3744 struct sk_buff *reply_skb = NULL;
3745
Jeff Johnson1f61b612016-02-12 16:28:33 -08003746 ENTER_DEV(wdev->netdev);
3747
Anurag Chouhan6d760662016-02-20 16:05:43 +05303748 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 hdd_err("Command not allowed in FTM mode");
3750 return -EPERM;
3751 }
3752
3753 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303754 if (status)
3755 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003756
3757 features = 0;
3758
3759 if (hdd_is_memdump_supported())
3760 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3761 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3762 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3763 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3764
3765 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3766 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3767 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003768 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769 return -ENOMEM;
3770 }
3771
Jeff Johnson020db452016-06-29 14:37:26 -07003772 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003773 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3774 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003775 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 kfree_skb(reply_skb);
3777 return -EINVAL;
3778 }
3779
3780 return cfg80211_vendor_cmd_reply(reply_skb);
3781}
3782
3783/**
3784 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3785 * @wiphy: pointer to wireless wiphy structure.
3786 * @wdev: pointer to wireless_dev structure.
3787 * @data: Pointer to the data to be passed via vendor interface
3788 * @data_len:Length of the data to be passed
3789 *
3790 * This is called by userspace to know the supported logger features
3791 *
3792 * Return: Return the Success or Failure code.
3793 */
3794static int
3795wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3796 struct wireless_dev *wdev,
3797 const void *data, int data_len)
3798{
3799 int ret;
3800
3801 cds_ssr_protect(__func__);
3802 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3803 data, data_len);
3804 cds_ssr_unprotect(__func__);
3805
3806 return ret;
3807}
3808
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003809#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810/**
3811 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05303812 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 * @bssid: pointer to bssid of roamed AP.
3814 * @req_rsn_ie: Pointer to request RSN IE
3815 * @req_rsn_len: Length of the request RSN IE
3816 * @rsp_rsn_ie: Pointer to response RSN IE
3817 * @rsp_rsn_len: Length of the response RSN IE
3818 * @roam_info_ptr: Pointer to the roaming related information
3819 *
3820 * This is called when wlan driver needs to send the roaming and
3821 * authorization information after roaming.
3822 *
3823 * The information that would be sent is the request RSN IE, response
3824 * RSN IE and BSSID of the newly roamed AP.
3825 *
3826 * If the Authorized status is authenticated, then additional parameters
3827 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3828 * supplicant.
3829 *
3830 * The supplicant upon receiving this event would ignore the legacy
3831 * cfg80211_roamed call and use the entire information from this event.
3832 * The cfg80211_roamed should still co-exist since the kernel will
3833 * make use of the parameters even if the supplicant ignores it.
3834 *
3835 * Return: Return the Success or Failure code.
3836 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05303837int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3839 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3840{
Prakash Dhavali989127d2016-11-29 14:56:44 +05303841 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003843 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003844 ENTER();
3845
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303846 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003848
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003849 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003850 !roam_info_ptr->roamSynchInProgress)
3851 return 0;
3852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05303854 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3856 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3857 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003858 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3860 GFP_KERNEL);
3861
3862 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003863 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864 return -EINVAL;
3865 }
3866
3867 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3868 ETH_ALEN, bssid) ||
3869 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3870 req_rsn_len, req_rsn_ie) ||
3871 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3872 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003873 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 goto nla_put_failure;
3875 }
Jeff Johnson020db452016-06-29 14:37:26 -07003876 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 if (roam_info_ptr->synchAuthStatus ==
3878 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003879 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003880 if (nla_put_u8(skb,
3881 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3882 hdd_err("nla put fail");
3883 goto nla_put_failure;
3884 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003885 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3886 /* if FT or CCKM connection: dont send replay counter */
3887 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3888 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3889 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3890 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3891 nla_put(skb,
3892 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3893 SIR_REPLAY_CTR_LEN,
3894 roam_info_ptr->replay_ctr)) {
3895 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003896 hdd_err("failed to send replay counter.");
3897 goto nla_put_failure;
3898 }
3899 if (nla_put(skb,
3900 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3901 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3902 nla_put(skb,
3903 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3904 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3905 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003906 goto nla_put_failure;
3907 }
3908 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003909 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003910 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3911 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003912 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003913 goto nla_put_failure;
3914 }
3915 }
3916
Jeff Johnson020db452016-06-29 14:37:26 -07003917 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003918 roam_info_ptr->subnet_change_status);
3919
3920 /*
3921 * Add subnet change status if subnet has changed
3922 * 0 = unchanged
3923 * 1 = changed
3924 * 2 = unknown
3925 */
3926 if (roam_info_ptr->subnet_change_status) {
3927 if (nla_put_u8(skb,
3928 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3929 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003930 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003931 goto nla_put_failure;
3932 }
3933 }
3934
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003935 cfg80211_vendor_event(skb, GFP_KERNEL);
3936 return 0;
3937
3938nla_put_failure:
3939 kfree_skb(skb);
3940 return -EINVAL;
3941}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003942#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943
3944static const struct nla_policy
3945wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3946
3947 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3948 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3949 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303950 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303951 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3952 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003953 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3954 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3955 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3956 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3957 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303958 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003959};
3960
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003961/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303962 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3963 *
3964 * @adapter: Pointer to HDD adapter
3965 * @ie_data: Pointer to Scan IEs buffer
3966 * @ie_len: Length of Scan IEs
3967 *
3968 * Return: 0 on success; error number otherwise
3969 */
3970static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3971 uint8_t *ie_data, uint8_t ie_len)
3972{
3973 hdd_scaninfo_t *scan_info = NULL;
3974 scan_info = &adapter->scan_info;
3975
3976 if (scan_info->default_scan_ies) {
3977 qdf_mem_free(scan_info->default_scan_ies);
3978 scan_info->default_scan_ies = NULL;
3979 }
3980
3981 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3982 if (!scan_info->default_scan_ies)
3983 return -ENOMEM;
3984
3985 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3986 scan_info->default_scan_ies_len = ie_len;
3987 return 0;
3988}
3989
3990/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003991 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3992 * vendor command
3993 *
3994 * @wiphy: wiphy device pointer
3995 * @wdev: wireless device pointer
3996 * @data: Vendor command data buffer
3997 * @data_len: Buffer length
3998 *
3999 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4000 *
4001 * Return: Error code.
4002 */
4003static int
4004__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4005 struct wireless_dev *wdev,
4006 const void *data,
4007 int data_len)
4008{
4009 struct net_device *dev = wdev->netdev;
4010 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4011 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4012 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4013 int ret_val = 0;
4014 u32 modulated_dtim;
4015 u16 stats_avg_factor;
4016 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304017 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004018 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004019 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304020 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304021 int attr_len;
4022 int access_policy = 0;
4023 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4024 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304025 uint16_t scan_ie_len = 0;
4026 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304027 struct sir_set_tx_rx_aggregation_size request;
4028 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004029 uint8_t retry, delay;
4030 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304031 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304032
Jeff Johnson1f61b612016-02-12 16:28:33 -08004033 ENTER_DEV(dev);
4034
Anurag Chouhan6d760662016-02-20 16:05:43 +05304035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 hdd_err("Command not allowed in FTM mode");
4037 return -EPERM;
4038 }
4039
4040 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304041 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043
4044 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4045 data, data_len,
4046 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004047 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 return -EINVAL;
4049 }
4050
Krunal Sonie3531942016-04-12 17:43:53 -07004051 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4052 ftm_capab = nla_get_u32(tb[
4053 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4054 hdd_ctx->config->fine_time_meas_cap =
4055 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4056 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304057 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004058 hdd_ctx->config->fine_time_meas_cap);
4059 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4060 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4061 hdd_ctx->config->fine_time_meas_cap);
4062 }
4063
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4065 modulated_dtim = nla_get_u32(
4066 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4067
4068 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4069 adapter->sessionId,
4070 modulated_dtim);
4071
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304072 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 ret_val = -EPERM;
4074 }
4075
Kapil Gupta6213c012016-09-02 19:39:09 +05304076 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4077 qpower = nla_get_u8(
4078 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4079 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4080 ret_val = -EINVAL;
4081 }
4082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4084 stats_avg_factor = nla_get_u16(
4085 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4086 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4087 adapter->sessionId,
4088 stats_avg_factor);
4089
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304090 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 ret_val = -EPERM;
4092 }
4093
4094
4095 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4096 guard_time = nla_get_u32(
4097 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4098 status = sme_configure_guard_time(hdd_ctx->hHal,
4099 adapter->sessionId,
4100 guard_time);
4101
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304102 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004103 ret_val = -EPERM;
4104 }
4105
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304106 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4107 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4108 attr_len = nla_len(
4109 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4110 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4111 hdd_info("Invalid value. attr_len %d",
4112 attr_len);
4113 return -EINVAL;
4114 }
4115
4116 nla_memcpy(&vendor_ie,
4117 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4118 attr_len);
4119 vendor_ie_present = true;
4120 hdd_info("Access policy vendor ie present.attr_len %d",
4121 attr_len);
4122 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4123 &vendor_ie[0], attr_len);
4124 }
4125
4126 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4127 access_policy = (int) nla_get_u32(
4128 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4129 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4130 (access_policy >
4131 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4132 hdd_info("Invalid value. access_policy %d",
4133 access_policy);
4134 return -EINVAL;
4135 }
4136 access_policy_present = true;
4137 hdd_info("Access policy present. access_policy %d",
4138 access_policy);
4139 }
4140
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004141 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4142 retry = nla_get_u8(tb[
4143 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4144 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4145 CFG_NON_AGG_RETRY_MAX : retry;
4146 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4147 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4148 retry, PDEV_CMD);
4149 }
4150
4151 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4152 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4153 retry = retry > CFG_AGG_RETRY_MAX ?
4154 CFG_AGG_RETRY_MAX : retry;
4155
4156 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4157 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4158 CFG_AGG_RETRY_MIN : retry;
4159 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4160 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4161 retry, PDEV_CMD);
4162 }
4163
4164 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4165 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4166 retry = retry > CFG_MGMT_RETRY_MAX ?
4167 CFG_MGMT_RETRY_MAX : retry;
4168 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4169 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4170 retry, PDEV_CMD);
4171 }
4172
4173 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4174 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4175 retry = retry > CFG_CTRL_RETRY_MAX ?
4176 CFG_CTRL_RETRY_MAX : retry;
4177 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4178 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4179 retry, PDEV_CMD);
4180 }
4181
4182 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4183 delay = nla_get_u8(tb[
4184 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4185 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4186 CFG_PROPAGATION_DELAY_MAX : delay;
4187 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4188 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4189 delay, PDEV_CMD);
4190 }
4191
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304192 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4193 tx_fail_count = nla_get_u32(
4194 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4195 if (tx_fail_count) {
4196 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4197 adapter->sessionId, tx_fail_count);
4198 if (QDF_STATUS_SUCCESS != status) {
4199 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4200 status);
4201 return -EINVAL;
4202 }
4203 }
4204 }
4205
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304206 if (vendor_ie_present && access_policy_present) {
4207 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4208 access_policy =
4209 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304210 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304211 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304212 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304213
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304214 hdd_info("calling sme_update_access_policy_vendor_ie");
4215 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4216 adapter->sessionId, &vendor_ie[0],
4217 access_policy);
4218 if (QDF_STATUS_SUCCESS != status) {
4219 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304220 return -EINVAL;
4221 }
4222 }
4223
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304224 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4225 set_value = nla_get_u8(
4226 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4227 hdd_info("set_value: %d", set_value);
4228 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4229 }
4230
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304231 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4232 scan_ie_len = nla_len(
4233 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4234 hdd_info("Received default scan IE of len %d session %d device mode %d",
4235 scan_ie_len, adapter->sessionId,
4236 adapter->device_mode);
4237 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4238 scan_ie = (uint8_t *) nla_data(tb
4239 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304240
4241 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4242 scan_ie_len))
4243 hdd_err("Failed to save default scan IEs");
4244
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304245 if (adapter->device_mode == QDF_STA_MODE) {
4246 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4247 adapter->sessionId, scan_ie,
4248 scan_ie_len);
4249 if (QDF_STATUS_SUCCESS != status)
4250 ret_val = -EPERM;
4251 }
4252 } else
4253 ret_val = -EPERM;
4254 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304255
4256 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4257 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4258 /* if one is specified, both must be specified */
4259 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4260 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4261 hdd_err("Both TX and RX MPDU Aggregation required");
4262 return -EINVAL;
4263 }
4264
4265 request.tx_aggregation_size = nla_get_u8(
4266 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4267 request.rx_aggregation_size = nla_get_u8(
4268 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4269 request.vdev_id = adapter->sessionId;
4270
4271 if (request.tx_aggregation_size >=
4272 CFG_TX_AGGREGATION_SIZE_MIN &&
4273 request.tx_aggregation_size <=
4274 CFG_TX_AGGREGATION_SIZE_MAX &&
4275 request.rx_aggregation_size >=
4276 CFG_RX_AGGREGATION_SIZE_MIN &&
4277 request.rx_aggregation_size <=
4278 CFG_RX_AGGREGATION_SIZE_MAX) {
4279 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4280 if (qdf_status != QDF_STATUS_SUCCESS) {
4281 hdd_err("failed to set aggr sizes err %d",
4282 qdf_status);
4283 ret_val = -EPERM;
4284 }
4285 } else {
4286 hdd_err("TX %d RX %d MPDU aggr size not in range",
4287 request.tx_aggregation_size,
4288 request.rx_aggregation_size);
4289 ret_val = -EINVAL;
4290 }
4291 }
4292
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304293 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4294 uint8_t ignore_assoc_disallowed;
4295
4296 ignore_assoc_disallowed
4297 = nla_get_u8(tb[
4298 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4299 hdd_info("Set ignore_assoc_disallowed value - %d",
4300 ignore_assoc_disallowed);
4301 if ((ignore_assoc_disallowed <
4302 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4303 (ignore_assoc_disallowed >
4304 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4305 return -EPERM;
4306
4307 sme_update_session_param(hdd_ctx->hHal,
4308 adapter->sessionId,
4309 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4310 ignore_assoc_disallowed);
4311 }
4312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 return ret_val;
4314}
4315
4316/**
4317 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4318 * vendor command
4319 *
4320 * @wiphy: wiphy device pointer
4321 * @wdev: wireless device pointer
4322 * @data: Vendor command data buffer
4323 * @data_len: Buffer length
4324 *
4325 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4326 *
4327 * Return: EOK or other error codes.
4328 */
4329static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4330 struct wireless_dev *wdev,
4331 const void *data,
4332 int data_len)
4333{
4334 int ret;
4335
4336 cds_ssr_protect(__func__);
4337 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4338 data, data_len);
4339 cds_ssr_unprotect(__func__);
4340
4341 return ret;
4342}
4343
4344static const struct
4345nla_policy
4346qca_wlan_vendor_wifi_logger_start_policy
4347[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4348 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4349 = {.type = NLA_U32 },
4350 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4351 = {.type = NLA_U32 },
4352 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4353 = {.type = NLA_U32 },
4354};
4355
4356/**
4357 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4358 * or disable the collection of packet statistics from the firmware
4359 * @wiphy: WIPHY structure pointer
4360 * @wdev: Wireless device structure pointer
4361 * @data: Pointer to the data received
4362 * @data_len: Length of the data received
4363 *
4364 * This function enables or disables the collection of packet statistics from
4365 * the firmware
4366 *
4367 * Return: 0 on success and errno on failure
4368 */
4369static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4370 struct wireless_dev *wdev,
4371 const void *data,
4372 int data_len)
4373{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304374 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4376 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4377 struct sir_wifi_start_log start_log;
4378
Jeff Johnson1f61b612016-02-12 16:28:33 -08004379 ENTER_DEV(wdev->netdev);
4380
Anurag Chouhan6d760662016-02-20 16:05:43 +05304381 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 hdd_err("Command not allowed in FTM mode");
4383 return -EPERM;
4384 }
4385
4386 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304387 if (status)
4388 return status;
4389
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390
4391 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4392 data, data_len,
4393 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004394 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 return -EINVAL;
4396 }
4397
4398 /* Parse and fetch ring id */
4399 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004400 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 return -EINVAL;
4402 }
4403 start_log.ring_id = nla_get_u32(
4404 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004405 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406
4407 /* Parse and fetch verbose level */
4408 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004409 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 return -EINVAL;
4411 }
4412 start_log.verbose_level = nla_get_u32(
4413 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004414 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415
4416 /* Parse and fetch flag */
4417 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004418 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 return -EINVAL;
4420 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304421 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304423 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004424
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304425 /* size is buff size which can be set using iwpriv command*/
4426 start_log.size = 0;
4427
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4429
4430 if (start_log.ring_id == RING_ID_WAKELOCK) {
4431 /* Start/stop wakelock events */
4432 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4433 cds_set_wakelock_logging(true);
4434 else
4435 cds_set_wakelock_logging(false);
4436 return 0;
4437 }
4438
4439 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304440 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004441 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004442 status);
4443 return -EINVAL;
4444 }
4445 return 0;
4446}
4447
4448/**
4449 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4450 * or disable the collection of packet statistics from the firmware
4451 * @wiphy: WIPHY structure pointer
4452 * @wdev: Wireless device structure pointer
4453 * @data: Pointer to the data received
4454 * @data_len: Length of the data received
4455 *
4456 * This function is used to enable or disable the collection of packet
4457 * statistics from the firmware
4458 *
4459 * Return: 0 on success and errno on failure
4460 */
4461static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4462 struct wireless_dev *wdev,
4463 const void *data,
4464 int data_len)
4465{
4466 int ret = 0;
4467
4468 cds_ssr_protect(__func__);
4469 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4470 wdev, data, data_len);
4471 cds_ssr_unprotect(__func__);
4472
4473 return ret;
4474}
4475
4476static const struct
4477nla_policy
4478qca_wlan_vendor_wifi_logger_get_ring_data_policy
4479[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4480 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4481 = {.type = NLA_U32 },
4482};
4483
4484/**
4485 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4486 * @wiphy: WIPHY structure pointer
4487 * @wdev: Wireless device structure pointer
4488 * @data: Pointer to the data received
4489 * @data_len: Length of the data received
4490 *
4491 * This function is used to flush or retrieve the per packet statistics from
4492 * the driver
4493 *
4494 * Return: 0 on success and errno on failure
4495 */
4496static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4497 struct wireless_dev *wdev,
4498 const void *data,
4499 int data_len)
4500{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304501 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 uint32_t ring_id;
4503 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4504 struct nlattr *tb
4505 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4506
Jeff Johnson1f61b612016-02-12 16:28:33 -08004507 ENTER_DEV(wdev->netdev);
4508
Anurag Chouhan6d760662016-02-20 16:05:43 +05304509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510 hdd_err("Command not allowed in FTM mode");
4511 return -EPERM;
4512 }
4513
4514 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304515 if (status)
4516 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004517
4518 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4519 data, data_len,
4520 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004521 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 return -EINVAL;
4523 }
4524
4525 /* Parse and fetch ring id */
4526 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004527 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 return -EINVAL;
4529 }
4530
4531 ring_id = nla_get_u32(
4532 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4533
4534 if (ring_id == RING_ID_PER_PACKET_STATS) {
4535 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004536 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304537 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4538 /*
4539 * As part of DRIVER ring ID, flush both driver and fw logs.
4540 * For other Ring ID's driver doesn't have any rings to flush
4541 */
4542 hdd_notice("Bug report triggered by framework");
4543
4544 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4545 WLAN_LOG_INDICATOR_FRAMEWORK,
4546 WLAN_LOG_REASON_CODE_UNUSED,
4547 true, false);
4548 if (QDF_STATUS_SUCCESS != status) {
4549 hdd_err("Failed to trigger bug report");
4550 return -EINVAL;
4551 }
4552 } else {
4553 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4554 WLAN_LOG_INDICATOR_FRAMEWORK,
4555 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004556 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 return 0;
4558}
4559
4560/**
4561 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4562 * @wiphy: WIPHY structure pointer
4563 * @wdev: Wireless device structure pointer
4564 * @data: Pointer to the data received
4565 * @data_len: Length of the data received
4566 *
4567 * This function is used to flush or retrieve the per packet statistics from
4568 * the driver
4569 *
4570 * Return: 0 on success and errno on failure
4571 */
4572static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4573 struct wireless_dev *wdev,
4574 const void *data,
4575 int data_len)
4576{
4577 int ret = 0;
4578
4579 cds_ssr_protect(__func__);
4580 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4581 wdev, data, data_len);
4582 cds_ssr_unprotect(__func__);
4583
4584 return ret;
4585}
4586
4587#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4588/**
4589 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4590 * @hdd_ctx: HDD context
4591 * @request_id: [input] request id
4592 * @pattern_id: [output] pattern id
4593 *
4594 * This function loops through request id to pattern id array
4595 * if the slot is available, store the request id and return pattern id
4596 * if entry exists, return the pattern id
4597 *
4598 * Return: 0 on success and errno on failure
4599 */
4600static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4601 uint32_t request_id,
4602 uint8_t *pattern_id)
4603{
4604 uint32_t i;
4605
4606 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4607 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4608 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4609 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4610 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4611 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4612 return 0;
4613 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4614 request_id) {
4615 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4616 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4617 return 0;
4618 }
4619 }
4620 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4621 return -EINVAL;
4622}
4623
4624/**
4625 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4626 * @hdd_ctx: HDD context
4627 * @request_id: [input] request id
4628 * @pattern_id: [output] pattern id
4629 *
4630 * This function loops through request id to pattern id array
4631 * reset request id to 0 (slot available again) and
4632 * return pattern id
4633 *
4634 * Return: 0 on success and errno on failure
4635 */
4636static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4637 uint32_t request_id,
4638 uint8_t *pattern_id)
4639{
4640 uint32_t i;
4641
4642 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4643 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4644 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4645 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4646 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4647 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4648 return 0;
4649 }
4650 }
4651 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4652 return -EINVAL;
4653}
4654
4655
4656/*
4657 * define short names for the global vendor params
4658 * used by __wlan_hdd_cfg80211_offloaded_packets()
4659 */
4660#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4661#define PARAM_REQUEST_ID \
4662 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4663#define PARAM_CONTROL \
4664 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4665#define PARAM_IP_PACKET \
4666 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4667#define PARAM_SRC_MAC_ADDR \
4668 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4669#define PARAM_DST_MAC_ADDR \
4670 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4671#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4672
4673/**
4674 * wlan_hdd_add_tx_ptrn() - add tx pattern
4675 * @adapter: adapter pointer
4676 * @hdd_ctx: hdd context
4677 * @tb: nl attributes
4678 *
4679 * This function reads the NL attributes and forms a AddTxPtrn message
4680 * posts it to SME.
4681 *
4682 */
4683static int
4684wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4685 struct nlattr **tb)
4686{
4687 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304688 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689 uint32_t request_id, ret, len;
4690 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304691 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 uint16_t eth_type = htons(ETH_P_IP);
4693
4694 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004695 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 return -ENOTSUPP;
4697 }
4698
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304699 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004701 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004702 return -ENOMEM;
4703 }
4704
4705 /* Parse and fetch request Id */
4706 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004707 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708 goto fail;
4709 }
4710
4711 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4712 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004713 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714 return -EINVAL;
4715 }
Jeff Johnson77848112016-06-29 14:52:06 -07004716 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717
4718 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004719 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 goto fail;
4721 }
4722 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004723 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004725 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 goto fail;
4727 }
4728
4729 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004730 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004731 goto fail;
4732 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004733 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304734 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004735 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004736 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004737
Anurag Chouhanc5548422016-02-24 18:33:27 +05304738 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004739 &adapter->macAddressCurrent)) {
4740 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741 goto fail;
4742 }
4743
4744 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004745 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 goto fail;
4747 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304748 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004749 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750 MAC_ADDR_ARRAY(dst_addr.bytes));
4751
4752 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004753 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 goto fail;
4755 }
4756 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004757 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758
4759 if (add_req->ucPtrnSize < 0 ||
4760 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4761 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004762 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004763 add_req->ucPtrnSize);
4764 goto fail;
4765 }
4766
4767 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304768 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304769 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304770 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304771 QDF_MAC_ADDR_SIZE);
4772 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304773 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004774 len += 2;
4775
4776 /*
4777 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4778 * ------------------------------------------------------------
4779 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4780 * ------------------------------------------------------------
4781 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304782 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004783 nla_data(tb[PARAM_IP_PACKET]),
4784 add_req->ucPtrnSize);
4785 add_req->ucPtrnSize += len;
4786
4787 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4788 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004789 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004790 goto fail;
4791 }
4792 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004793 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794
4795 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304796 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004797 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 goto fail;
4799 }
4800
4801 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304802 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803 return 0;
4804
4805fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304806 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 return -EINVAL;
4808}
4809
4810/**
4811 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4812 * @adapter: adapter pointer
4813 * @hdd_ctx: hdd context
4814 * @tb: nl attributes
4815 *
4816 * This function reads the NL attributes and forms a DelTxPtrn message
4817 * posts it to SME.
4818 *
4819 */
4820static int
4821wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4822 struct nlattr **tb)
4823{
4824 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304825 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826 uint32_t request_id, ret;
4827 uint8_t pattern_id = 0;
4828
4829 /* Parse and fetch request Id */
4830 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004831 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832 return -EINVAL;
4833 }
4834 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4835 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004836 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 return -EINVAL;
4838 }
4839
4840 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4841 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004842 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 return -EINVAL;
4844 }
4845
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304846 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004847 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004848 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 return -ENOMEM;
4850 }
4851
Anurag Chouhanc5548422016-02-24 18:33:27 +05304852 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004853 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004855 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004856 request_id, del_req->ucPtrnId);
4857
4858 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304859 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004860 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861 goto fail;
4862 }
4863
4864 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304865 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 return 0;
4867
4868fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304869 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 return -EINVAL;
4871}
4872
4873
4874/**
4875 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4876 * @wiphy: Pointer to wireless phy
4877 * @wdev: Pointer to wireless device
4878 * @data: Pointer to data
4879 * @data_len: Data length
4880 *
4881 * Return: 0 on success, negative errno on failure
4882 */
4883static int
4884__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4885 struct wireless_dev *wdev,
4886 const void *data,
4887 int data_len)
4888{
4889 struct net_device *dev = wdev->netdev;
4890 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4891 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4892 struct nlattr *tb[PARAM_MAX + 1];
4893 uint8_t control;
4894 int ret;
4895 static const struct nla_policy policy[PARAM_MAX + 1] = {
4896 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4897 [PARAM_CONTROL] = { .type = NLA_U32 },
4898 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304899 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304901 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004902 [PARAM_PERIOD] = { .type = NLA_U32 },
4903 };
4904
Jeff Johnson1f61b612016-02-12 16:28:33 -08004905 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906
Anurag Chouhan6d760662016-02-20 16:05:43 +05304907 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908 hdd_err("Command not allowed in FTM mode");
4909 return -EPERM;
4910 }
4911
4912 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304913 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004915
4916 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004917 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 return -ENOTSUPP;
4919 }
4920
4921 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004922 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004923 return -EINVAL;
4924 }
4925
4926 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004927 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 return -EINVAL;
4929 }
4930 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004931 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932
4933 if (control == WLAN_START_OFFLOADED_PACKETS)
4934 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4935 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4936 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4937 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004938 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939 return -EINVAL;
4940 }
4941}
4942
4943/*
4944 * done with short names for the global vendor params
4945 * used by __wlan_hdd_cfg80211_offloaded_packets()
4946 */
4947#undef PARAM_MAX
4948#undef PARAM_REQUEST_ID
4949#undef PARAM_CONTROL
4950#undef PARAM_IP_PACKET
4951#undef PARAM_SRC_MAC_ADDR
4952#undef PARAM_DST_MAC_ADDR
4953#undef PARAM_PERIOD
4954
4955/**
4956 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4957 * @wiphy: wiphy structure pointer
4958 * @wdev: Wireless device structure pointer
4959 * @data: Pointer to the data received
4960 * @data_len: Length of @data
4961 *
4962 * Return: 0 on success; errno on failure
4963 */
4964static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4965 struct wireless_dev *wdev,
4966 const void *data,
4967 int data_len)
4968{
4969 int ret = 0;
4970
4971 cds_ssr_protect(__func__);
4972 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4973 wdev, data, data_len);
4974 cds_ssr_unprotect(__func__);
4975
4976 return ret;
4977}
4978#endif
4979
4980/*
4981 * define short names for the global vendor params
4982 * used by __wlan_hdd_cfg80211_monitor_rssi()
4983 */
4984#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4985#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4986#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4987#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4988#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4989
4990/**
4991 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4992 * @wiphy: Pointer to wireless phy
4993 * @wdev: Pointer to wireless device
4994 * @data: Pointer to data
4995 * @data_len: Data length
4996 *
4997 * Return: 0 on success, negative errno on failure
4998 */
4999static int
5000__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5001 struct wireless_dev *wdev,
5002 const void *data,
5003 int data_len)
5004{
5005 struct net_device *dev = wdev->netdev;
5006 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5007 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5008 struct nlattr *tb[PARAM_MAX + 1];
5009 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305010 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 int ret;
5012 uint32_t control;
5013 static const struct nla_policy policy[PARAM_MAX + 1] = {
5014 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5015 [PARAM_CONTROL] = { .type = NLA_U32 },
5016 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5017 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5018 };
5019
Jeff Johnson1f61b612016-02-12 16:28:33 -08005020 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305022 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5023 hdd_err("invalid session id: %d", adapter->sessionId);
5024 return -EINVAL;
5025 }
5026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305028 if (ret)
5029 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030
5031 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005032 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033 return -ENOTSUPP;
5034 }
5035
5036 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005037 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038 return -EINVAL;
5039 }
5040
5041 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005042 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005043 return -EINVAL;
5044 }
5045
5046 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005047 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 return -EINVAL;
5049 }
5050
5051 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5052 req.session_id = adapter->sessionId;
5053 control = nla_get_u32(tb[PARAM_CONTROL]);
5054
5055 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5056 req.control = true;
5057 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005058 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 return -EINVAL;
5060 }
5061
5062 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005063 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 return -EINVAL;
5065 }
5066
5067 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5068 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5069
5070 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005071 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072 req.min_rssi, req.max_rssi);
5073 return -EINVAL;
5074 }
Jeff Johnson77848112016-06-29 14:52:06 -07005075 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005076 req.min_rssi, req.max_rssi);
5077
5078 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5079 req.control = false;
5080 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005081 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005082 return -EINVAL;
5083 }
Jeff Johnson77848112016-06-29 14:52:06 -07005084 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005085 req.request_id, req.session_id, req.control);
5086
5087 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305088 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005089 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005090 return -EINVAL;
5091 }
5092
5093 return 0;
5094}
5095
5096/*
5097 * done with short names for the global vendor params
5098 * used by __wlan_hdd_cfg80211_monitor_rssi()
5099 */
5100#undef PARAM_MAX
5101#undef PARAM_CONTROL
5102#undef PARAM_REQUEST_ID
5103#undef PARAM_MAX_RSSI
5104#undef PARAM_MIN_RSSI
5105
5106/**
5107 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5108 * @wiphy: wiphy structure pointer
5109 * @wdev: Wireless device structure pointer
5110 * @data: Pointer to the data received
5111 * @data_len: Length of @data
5112 *
5113 * Return: 0 on success; errno on failure
5114 */
5115static int
5116wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5117 const void *data, int data_len)
5118{
5119 int ret;
5120
5121 cds_ssr_protect(__func__);
5122 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5123 cds_ssr_unprotect(__func__);
5124
5125 return ret;
5126}
5127
5128/**
5129 * hdd_rssi_threshold_breached() - rssi breached NL event
5130 * @hddctx: HDD context
5131 * @data: rssi breached event data
5132 *
5133 * This function reads the rssi breached event %data and fill in the skb with
5134 * NL attributes and send up the NL event.
5135 *
5136 * Return: none
5137 */
5138void hdd_rssi_threshold_breached(void *hddctx,
5139 struct rssi_breach_event *data)
5140{
5141 hdd_context_t *hdd_ctx = hddctx;
5142 struct sk_buff *skb;
5143
5144 ENTER();
5145
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305146 if (wlan_hdd_validate_context(hdd_ctx))
5147 return;
5148 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005149 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 return;
5151 }
5152
5153 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5154 NULL,
5155 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5156 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5157 GFP_KERNEL);
5158
5159 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005160 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005161 return;
5162 }
5163
Jeff Johnson77848112016-06-29 14:52:06 -07005164 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005166 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005167 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5168
5169 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5170 data->request_id) ||
5171 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5172 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5173 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5174 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005175 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005176 goto fail;
5177 }
5178
5179 cfg80211_vendor_event(skb, GFP_KERNEL);
5180 return;
5181
5182fail:
5183 kfree_skb(skb);
5184 return;
5185}
5186
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305187static const struct nla_policy
5188ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5189 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5190};
5191
5192/**
5193 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5194 * @wiphy: Pointer to wireless phy
5195 * @wdev: Pointer to wireless device
5196 * @data: Pointer to data
5197 * @data_len: Length of @data
5198 *
5199 * Return: 0 on success, negative errno on failure
5200 */
5201static int
5202__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5203 struct wireless_dev *wdev,
5204 const void *data, int data_len)
5205{
5206 int status;
5207 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5208 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005209 struct net_device *dev = wdev->netdev;
5210 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305211
5212 ENTER_DEV(wdev->netdev);
5213
5214 status = wlan_hdd_validate_context(pHddCtx);
5215 if (0 != status)
5216 return status;
5217 if (!pHddCtx->config->fhostNSOffload) {
5218 hdd_err("ND Offload not supported");
5219 return -EINVAL;
5220 }
5221
5222 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5223 (struct nlattr *)data,
5224 data_len, ns_offload_set_policy)) {
5225 hdd_err("nla_parse failed");
5226 return -EINVAL;
5227 }
5228
5229 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5230 hdd_err("ND Offload flag attribute not present");
5231 return -EINVAL;
5232 }
5233
5234 pHddCtx->ns_offload_enable =
5235 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5236
Dustin Brownd8279d22016-09-07 14:52:57 -07005237 /* update ns offload in case it is already enabled/disabled */
5238 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5239
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305240 return 0;
5241}
5242
5243/**
5244 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5245 * @wiphy: pointer to wireless wiphy structure.
5246 * @wdev: pointer to wireless_dev structure.
5247 * @data: Pointer to the data to be passed via vendor interface
5248 * @data_len:Length of the data to be passed
5249 *
5250 * Return: Return the Success or Failure code.
5251 */
5252static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5253 struct wireless_dev *wdev,
5254 const void *data, int data_len)
5255{
5256 int ret;
5257
5258 cds_ssr_protect(__func__);
5259 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5260 cds_ssr_unprotect(__func__);
5261
5262 return ret;
5263}
5264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5266 * @wiphy: Pointer to wireless phy
5267 * @wdev: Pointer to wireless device
5268 * @data: Pointer to data
5269 * @data_len: Data length
5270 *
5271 * This function return the preferred frequency list generated by the policy
5272 * manager.
5273 *
5274 * Return: success or failure code
5275 */
5276static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5277 struct wireless_dev
5278 *wdev, const void *data,
5279 int data_len)
5280{
5281 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5282 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305283 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305284 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305286 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287 enum cds_con_mode intf_mode;
5288 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5289 struct sk_buff *reply_skb;
5290
Jeff Johnson1f61b612016-02-12 16:28:33 -08005291 ENTER_DEV(wdev->netdev);
5292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 ret = wlan_hdd_validate_context(hdd_ctx);
5294 if (ret)
5295 return -EINVAL;
5296
5297 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5298 data, data_len, NULL)) {
5299 hdd_err("Invalid ATTR");
5300 return -EINVAL;
5301 }
5302
5303 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5304 hdd_err("attr interface type failed");
5305 return -EINVAL;
5306 }
5307
5308 intf_mode = nla_get_u32(tb
5309 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5310
5311 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5312 hdd_err("Invalid interface type");
5313 return -EINVAL;
5314 }
5315
5316 hdd_debug("Userspace requested pref freq list");
5317
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305318 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5319 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305320 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 hdd_err("Get pcl failed");
5322 return -EINVAL;
5323 }
5324
5325 /* convert channel number to frequency */
5326 for (i = 0; i < pcl_len; i++) {
5327 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5328 freq_list[i] =
5329 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005330 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005331 else
5332 freq_list[i] =
5333 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005334 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335 }
5336
5337 /* send the freq_list back to supplicant */
5338 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5339 sizeof(u32) *
5340 pcl_len +
5341 NLMSG_HDRLEN);
5342
5343 if (!reply_skb) {
5344 hdd_err("Allocate reply_skb failed");
5345 return -EINVAL;
5346 }
5347
5348 if (nla_put_u32(reply_skb,
5349 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5350 intf_mode) ||
5351 nla_put(reply_skb,
5352 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5353 sizeof(uint32_t) * pcl_len,
5354 freq_list)) {
5355 hdd_err("nla put fail");
5356 kfree_skb(reply_skb);
5357 return -EINVAL;
5358 }
5359
5360 return cfg80211_vendor_cmd_reply(reply_skb);
5361}
5362
5363/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5364 * @wiphy: Pointer to wireless phy
5365 * @wdev: Pointer to wireless device
5366 * @data: Pointer to data
5367 * @data_len: Data length
5368 *
5369 * This function return the preferred frequency list generated by the policy
5370 * manager.
5371 *
5372 * Return: success or failure code
5373 */
5374static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5375 struct wireless_dev
5376 *wdev, const void *data,
5377 int data_len)
5378{
5379 int ret = 0;
5380
5381 cds_ssr_protect(__func__);
5382 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5383 data, data_len);
5384 cds_ssr_unprotect(__func__);
5385
5386 return ret;
5387}
5388
5389/**
5390 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5391 * @wiphy: Pointer to wireless phy
5392 * @wdev: Pointer to wireless device
5393 * @data: Pointer to data
5394 * @data_len: Data length
5395 *
5396 * Return: 0 on success, negative errno on failure
5397 */
5398static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5399 struct wireless_dev *wdev,
5400 const void *data,
5401 int data_len)
5402{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305403 struct net_device *ndev = wdev->netdev;
5404 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5406 int ret = 0;
5407 enum cds_con_mode intf_mode;
5408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5409 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410
Jeff Johnson1f61b612016-02-12 16:28:33 -08005411 ENTER_DEV(ndev);
5412
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 ret = wlan_hdd_validate_context(hdd_ctx);
5414 if (ret)
5415 return ret;
5416
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5418 data, data_len, NULL)) {
5419 hdd_err("Invalid ATTR");
5420 return -EINVAL;
5421 }
5422
5423 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5424 hdd_err("attr interface type failed");
5425 return -EINVAL;
5426 }
5427
5428 intf_mode = nla_get_u32(tb
5429 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5430
5431 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5432 hdd_err("Invalid interface type");
5433 return -EINVAL;
5434 }
5435
5436 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5437 hdd_err("attr probable freq failed");
5438 return -EINVAL;
5439 }
5440
5441 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5442 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5443
5444 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005445 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 channel_hint, HW_MODE_20_MHZ)) {
5447 hdd_err("Set channel hint failed due to concurrency check");
5448 return -EINVAL;
5449 }
5450
Krunal Soni09e55032016-06-07 10:06:55 -07005451 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5452 hdd_warn("Remain On Channel Pending");
5453
Krunal Soni3091bcc2016-06-23 12:28:21 -07005454 ret = qdf_reset_connection_update();
5455 if (!QDF_IS_STATUS_SUCCESS(ret))
5456 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005457
Krunal Soni3091bcc2016-06-23 12:28:21 -07005458 ret = cds_current_connections_update(adapter->sessionId,
5459 channel_hint,
5460 SIR_UPDATE_REASON_SET_OPER_CHAN);
5461 if (QDF_STATUS_E_FAILURE == ret) {
5462 /* return in the failure case */
5463 hdd_err("ERROR: connections update failed!!");
5464 return -EINVAL;
5465 }
5466
5467 if (QDF_STATUS_SUCCESS == ret) {
5468 /*
5469 * Success is the only case for which we expect hw mode
5470 * change to take place, hence we need to wait.
5471 * For any other return value it should be a pass
5472 * through
5473 */
5474 ret = qdf_wait_for_connection_update();
5475 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5476 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 return -EINVAL;
5478 }
5479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005480 }
5481
5482 return 0;
5483}
5484
5485/**
5486 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5487 * @wiphy: Pointer to wireless phy
5488 * @wdev: Pointer to wireless device
5489 * @data: Pointer to data
5490 * @data_len: Data length
5491 *
5492 * Return: 0 on success, negative errno on failure
5493 */
5494static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5495 struct wireless_dev *wdev,
5496 const void *data,
5497 int data_len)
5498{
5499 int ret = 0;
5500
5501 cds_ssr_protect(__func__);
5502 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5503 data, data_len);
5504 cds_ssr_unprotect(__func__);
5505
5506 return ret;
5507}
5508
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305509static const struct
5510nla_policy
5511qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5512 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5513};
5514
5515/**
5516 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5517 * @wiphy: WIPHY structure pointer
5518 * @wdev: Wireless device structure pointer
5519 * @data: Pointer to the data received
5520 * @data_len: Length of the data received
5521 *
5522 * This function is used to get link properties like nss, rate flags and
5523 * operating frequency for the active connection with the given peer.
5524 *
5525 * Return: 0 on success and errno on failure
5526 */
5527static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5528 struct wireless_dev *wdev,
5529 const void *data,
5530 int data_len)
5531{
5532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5533 struct net_device *dev = wdev->netdev;
5534 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5535 hdd_station_ctx_t *hdd_sta_ctx;
5536 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305537 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305538 uint32_t sta_id;
5539 struct sk_buff *reply_skb;
5540 uint32_t rate_flags = 0;
5541 uint8_t nss;
5542 uint8_t final_rate_flags = 0;
5543 uint32_t freq;
5544
Jeff Johnson1f61b612016-02-12 16:28:33 -08005545 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305546
Anurag Chouhan6d760662016-02-20 16:05:43 +05305547 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305548 hdd_err("Command not allowed in FTM mode");
5549 return -EPERM;
5550 }
5551
5552 if (0 != wlan_hdd_validate_context(hdd_ctx))
5553 return -EINVAL;
5554
5555 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5556 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005557 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305558 return -EINVAL;
5559 }
5560
5561 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005562 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305563 adapter->device_mode);
5564 return -EINVAL;
5565 }
5566
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305567 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305568 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005569 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305570 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5571
Krunal Sonib4326f22016-03-10 13:05:51 -08005572 if (adapter->device_mode == QDF_STA_MODE ||
5573 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305574 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5575 if ((hdd_sta_ctx->conn_info.connState !=
5576 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305577 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305578 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005579 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305580 MAC_ADDR_ARRAY(peer_mac));
5581 return -EINVAL;
5582 }
5583
5584 nss = hdd_sta_ctx->conn_info.nss;
5585 freq = cds_chan_to_freq(
5586 hdd_sta_ctx->conn_info.operationChannel);
5587 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005588 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5589 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305590
5591 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5592 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305593 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305594 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305595 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305596 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305597 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305598 break;
5599 }
5600
5601 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005602 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305603 MAC_ADDR_ARRAY(peer_mac));
5604 return -EINVAL;
5605 }
5606
5607 nss = adapter->aStaInfo[sta_id].nss;
5608 freq = cds_chan_to_freq(
5609 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5610 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5611 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005612 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305613 MAC_ADDR_ARRAY(peer_mac));
5614 return -EINVAL;
5615 }
5616
5617 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5618 if (rate_flags & eHAL_TX_RATE_VHT80) {
5619 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005620#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305621 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005622#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305623 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5624 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005625#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305626 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005627#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305628 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5629 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5630 } else if (rate_flags &
5631 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5632 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005633#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305634 if (rate_flags & eHAL_TX_RATE_HT40)
5635 final_rate_flags |=
5636 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005637#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305638 }
5639
5640 if (rate_flags & eHAL_TX_RATE_SGI) {
5641 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5642 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5643 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5644 }
5645 }
5646
5647 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5648 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5649
5650 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005651 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305652 return -EINVAL;
5653 }
5654
5655 if (nla_put_u8(reply_skb,
5656 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5657 nss) ||
5658 nla_put_u8(reply_skb,
5659 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5660 final_rate_flags) ||
5661 nla_put_u32(reply_skb,
5662 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5663 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005664 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305665 kfree_skb(reply_skb);
5666 return -EINVAL;
5667 }
5668
5669 return cfg80211_vendor_cmd_reply(reply_skb);
5670}
5671
5672/**
5673 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5674 * properties.
5675 * @wiphy: WIPHY structure pointer
5676 * @wdev: Wireless device structure pointer
5677 * @data: Pointer to the data received
5678 * @data_len: Length of the data received
5679 *
5680 * This function is used to get link properties like nss, rate flags and
5681 * operating frequency for the active connection with the given peer.
5682 *
5683 * Return: 0 on success and errno on failure
5684 */
5685static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5686 struct wireless_dev *wdev,
5687 const void *data,
5688 int data_len)
5689{
5690 int ret = 0;
5691
5692 cds_ssr_protect(__func__);
5693 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5694 wdev, data, data_len);
5695 cds_ssr_unprotect(__func__);
5696
5697 return ret;
5698}
5699
Peng Xu278d0122015-09-24 16:34:17 -07005700static const struct
5701nla_policy
5702qca_wlan_vendor_ota_test_policy
5703[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5704 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5705};
5706
5707/**
5708 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5709 * @wiphy: Pointer to wireless phy
5710 * @wdev: Pointer to wireless device
5711 * @data: Pointer to data
5712 * @data_len: Data length
5713 *
5714 * Return: 0 on success, negative errno on failure
5715 */
5716static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5717 struct wireless_dev *wdev,
5718 const void *data,
5719 int data_len)
5720{
5721 struct net_device *dev = wdev->netdev;
5722 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5723 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5724 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5725 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5726 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305727 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005728 uint32_t current_roam_state;
5729
Jeff Johnson1f61b612016-02-12 16:28:33 -08005730 ENTER_DEV(dev);
5731
Anurag Chouhan6d760662016-02-20 16:05:43 +05305732 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005733 hdd_err("Command not allowed in FTM mode");
5734 return -EPERM;
5735 }
5736
5737 if (0 != wlan_hdd_validate_context(hdd_ctx))
5738 return -EINVAL;
5739
5740 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5741 data, data_len,
5742 qca_wlan_vendor_ota_test_policy)) {
5743 hdd_err("invalid attr");
5744 return -EINVAL;
5745 }
5746
5747 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5748 hdd_err("attr ota test failed");
5749 return -EINVAL;
5750 }
5751
5752 ota_enable = nla_get_u8(
5753 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5754
5755 hdd_info(" OTA test enable = %d", ota_enable);
5756 if (ota_enable != 1) {
5757 hdd_err("Invalid value, only enable test mode is supported!");
5758 return -EINVAL;
5759 }
5760
5761 current_roam_state =
5762 sme_get_current_roam_state(hal, adapter->sessionId);
5763 status = sme_stop_roaming(hal, adapter->sessionId,
5764 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305765 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005766 hdd_err("Enable/Disable roaming failed");
5767 return -EINVAL;
5768 }
5769
5770 status = sme_ps_enable_disable(hal, adapter->sessionId,
5771 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305772 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005773 hdd_err("Enable/Disable power save failed");
5774 /* restore previous roaming setting */
5775 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5776 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5777 status = sme_start_roaming(hal, adapter->sessionId,
5778 eCsrHddIssued);
5779 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5780 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5781 status = sme_stop_roaming(hal, adapter->sessionId,
5782 eCsrHddIssued);
5783
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305784 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005785 hdd_err("Restoring roaming state failed");
5786
5787 return -EINVAL;
5788 }
5789
5790
5791 return 0;
5792}
5793
5794/**
5795 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5796 * @wiphy: Pointer to wireless phy
5797 * @wdev: Pointer to wireless device
5798 * @data: Pointer to data
5799 * @data_len: Data length
5800 *
5801 * Return: 0 on success, negative errno on failure
5802 */
5803static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5804 struct wireless_dev *wdev,
5805 const void *data,
5806 int data_len)
5807{
5808 int ret = 0;
5809
5810 cds_ssr_protect(__func__);
5811 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5812 cds_ssr_unprotect(__func__);
5813
5814 return ret;
5815}
5816
Peng Xu4d67c8f2015-10-16 16:02:26 -07005817/**
5818 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5819 * @wiphy: Pointer to wireless phy
5820 * @wdev: Pointer to wireless device
5821 * @data: Pointer to data
5822 * @data_len: Data length
5823 *
5824 * Return: 0 on success, negative errno on failure
5825 */
5826static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5827 struct wireless_dev *wdev,
5828 const void *data,
5829 int data_len)
5830{
5831 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5832 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005833 hdd_adapter_t *adapter;
5834 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005835 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5836 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005837 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005838
Jeff Johnson1f61b612016-02-12 16:28:33 -08005839 ENTER_DEV(dev);
5840
Peng Xu4d67c8f2015-10-16 16:02:26 -07005841 ret = wlan_hdd_validate_context(hdd_ctx);
5842 if (ret)
5843 return ret;
5844
5845 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5846
5847 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5848 data, data_len, NULL)) {
5849 hdd_err("Invalid ATTR");
5850 return -EINVAL;
5851 }
5852
5853 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5854 hdd_err("attr tx power scale failed");
5855 return -EINVAL;
5856 }
5857
5858 scale_value = nla_get_u8(tb
5859 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5860
5861 if (scale_value > MAX_TXPOWER_SCALE) {
5862 hdd_err("Invalid tx power scale level");
5863 return -EINVAL;
5864 }
5865
Peng Xu62c8c432016-05-09 15:23:02 -07005866 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005867
Peng Xu62c8c432016-05-09 15:23:02 -07005868 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005869 hdd_err("Set tx power scale failed");
5870 return -EINVAL;
5871 }
5872
5873 return 0;
5874}
5875
5876/**
5877 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5878 * @wiphy: Pointer to wireless phy
5879 * @wdev: Pointer to wireless device
5880 * @data: Pointer to data
5881 * @data_len: Data length
5882 *
5883 * Return: 0 on success, negative errno on failure
5884 */
5885static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5886 struct wireless_dev *wdev,
5887 const void *data,
5888 int data_len)
5889{
Peng Xu62c8c432016-05-09 15:23:02 -07005890 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005891
5892 cds_ssr_protect(__func__);
5893 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5894 data, data_len);
5895 cds_ssr_unprotect(__func__);
5896
5897 return ret;
5898}
5899
5900/**
5901 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5902 * @wiphy: Pointer to wireless phy
5903 * @wdev: Pointer to wireless device
5904 * @data: Pointer to data
5905 * @data_len: Data length
5906 *
5907 * Return: 0 on success, negative errno on failure
5908 */
5909static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5910 struct wireless_dev *wdev,
5911 const void *data,
5912 int data_len)
5913{
5914 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5915 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005916 hdd_adapter_t *adapter;
5917 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005918 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5919 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005920 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005921
Jeff Johnson1f61b612016-02-12 16:28:33 -08005922 ENTER_DEV(dev);
5923
Peng Xu4d67c8f2015-10-16 16:02:26 -07005924 ret = wlan_hdd_validate_context(hdd_ctx);
5925 if (ret)
5926 return ret;
5927
5928 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5929
5930 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5931 data, data_len, NULL)) {
5932 hdd_err("Invalid ATTR");
5933 return -EINVAL;
5934 }
5935
5936 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5937 hdd_err("attr tx power decrease db value failed");
5938 return -EINVAL;
5939 }
5940
5941 scale_value = nla_get_u8(tb
5942 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5943
Peng Xu62c8c432016-05-09 15:23:02 -07005944 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5945 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005946
Peng Xu62c8c432016-05-09 15:23:02 -07005947 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005948 hdd_err("Set tx power decrease db failed");
5949 return -EINVAL;
5950 }
5951
5952 return 0;
5953}
5954
5955/**
5956 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5957 * @wiphy: Pointer to wireless phy
5958 * @wdev: Pointer to wireless device
5959 * @data: Pointer to data
5960 * @data_len: Data length
5961 *
5962 * Return: 0 on success, negative errno on failure
5963 */
5964static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5965 struct wireless_dev *wdev,
5966 const void *data,
5967 int data_len)
5968{
Peng Xu62c8c432016-05-09 15:23:02 -07005969 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005970
5971 cds_ssr_protect(__func__);
5972 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5973 data, data_len);
5974 cds_ssr_unprotect(__func__);
5975
5976 return ret;
5977}
Peng Xu8fdaa492016-06-22 10:20:47 -07005978
5979/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305980 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5981 * @wiphy: Pointer to wireless phy
5982 * @wdev: Pointer to wireless device
5983 * @data: Pointer to data
5984 * @data_len: Data length
5985 *
5986 * Processes the conditional channel switch request and invokes the helper
5987 * APIs to process the channel switch request.
5988 *
5989 * Return: 0 on success, negative errno on failure
5990 */
5991static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5992 struct wireless_dev *wdev,
5993 const void *data,
5994 int data_len)
5995{
5996 int ret;
5997 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5998 struct net_device *dev = wdev->netdev;
5999 hdd_adapter_t *adapter;
6000 struct nlattr
6001 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6002 uint32_t freq_len, i;
6003 uint32_t *freq;
6004 uint8_t chans[QDF_MAX_NUM_CHAN];
6005
6006 ENTER_DEV(dev);
6007
6008 ret = wlan_hdd_validate_context(hdd_ctx);
6009 if (ret)
6010 return ret;
6011
6012 if (!hdd_ctx->config->enableDFSMasterCap) {
6013 hdd_err("DFS master capability is not present in the driver");
6014 return -EINVAL;
6015 }
6016
6017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6018 hdd_err("Command not allowed in FTM mode");
6019 return -EPERM;
6020 }
6021
6022 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6023 if (adapter->device_mode != QDF_SAP_MODE) {
6024 hdd_err("Invalid device mode %d", adapter->device_mode);
6025 return -EINVAL;
6026 }
6027
6028 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6029 data, data_len, NULL)) {
6030 hdd_err("Invalid ATTR");
6031 return -EINVAL;
6032 }
6033
6034 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6035 hdd_err("Frequency list is missing");
6036 return -EINVAL;
6037 }
6038
6039 freq_len = nla_len(
6040 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6041 sizeof(uint32_t);
6042
6043 if (freq_len > QDF_MAX_NUM_CHAN) {
6044 hdd_err("insufficient space to hold channels");
6045 return -ENOMEM;
6046 }
6047
6048 hdd_debug("freq_len=%d", freq_len);
6049
6050 freq = nla_data(
6051 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6052
6053
6054 for (i = 0; i < freq_len; i++) {
6055 if (freq[i] == 0)
6056 chans[i] = 0;
6057 else
6058 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6059
6060 hdd_debug("freq[%d]=%d", i, freq[i]);
6061 }
6062
6063 /*
6064 * The input frequency list from user space is designed to be a
6065 * priority based frequency list. This is only to accommodate any
6066 * future request. But, current requirement is only to perform CAC
6067 * on a single channel. So, the first entry from the list is picked.
6068 *
6069 * If channel is zero, any channel in the available outdoor regulatory
6070 * domain will be selected.
6071 */
6072 ret = wlan_hdd_request_pre_cac(chans[0]);
6073 if (ret) {
6074 hdd_err("pre cac request failed with reason:%d", ret);
6075 return ret;
6076 }
6077
6078 return 0;
6079}
6080
6081/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006082 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6083 * @wiphy: Pointer to wireless phy
6084 * @wdev: Pointer to wireless device
6085 * @data: Pointer to data
6086 * @data_len: Data length
6087 *
6088 * This function is to process the p2p listen offload start vendor
6089 * command. It parses the input parameters and invoke WMA API to
6090 * send the command to firmware.
6091 *
6092 * Return: 0 on success, negative errno on failure
6093 */
6094static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6095 struct wireless_dev *wdev,
6096 const void *data,
6097 int data_len)
6098{
6099 int ret;
6100 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6101 struct net_device *dev = wdev->netdev;
6102 hdd_adapter_t *adapter;
6103 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6104 struct sir_p2p_lo_start params;
6105 QDF_STATUS status;
6106
6107 ENTER_DEV(dev);
6108
6109 ret = wlan_hdd_validate_context(hdd_ctx);
6110 if (ret)
6111 return ret;
6112
6113 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6114 hdd_err("Command not allowed in FTM mode");
6115 return -EPERM;
6116 }
6117
6118 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6119 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6120 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6121 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6122 hdd_err("Invalid device mode %d", adapter->device_mode);
6123 return -EINVAL;
6124 }
6125
6126 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6127 data, data_len, NULL)) {
6128 hdd_err("Invalid ATTR");
6129 return -EINVAL;
6130 }
6131
6132 memset(&params, 0, sizeof(params));
6133
6134 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6135 params.ctl_flags = 1; /* set to default value */
6136 else
6137 params.ctl_flags = nla_get_u32(tb
6138 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6139
6140 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6141 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6142 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6143 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6144 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6145 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6146 hdd_err("Attribute parsing failed");
6147 return -EINVAL;
6148 }
6149
6150 params.vdev_id = adapter->sessionId;
6151 params.freq = nla_get_u32(tb
6152 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6153 if ((params.freq != 2412) && (params.freq != 2437) &&
6154 (params.freq != 2462)) {
6155 hdd_err("Invalid listening channel: %d", params.freq);
6156 return -EINVAL;
6157 }
6158
6159 params.period = nla_get_u32(tb
6160 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6161 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6162 hdd_err("Invalid period: %d", params.period);
6163 return -EINVAL;
6164 }
6165
6166 params.interval = nla_get_u32(tb
6167 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6168 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6169 hdd_err("Invalid interval: %d", params.interval);
6170 return -EINVAL;
6171 }
6172
6173 params.count = nla_get_u32(tb
6174 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006175 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006176 hdd_err("Invalid count: %d", params.count);
6177 return -EINVAL;
6178 }
6179
6180 params.device_types = nla_data(tb
6181 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6182 if (params.device_types == NULL) {
6183 hdd_err("Invalid device types");
6184 return -EINVAL;
6185 }
6186
6187 params.dev_types_len = nla_len(tb
6188 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6189 if (params.dev_types_len < 8) {
6190 hdd_err("Invalid device type length: %d", params.dev_types_len);
6191 return -EINVAL;
6192 }
6193
6194 params.probe_resp_tmplt = nla_data(tb
6195 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6196 if (params.probe_resp_tmplt == NULL) {
6197 hdd_err("Invalid probe response template");
6198 return -EINVAL;
6199 }
6200
6201 params.probe_resp_len = nla_len(tb
6202 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6203 if (params.probe_resp_len == 0) {
6204 hdd_err("Invalid probe resp template length: %d",
6205 params.probe_resp_len);
6206 return -EINVAL;
6207 }
6208
6209 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6210 params.freq, params.period, params.interval, params.count);
6211
6212 status = wma_p2p_lo_start(&params);
6213
6214 if (!QDF_IS_STATUS_SUCCESS(status)) {
6215 hdd_err("P2P LO start failed");
6216 return -EINVAL;
6217 }
6218
6219 return 0;
6220}
6221
6222
6223/**
6224 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6225 * @wiphy: Pointer to wireless phy
6226 * @wdev: Pointer to wireless device
6227 * @data: Pointer to data
6228 * @data_len: Data length
6229 *
6230 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6231 * to process p2p listen offload start vendor command.
6232 *
6233 * Return: 0 on success, negative errno on failure
6234 */
6235static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6236 struct wireless_dev *wdev,
6237 const void *data,
6238 int data_len)
6239{
6240 int ret = 0;
6241
6242 cds_ssr_protect(__func__);
6243 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6244 data, data_len);
6245 cds_ssr_unprotect(__func__);
6246
6247 return ret;
6248}
6249
6250/**
6251 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6252 * @wiphy: Pointer to wireless phy
6253 * @wdev: Pointer to wireless device
6254 * @data: Pointer to data
6255 * @data_len: Data length
6256 *
6257 * This function is to process the p2p listen offload stop vendor
6258 * command. It invokes WMA API to send command to firmware.
6259 *
6260 * Return: 0 on success, negative errno on failure
6261 */
6262static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6263 struct wireless_dev *wdev,
6264 const void *data,
6265 int data_len)
6266{
6267 QDF_STATUS status;
6268 hdd_adapter_t *adapter;
6269 struct net_device *dev = wdev->netdev;
6270
6271 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6272 hdd_err("Command not allowed in FTM mode");
6273 return -EPERM;
6274 }
6275
6276 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6277 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6278 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6279 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6280 hdd_err("Invalid device mode");
6281 return -EINVAL;
6282 }
6283
6284 status = wma_p2p_lo_stop(adapter->sessionId);
6285
6286 if (!QDF_IS_STATUS_SUCCESS(status)) {
6287 hdd_err("P2P LO stop failed");
6288 return -EINVAL;
6289 }
6290
6291 return 0;
6292}
6293
6294/**
6295 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6296 * @wiphy: Pointer to wireless phy
6297 * @wdev: Pointer to wireless device
6298 * @data: Pointer to data
6299 * @data_len: Data length
6300 *
6301 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6302 * to process p2p listen offload stop vendor command.
6303 *
6304 * Return: 0 on success, negative errno on failure
6305 */
6306static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6307 struct wireless_dev *wdev,
6308 const void *data,
6309 int data_len)
6310{
6311 int ret = 0;
6312
6313 cds_ssr_protect(__func__);
6314 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6315 data, data_len);
6316 cds_ssr_unprotect(__func__);
6317
6318 return ret;
6319}
6320
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306321/**
6322 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6323 * @wiphy: Pointer to wireless phy
6324 * @wdev: Pointer to wireless device
6325 * @data: Pointer to data
6326 * @data_len: Data length
6327 *
6328 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6329 * to process the conditional channel switch request.
6330 *
6331 * Return: 0 on success, negative errno on failure
6332 */
6333static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6334 struct wireless_dev *wdev,
6335 const void *data,
6336 int data_len)
6337{
6338 int ret;
6339
6340 cds_ssr_protect(__func__);
6341 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6342 data, data_len);
6343 cds_ssr_unprotect(__func__);
6344
6345 return ret;
6346}
6347
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306348/*
6349 * define short names for the global vendor params
6350 * used by __wlan_hdd_cfg80211_bpf_offload()
6351 */
6352#define BPF_INVALID \
6353 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6354#define BPF_SET_RESET \
6355 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6356#define BPF_VERSION \
6357 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6358#define BPF_FILTER_ID \
6359 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6360#define BPF_PACKET_SIZE \
6361 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6362#define BPF_CURRENT_OFFSET \
6363 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6364#define BPF_PROGRAM \
6365 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6366#define BPF_MAX \
6367 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006368
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306369static const struct nla_policy
6370wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6371 [BPF_SET_RESET] = {.type = NLA_U32},
6372 [BPF_VERSION] = {.type = NLA_U32},
6373 [BPF_FILTER_ID] = {.type = NLA_U32},
6374 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6375 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6376 [BPF_PROGRAM] = {.type = NLA_U8},
6377};
6378
6379/**
6380 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6381 * @hdd_context: hdd_context
6382 * @bpf_get_offload: struct for get offload
6383 *
6384 * This function receives the response/data from the lower layer and
6385 * checks to see if the thread is still waiting then post the results to
6386 * upper layer, if the request has timed out then ignore.
6387 *
6388 * Return: None
6389 */
6390void hdd_get_bpf_offload_cb(void *hdd_context,
6391 struct sir_bpf_get_offload *data)
6392{
6393 hdd_context_t *hdd_ctx = hdd_context;
6394 struct hdd_bpf_context *context;
6395
6396 ENTER();
6397
6398 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006399 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306400 data);
6401 return;
6402 }
6403
6404 spin_lock(&hdd_context_lock);
6405
6406 context = &bpf_context;
6407 /* The caller presumably timed out so there is nothing we can do */
6408 if (context->magic != BPF_CONTEXT_MAGIC) {
6409 spin_unlock(&hdd_context_lock);
6410 return;
6411 }
6412
6413 /* context is valid so caller is still waiting */
6414 /* paranoia: invalidate the magic */
6415 context->magic = 0;
6416
6417 context->capability_response = *data;
6418 complete(&context->completion);
6419
6420 spin_unlock(&hdd_context_lock);
6421
6422 return;
6423}
6424
6425/**
6426 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6427 * @hdd_context: hdd_context
6428 * @bpf_get_offload: struct for get offload
6429 *
6430 * Return: 0 on success, error number otherwise.
6431 */
6432static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6433 struct sir_bpf_get_offload *bpf_get_offload)
6434{
6435 struct sk_buff *skb;
6436 uint32_t nl_buf_len;
6437
6438 ENTER();
6439
6440 nl_buf_len = NLMSG_HDRLEN;
6441 nl_buf_len +=
6442 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6443 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6444
6445 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6446 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006447 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306448 return -ENOMEM;
6449 }
6450
Jeff Johnson77848112016-06-29 14:52:06 -07006451 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306452 bpf_get_offload->bpf_version,
6453 bpf_get_offload->max_bytes_for_bpf_inst);
6454
6455 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6456 bpf_get_offload->max_bytes_for_bpf_inst) ||
6457 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006458 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306459 goto nla_put_failure;
6460 }
6461
6462 cfg80211_vendor_cmd_reply(skb);
6463 EXIT();
6464 return 0;
6465
6466nla_put_failure:
6467 kfree_skb(skb);
6468 return -EINVAL;
6469}
6470
6471/**
6472 * hdd_get_bpf_offload - Get BPF offload Capabilities
6473 * @hdd_ctx: Hdd context
6474 *
6475 * Return: 0 on success, errno on failure
6476 */
6477static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6478{
6479 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006480 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306481 QDF_STATUS status;
6482 int ret;
6483
6484 ENTER();
6485
6486 spin_lock(&hdd_context_lock);
6487 context = &bpf_context;
6488 context->magic = BPF_CONTEXT_MAGIC;
6489 INIT_COMPLETION(context->completion);
6490 spin_unlock(&hdd_context_lock);
6491
6492 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6493 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006494 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306495 return -EINVAL;
6496 }
6497 /* request was sent -- wait for the response */
6498 rc = wait_for_completion_timeout(&context->completion,
6499 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6500 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006501 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306502 spin_lock(&hdd_context_lock);
6503 context->magic = 0;
6504 spin_unlock(&hdd_context_lock);
6505
6506 return -ETIMEDOUT;
6507 }
6508 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6509 &bpf_context.capability_response);
6510 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006511 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306512
6513 EXIT();
6514 return ret;
6515}
6516
6517/**
6518 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6519 * @hdd_ctx: Hdd context
6520 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306521 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306522 *
6523 * Return: 0 on success; errno on failure
6524 */
6525static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6526 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306527 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306528{
6529 struct sir_bpf_set_offload *bpf_set_offload;
6530 QDF_STATUS status;
6531 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306532 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306533
6534 ENTER();
6535
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306536 if (adapter->device_mode == QDF_STA_MODE ||
6537 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6538 if (!hdd_conn_is_connected(
6539 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6540 hdd_err("Not in Connected state!");
6541 return -ENOTSUPP;
6542 }
6543 }
6544
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306545 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6546 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006547 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306548 return -ENOMEM;
6549 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306550
6551 /* Parse and fetch bpf packet size */
6552 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006553 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306554 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306555 goto fail;
6556 }
6557 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6558
6559 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006560 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306561 goto post_sme;
6562 }
6563
6564 /* Parse and fetch bpf program */
6565 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006566 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306567 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306568 goto fail;
6569 }
6570
6571 prog_len = nla_len(tb[BPF_PROGRAM]);
6572 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306573
6574 if (bpf_set_offload->program == NULL) {
6575 hdd_err("qdf_mem_malloc failed for bpf offload program");
6576 ret = -ENOMEM;
6577 goto fail;
6578 }
6579
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306580 bpf_set_offload->current_length = prog_len;
6581 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306582 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306583
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306584 hdd_info("BPF set instructions");
6585 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6586 bpf_set_offload->program, prog_len);
6587
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306588 /* Parse and fetch filter Id */
6589 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006590 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306591 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306592 goto fail;
6593 }
6594 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6595
6596 /* Parse and fetch current offset */
6597 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006598 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306599 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306600 goto fail;
6601 }
6602 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6603
6604post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006605 hdd_notice("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306606 bpf_set_offload->session_id,
6607 bpf_set_offload->version,
6608 bpf_set_offload->filter_id,
6609 bpf_set_offload->total_length,
6610 bpf_set_offload->current_length,
6611 bpf_set_offload->current_offset);
6612
6613 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6614 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006615 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306616 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306617 goto fail;
6618 }
6619 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306620
6621fail:
6622 if (bpf_set_offload->current_length)
6623 qdf_mem_free(bpf_set_offload->program);
6624 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306625 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306626}
6627
6628/**
6629 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6630 * @wiphy: wiphy structure pointer
6631 * @wdev: Wireless device structure pointer
6632 * @data: Pointer to the data received
6633 * @data_len: Length of @data
6634 *
6635 * Return: 0 on success; errno on failure
6636 */
6637static int
6638__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6639 struct wireless_dev *wdev,
6640 const void *data, int data_len)
6641{
6642 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6643 struct net_device *dev = wdev->netdev;
6644 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6645 struct nlattr *tb[BPF_MAX + 1];
6646 int ret_val, packet_filter_subcmd;
6647
6648 ENTER();
6649
6650 ret_val = wlan_hdd_validate_context(hdd_ctx);
6651 if (ret_val)
6652 return ret_val;
6653
6654 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006655 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306656 return -EINVAL;
6657 }
6658
6659 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006660 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306661 return -ENOTSUPP;
6662 }
6663
6664 if (nla_parse(tb, BPF_MAX, data, data_len,
6665 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006666 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306667 return -EINVAL;
6668 }
6669
6670 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006671 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306672 return -EINVAL;
6673 }
6674
6675 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6676
6677 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6678 return hdd_get_bpf_offload(hdd_ctx);
6679 else
6680 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306681 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306682}
6683
6684/**
6685 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6686 * @wiphy: wiphy structure pointer
6687 * @wdev: Wireless device structure pointer
6688 * @data: Pointer to the data received
6689 * @data_len: Length of @data
6690 *
6691 * Return: 0 on success; errno on failure
6692 */
6693
6694static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6695 struct wireless_dev *wdev,
6696 const void *data, int data_len)
6697{
6698 int ret;
6699
6700 cds_ssr_protect(__func__);
6701 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6702 cds_ssr_unprotect(__func__);
6703
6704 return ret;
6705}
6706
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306707/**
6708 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6709 * @pre_cac_adapter: AP adapter used for pre cac
6710 * @status: Status (true or false)
6711 * @handle: Global handle
6712 *
6713 * Sets the status of pre cac i.e., whether the pre cac is active or not
6714 *
6715 * Return: Zero on success, non-zero on failure
6716 */
6717static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6718 bool status, tHalHandle handle)
6719{
6720 QDF_STATUS ret;
6721
6722 ret = wlan_sap_set_pre_cac_status(
6723 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6724 if (QDF_IS_STATUS_ERROR(ret))
6725 return -EINVAL;
6726
6727 return 0;
6728}
6729
6730/**
6731 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6732 * @ap_adapter: AP adapter
6733 * @chan_before_pre_cac: Channel
6734 *
6735 * Saves the channel which the AP was beaconing on before moving to the pre
6736 * cac channel. If radar is detected on the pre cac channel, this saved
6737 * channel will be used for AP operations.
6738 *
6739 * Return: Zero on success, non-zero on failure
6740 */
6741static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6742 uint8_t chan_before_pre_cac)
6743{
6744 QDF_STATUS ret;
6745
6746 ret = wlan_sap_set_chan_before_pre_cac(
6747 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6748 if (QDF_IS_STATUS_ERROR(ret))
6749 return -EINVAL;
6750
6751 return 0;
6752}
6753
6754/**
6755 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6756 * @ap_adapter: AP adapter
6757 * @nol: Non-occupancy list
6758 * @nol_len: Length of NOL
6759 *
6760 * Get the NOL for SAP
6761 *
6762 * Return: Zero on success, non-zero on failure
6763 */
6764static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6765 uint32_t *nol_len)
6766{
6767 QDF_STATUS ret;
6768
6769 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6770 nol, nol_len);
6771 if (QDF_IS_STATUS_ERROR(ret))
6772 return -EINVAL;
6773
6774 return 0;
6775}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306776
6777/**
6778 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6779 * @hdd_ctx: HDD context
6780 * @ap_adapter: AP adapter
6781 * @channel: Channel requested by userspace
6782 * @pre_cac_chan: Pointer to the pre CAC channel
6783 *
6784 * Validates the channel provided by userspace. If user provided channel 0,
6785 * a valid outdoor channel must be selected from the regulatory channel.
6786 *
6787 * Return: Zero on success and non zero value on error
6788 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006789static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6790 hdd_adapter_t *ap_adapter,
6791 uint8_t channel,
6792 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306793{
6794 uint32_t i, j;
6795 QDF_STATUS status;
6796 int ret;
6797 uint8_t nol[QDF_MAX_NUM_CHAN];
6798 uint32_t nol_len = 0, weight_len = 0;
6799 bool found;
6800 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6801 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6802 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6803
6804 if (0 == channel) {
6805 /* Channel is not obtained from PCL because PCL may not have
6806 * the entire channel list. For example: if SAP is up on
6807 * channel 6 and PCL is queried for the next SAP interface,
6808 * if SCC is preferred, the PCL will contain only the channel
6809 * 6. But, we are in need of a DFS channel. So, going with the
6810 * first channel from the valid channel list.
6811 */
6812 status = cds_get_valid_chans(channel_list, &len);
6813 if (QDF_IS_STATUS_ERROR(status)) {
6814 hdd_err("Failed to get channel list");
6815 return -EINVAL;
6816 }
6817 cds_update_with_safe_channel_list(channel_list, &len,
6818 pcl_weights, weight_len);
6819 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6820 for (i = 0; i < len; i++) {
6821 found = false;
6822 for (j = 0; j < nol_len; j++) {
6823 if (channel_list[i] == nol[j]) {
6824 found = true;
6825 break;
6826 }
6827 }
6828 if (found)
6829 continue;
6830 if (CDS_IS_DFS_CH(channel_list[i])) {
6831 *pre_cac_chan = channel_list[i];
6832 break;
6833 }
6834 }
6835 if (*pre_cac_chan == 0) {
6836 hdd_err("unable to find outdoor channel");
6837 return -EINVAL;
6838 }
6839 } else {
6840 /* Only when driver selects a channel, check is done for
6841 * unnsafe and NOL channels. When user provides a fixed channel
6842 * the user is expected to take care of this.
6843 */
6844 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6845 !CDS_IS_DFS_CH(channel)) {
6846 hdd_err("Invalid channel for pre cac:%d", channel);
6847 return -EINVAL;
6848 } else {
6849 *pre_cac_chan = channel;
6850 }
6851 }
6852 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6853 return 0;
6854}
6855
6856/**
6857 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6858 * @channel: Channel option provided by userspace
6859 *
6860 * Sets the driver to the required hardware mode and start an adapater for
6861 * pre CAC which will mimic an AP.
6862 *
6863 * Return: Zero on success, non-zero value on error
6864 */
6865int wlan_hdd_request_pre_cac(uint8_t channel)
6866{
Krunal Sonib37bb352016-12-20 14:12:21 -08006867 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306868 hdd_context_t *hdd_ctx;
6869 int ret;
6870 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6871 hdd_ap_ctx_t *hdd_ap_ctx;
6872 QDF_STATUS status;
6873 struct wiphy *wiphy;
6874 struct net_device *dev;
6875 struct cfg80211_chan_def chandef;
6876 enum nl80211_channel_type channel_type;
6877 uint32_t freq;
6878 struct ieee80211_channel *chan;
6879 tHalHandle handle;
6880 bool val;
6881
6882 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6883 if (0 != wlan_hdd_validate_context(hdd_ctx))
6884 return -EINVAL;
6885
6886 if (cds_get_connection_count() > 1) {
6887 hdd_err("pre cac not allowed in concurrency");
6888 return -EINVAL;
6889 }
6890
6891 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6892 if (!ap_adapter) {
6893 hdd_err("unable to get SAP adapter");
6894 return -EINVAL;
6895 }
6896
6897 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6898 if (!handle) {
6899 hdd_err("Invalid handle");
6900 return -EINVAL;
6901 }
6902
6903 val = wlan_sap_is_pre_cac_active(handle);
6904 if (val) {
6905 hdd_err("pre cac is already in progress");
6906 return -EINVAL;
6907 }
6908
6909 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6910 if (!hdd_ap_ctx) {
6911 hdd_err("SAP context is NULL");
6912 return -EINVAL;
6913 }
6914
6915 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6916 hdd_err("SAP is already on DFS channel:%d",
6917 hdd_ap_ctx->operatingChannel);
6918 return -EINVAL;
6919 }
6920
6921 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6922 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6923 hdd_ap_ctx->operatingChannel);
6924 return -EINVAL;
6925 }
6926
Krunal Sonib37bb352016-12-20 14:12:21 -08006927 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6928 if (!mac_addr) {
6929 hdd_err("can't add virtual intf: Not getting valid mac addr");
6930 return -EINVAL;
6931 }
6932
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306933 hdd_info("channel:%d", channel);
6934
6935 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6936 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006937 if (ret != 0) {
6938 hdd_err("can't validate pre-cac channel");
6939 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306940 }
6941
6942 hdd_debug("starting pre cac SAP adapter");
6943
6944 /* Starting a SAP adapter:
6945 * Instead of opening an adapter, we could just do a SME open session
6946 * for AP type. But, start BSS would still need an adapter.
6947 * So, this option is not taken.
6948 *
6949 * hdd open adapter is going to register this precac interface with
6950 * user space. This interface though exposed to user space will be in
6951 * DOWN state. Consideration was done to avoid this registration to the
6952 * user space. But, as part of SAP operations multiple events are sent
6953 * to user space. Some of these events received from unregistered
6954 * interface was causing crashes. So, retaining the registration.
6955 *
6956 * So, this interface would remain registered and will remain in DOWN
6957 * state for the CAC duration. We will add notes in the feature
6958 * announcement to not use this temporary interface for any activity
6959 * from user space.
6960 */
6961 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006962 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306963 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306964 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006965 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306966 }
6967
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306968 /*
6969 * This interface is internally created by the driver. So, no interface
6970 * up comes for this interface from user space and hence starting
6971 * the adapter internally.
6972 */
6973 if (hdd_start_adapter(pre_cac_adapter)) {
6974 hdd_err("error starting the pre cac adapter");
6975 goto close_pre_cac_adapter;
6976 }
6977
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306978 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6979
6980 wiphy = hdd_ctx->wiphy;
6981 dev = pre_cac_adapter->dev;
6982
6983 /* Since this is only a dummy interface lets us use the IEs from the
6984 * other active SAP interface. In regular scenarios, these IEs would
6985 * come from the user space entity
6986 */
6987 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6988 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6989 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6990 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306991 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306992 }
6993 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6994 ap_adapter->sessionCtx.ap.beacon,
6995 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6996 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6997 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6998 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6999 ap_adapter->sessionCtx.ap.sapConfig.authType;
7000
7001 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7002 * to operate on the same bandwidth as that of the 2.4GHz operations.
7003 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7004 */
7005 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7006 case CH_WIDTH_20MHZ:
7007 channel_type = NL80211_CHAN_HT20;
7008 break;
7009 case CH_WIDTH_40MHZ:
7010 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7011 ap_adapter->sessionCtx.ap.sapConfig.channel)
7012 channel_type = NL80211_CHAN_HT40PLUS;
7013 else
7014 channel_type = NL80211_CHAN_HT40MINUS;
7015 break;
7016 default:
7017 channel_type = NL80211_CHAN_NO_HT;
7018 break;
7019 }
7020
7021 freq = cds_chan_to_freq(pre_cac_chan);
7022 chan = __ieee80211_get_channel(wiphy, freq);
7023 if (!chan) {
7024 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307025 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307026 }
7027
7028 cfg80211_chandef_create(&chandef, chan, channel_type);
7029
7030 hdd_debug("orig width:%d channel_type:%d freq:%d",
7031 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7032 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007033 /*
7034 * Doing update after opening and starting pre-cac adapter will make
7035 * sure that driver won't do hardware mode change if there are any
7036 * initial hick-ups or issues in pre-cac adapter's configuration.
7037 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7038 * connection update should result in DBS mode
7039 */
7040 status = cds_update_and_wait_for_connection_update(
7041 ap_adapter->sessionId,
7042 pre_cac_chan,
7043 SIR_UPDATE_REASON_PRE_CAC);
7044 if (QDF_IS_STATUS_ERROR(status)) {
7045 hdd_err("error in moving to DBS mode");
7046 goto stop_close_pre_cac_adapter;
7047 }
7048
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307049
7050 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7051 if (0 != ret) {
7052 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307053 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307054 }
7055
7056 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7057 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007058 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307059 if (QDF_IS_STATUS_ERROR(status)) {
7060 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307061 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307062 }
7063
7064 /*
7065 * The pre cac status is set here. But, it would not be reset explicitly
7066 * anywhere, since after the pre cac success/failure, the pre cac
7067 * adapter itself would be removed.
7068 */
7069 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7070 if (0 != ret) {
7071 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307072 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307073 }
7074
7075 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7076 hdd_ap_ctx->operatingChannel);
7077 if (0 != ret) {
7078 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307079 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307080 }
7081
7082 ap_adapter->pre_cac_chan = pre_cac_chan;
7083
7084 return 0;
7085
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307086stop_close_pre_cac_adapter:
7087 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307088 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7089 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307090close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307091 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007092release_intf_addr_and_return_failure:
7093 /*
7094 * Release the interface address as the adapter
7095 * failed to start, if you don't release then next
7096 * adapter which is trying to come wouldn't get valid
7097 * mac address. Remember we have limited pool of mac addresses
7098 */
7099 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307100 return -EINVAL;
7101}
7102
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307103/**
7104 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7105 *
7106 * Return: None
7107 */
7108void hdd_init_bpf_completion(void)
7109{
7110 init_completion(&bpf_context.completion);
7111}
7112
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307113static const struct nla_policy
7114wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7115 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7116};
7117
Agrawal Ashish65634612016-08-18 13:24:32 +05307118static const struct nla_policy
7119wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7120 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7121 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7122};
7123
7124/**
7125 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7126 * @wiphy: Pointer to wireless phy
7127 * @wdev: Pointer to wireless device
7128 * @data: Pointer to data
7129 * @data_len: Length of @data
7130 *
7131 * This function parses the incoming NL vendor command data attributes and
7132 * updates the SAP context about channel_hint and DFS mode.
7133 * If channel_hint is set, SAP will choose that channel
7134 * as operating channel.
7135 *
7136 * If DFS mode is enabled, driver will include DFS channels
7137 * in ACS else driver will skip DFS channels.
7138 *
7139 * Return: 0 on success, negative errno on failure
7140 */
7141static int
7142__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7143 struct wireless_dev *wdev,
7144 const void *data, int data_len)
7145{
7146 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7147 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7148 int ret;
7149 struct acs_dfs_policy *acs_policy;
7150 int mode = DFS_MODE_NONE;
7151 int channel_hint = 0;
7152
7153 ENTER_DEV(wdev->netdev);
7154
7155 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7156 hdd_err("Command not allowed in FTM mode");
7157 return -EINVAL;
7158 }
7159
7160 ret = wlan_hdd_validate_context(hdd_ctx);
7161 if (0 != ret)
7162 return ret;
7163
7164 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7165 data, data_len,
7166 wlan_hdd_set_acs_dfs_config_policy)) {
7167 hdd_err("invalid attr");
7168 return -EINVAL;
7169 }
7170
7171 acs_policy = &hdd_ctx->acs_policy;
7172 /*
7173 * SCM sends this attribute to restrict SAP from choosing
7174 * DFS channels from ACS.
7175 */
7176 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7177 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7178
7179 if (!IS_DFS_MODE_VALID(mode)) {
7180 hdd_err("attr acs dfs mode is not valid");
7181 return -EINVAL;
7182 }
7183 acs_policy->acs_dfs_mode = mode;
7184
7185 /*
7186 * SCM sends this attribute to provide an active channel,
7187 * to skip redundant ACS between drivers, and save driver start up time
7188 */
7189 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7190 channel_hint = nla_get_u8(
7191 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7192
7193 if (!IS_CHANNEL_VALID(channel_hint)) {
7194 hdd_err("acs channel is not valid");
7195 return -EINVAL;
7196 }
7197 acs_policy->acs_channel = channel_hint;
7198
7199 return 0;
7200}
7201
7202/**
7203 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7204 * @wiphy: wiphy structure pointer
7205 * @wdev: Wireless device structure pointer
7206 * @data: Pointer to the data received
7207 * @data_len: Length of @data
7208 *
7209 * This function parses the incoming NL vendor command data attributes and
7210 * updates the SAP context about channel_hint and DFS mode.
7211 *
7212 * Return: 0 on success; errno on failure
7213 */
7214static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7215 struct wireless_dev *wdev,
7216 const void *data, int data_len)
7217{
7218 int ret;
7219
7220 cds_ssr_protect(__func__);
7221 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7222 cds_ssr_unprotect(__func__);
7223
7224 return ret;
7225}
7226
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307227/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307228 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7229 * @mode : cfg80211 dfs mode
7230 *
7231 * Return: return csr sta roam dfs mode else return NONE
7232 */
7233static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7234 enum dfs_mode mode)
7235{
7236 switch (mode) {
7237 case DFS_MODE_ENABLE:
7238 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7239 break;
7240 case DFS_MODE_DISABLE:
7241 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7242 break;
7243 case DFS_MODE_DEPRIORITIZE:
7244 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7245 break;
7246 default:
7247 hdd_err("STA Roam policy dfs mode is NONE");
7248 return CSR_STA_ROAM_POLICY_NONE;
7249 }
7250}
7251
7252static const struct nla_policy
7253wlan_hdd_set_sta_roam_config_policy[
7254QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7255 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7256 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7257};
7258
7259/**
7260 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7261 * for station connection or roaming.
7262 * @wiphy: Pointer to wireless phy
7263 * @wdev: Pointer to wireless device
7264 * @data: Pointer to data
7265 * @data_len: Length of @data
7266 *
7267 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7268 * channels needs to be skipped in scanning or not.
7269 * If dfs_mode is disabled, driver will not scan DFS channels.
7270 * If skip_unsafe_channels is set, driver will skip unsafe channels
7271 * in Scanning.
7272 *
7273 * Return: 0 on success, negative errno on failure
7274 */
7275static int
7276__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7277 struct wireless_dev *wdev,
7278 const void *data, int data_len)
7279{
7280 struct net_device *dev = wdev->netdev;
7281 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7282 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7283 struct nlattr *tb[
7284 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7285 int ret;
7286 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7287 enum dfs_mode mode = DFS_MODE_NONE;
7288 bool skip_unsafe_channels = false;
7289 QDF_STATUS status;
7290
7291 ENTER_DEV(dev);
7292
7293 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7294 hdd_err("Command not allowed in FTM mode");
7295 return -EINVAL;
7296 }
7297
7298 ret = wlan_hdd_validate_context(hdd_ctx);
7299 if (0 != ret)
7300 return ret;
7301 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7302 data, data_len,
7303 wlan_hdd_set_sta_roam_config_policy)) {
7304 hdd_err("invalid attr");
7305 return -EINVAL;
7306 }
7307 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7308 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7309 if (!IS_DFS_MODE_VALID(mode)) {
7310 hdd_err("attr sta roam dfs mode policy is not valid");
7311 return -EINVAL;
7312 }
7313
7314 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7315
7316 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7317 skip_unsafe_channels = nla_get_u8(
7318 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7319
7320 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7321 skip_unsafe_channels, adapter->sessionId);
7322
7323 if (!QDF_IS_STATUS_SUCCESS(status)) {
7324 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7325 return -EINVAL;
7326 }
7327 return 0;
7328}
7329
7330/**
7331 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7332 * connection and roaming for station.
7333 * @wiphy: wiphy structure pointer
7334 * @wdev: Wireless device structure pointer
7335 * @data: Pointer to the data received
7336 * @data_len: Length of @data
7337 *
7338 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7339 * channels needs to be skipped in scanning or not.
7340 * If dfs_mode is disabled, driver will not scan DFS channels.
7341 * If skip_unsafe_channels is set, driver will skip unsafe channels
7342 * in Scanning.
7343 * Return: 0 on success; errno on failure
7344 */
7345static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7346 struct wireless_dev *wdev,
7347 const void *data, int data_len)
7348{
7349 int ret;
7350
7351 cds_ssr_protect(__func__);
7352 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7353 cds_ssr_unprotect(__func__);
7354
7355 return ret;
7356}
7357
Agrawal Ashish467dde42016-09-08 18:44:22 +05307358#ifdef FEATURE_WLAN_CH_AVOID
7359/**
7360 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7361 * is on unsafe channel.
7362 * @wiphy: wiphy structure pointer
7363 * @wdev: Wireless device structure pointer
7364 * @data: Pointer to the data received
7365 * @data_len: Length of @data
7366 *
7367 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7368 * on any of unsafe channels.
7369 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7370 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7371 *
7372 * Return: 0 on success; errno on failure
7373 */
7374static int
7375__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7376 struct wireless_dev *wdev,
7377 const void *data, int data_len)
7378{
7379 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7380 int ret;
7381 uint16_t unsafe_channel_count;
7382 int unsafe_channel_index;
7383 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7384
7385 ENTER_DEV(wdev->netdev);
7386
7387 if (!qdf_ctx) {
7388 cds_err("qdf_ctx is NULL");
7389 return -EINVAL;
7390 }
7391
7392 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7393 hdd_err("Command not allowed in FTM mode");
7394 return -EINVAL;
7395 }
7396
7397 ret = wlan_hdd_validate_context(hdd_ctx);
7398 if (0 != ret)
7399 return ret;
7400 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7401 &(hdd_ctx->unsafe_channel_count),
7402 sizeof(hdd_ctx->unsafe_channel_list));
7403
7404 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7405 (uint16_t)NUM_CHANNELS);
7406 for (unsafe_channel_index = 0;
7407 unsafe_channel_index < unsafe_channel_count;
7408 unsafe_channel_index++) {
7409 hdd_info("Channel %d is not safe",
7410 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7411 }
7412 hdd_unsafe_channel_restart_sap(hdd_ctx);
7413 return 0;
7414}
7415
7416/**
7417 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7418 * is on unsafe channel.
7419 * @wiphy: wiphy structure pointer
7420 * @wdev: Wireless device structure pointer
7421 * @data: Pointer to the data received
7422 * @data_len: Length of @data
7423 *
7424 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7425 * on any of unsafe channels.
7426 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7427 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7428 *
7429 * Return: 0 on success; errno on failure
7430 */
7431static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7432 struct wireless_dev *wdev,
7433 const void *data, int data_len)
7434{
7435 int ret;
7436
7437 cds_ssr_protect(__func__);
7438 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7439 cds_ssr_unprotect(__func__);
7440
7441 return ret;
7442}
7443
7444#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307445/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307446 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7447 * SAP is on unsafe channel.
7448 * @wiphy: wiphy structure pointer
7449 * @wdev: Wireless device structure pointer
7450 * @data: Pointer to the data received
7451 * @data_len: Length of @data
7452 *
7453 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7454 * driver.
7455 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7456 * will initiate restart of sap.
7457 *
7458 * Return: 0 on success; errno on failure
7459 */
7460static int
7461__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7462 struct wireless_dev *wdev,
7463 const void *data, int data_len)
7464{
7465 struct net_device *ndev = wdev->netdev;
7466 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7467 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7468 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7469 uint8_t config_channel = 0;
7470 hdd_ap_ctx_t *ap_ctx;
7471 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307472 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307473
7474 ENTER();
7475
7476 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007477 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307478 return -EINVAL;
7479 }
7480
7481 ret = wlan_hdd_validate_context(hdd_ctx);
7482 if (0 != ret)
7483 return -EINVAL;
7484
7485 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7486 data, data_len,
7487 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007488 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307489 return -EINVAL;
7490 }
7491
7492 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7493 if (!test_bit(SOFTAP_BSS_STARTED,
7494 &hostapd_adapter->event_flags)) {
7495 hdd_err("SAP is not started yet. Restart sap will be invalid");
7496 return -EINVAL;
7497 }
7498
7499 config_channel =
7500 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7501
7502 if (!((IS_24G_CH(config_channel)) ||
7503 (IS_5G_CH(config_channel)))) {
7504 hdd_err("Channel %d is not valid to restart SAP",
7505 config_channel);
7506 return -ENOTSUPP;
7507 }
7508
7509 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7510 ap_ctx->sapConfig.channel = config_channel;
7511 ap_ctx->sapConfig.ch_params.ch_width =
7512 ap_ctx->sapConfig.ch_width_orig;
7513
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007514 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307515 ap_ctx->sapConfig.sec_ch,
7516 &ap_ctx->sapConfig.ch_params);
7517
7518 cds_restart_sap(hostapd_adapter);
7519 }
7520
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307521 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7522 uint32_t freq_len, i;
7523 uint32_t *freq;
7524 uint8_t chans[QDF_MAX_NUM_CHAN];
7525
7526 hdd_debug("setting mandatory freq/chan list");
7527
7528 freq_len = nla_len(
7529 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7530 sizeof(uint32_t);
7531
7532 if (freq_len > QDF_MAX_NUM_CHAN) {
7533 hdd_err("insufficient space to hold channels");
7534 return -ENOMEM;
7535 }
7536
7537 freq = nla_data(
7538 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7539
7540 hdd_debug("freq_len=%d", freq_len);
7541
7542 for (i = 0; i < freq_len; i++) {
7543 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7544 hdd_debug("freq[%d]=%d", i, freq[i]);
7545 }
7546
7547 status = cds_set_sap_mandatory_channels(chans, freq_len);
7548 if (QDF_IS_STATUS_ERROR(status))
7549 return -EINVAL;
7550 }
7551
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307552 return 0;
7553}
7554
7555/**
7556 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7557 * @wiphy: wiphy structure pointer
7558 * @wdev: Wireless device structure pointer
7559 * @data: Pointer to the data received
7560 * @data_len: Length of @data
7561 *
7562 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7563 * driver.
7564 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7565 * will initiate restart of sap.
7566 *
7567 * Return: 0 on success; errno on failure
7568 */
7569static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7570 struct wireless_dev *wdev,
7571 const void *data, int data_len)
7572{
7573 int ret;
7574
7575 cds_ssr_protect(__func__);
7576 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7577 wdev, data, data_len);
7578 cds_ssr_unprotect(__func__);
7579
7580 return ret;
7581}
7582
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307583#undef BPF_INVALID
7584#undef BPF_SET_RESET
7585#undef BPF_VERSION
7586#undef BPF_ID
7587#undef BPF_PACKET_SIZE
7588#undef BPF_CURRENT_OFFSET
7589#undef BPF_PROGRAM
7590#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307591
7592/**
7593 * define short names for the global vendor params
7594 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7595 */
7596#define PARAM_TOTAL_CMD_EVENT_WAKE \
7597 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7598#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7599 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7600#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7601 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7602#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7603 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7604#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7605 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7606#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7607 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7608#define PARAM_TOTAL_RX_DATA_WAKE \
7609 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7610#define PARAM_RX_UNICAST_CNT \
7611 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7612#define PARAM_RX_MULTICAST_CNT \
7613 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7614#define PARAM_RX_BROADCAST_CNT \
7615 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7616#define PARAM_ICMP_PKT \
7617 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7618#define PARAM_ICMP6_PKT \
7619 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7620#define PARAM_ICMP6_RA \
7621 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7622#define PARAM_ICMP6_NA \
7623 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7624#define PARAM_ICMP6_NS \
7625 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7626#define PARAM_ICMP4_RX_MULTICAST_CNT \
7627 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7628#define PARAM_ICMP6_RX_MULTICAST_CNT \
7629 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7630#define PARAM_OTHER_RX_MULTICAST_CNT \
7631 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307632#define PARAM_RSSI_BREACH_CNT \
7633 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
7634#define PARAM_LOW_RSSI_CNT \
7635 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
7636#define PARAM_GSCAN_CNT \
7637 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
7638#define PARAM_PNO_COMPLETE_CNT \
7639 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
7640#define PARAM_PNO_MATCH_CNT \
7641 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
7642
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307643
7644
7645/**
7646 * hdd_send_wakelock_stats() - API to send wakelock stats
7647 * @ctx: context to be passed to callback
7648 * @data: data passed to callback
7649 *
7650 * This function is used to send wake lock stats to HAL layer
7651 *
7652 * Return: 0 on success, error number otherwise.
7653 */
7654static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7655 const struct sir_wake_lock_stats *data)
7656{
7657 struct sk_buff *skb;
7658 uint32_t nl_buf_len;
7659 uint32_t total_rx_data_wake, rx_multicast_cnt;
7660 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307661 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307662
7663 ENTER();
7664
7665 nl_buf_len = NLMSG_HDRLEN;
7666 nl_buf_len +=
7667 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7668 (NLMSG_HDRLEN + sizeof(uint32_t));
7669
7670 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7671
7672 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007673 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307674 return -ENOMEM;
7675 }
7676
Jeff Johnson64943bd2016-08-23 13:14:06 -07007677 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307678 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007679 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307680 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007681 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307682 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007683 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307684 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007685 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307686 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007687 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307688 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007689 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307690 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007691 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7692 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307693 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307694 hdd_info("wow_rssi_breach_wake_up_count %d",
7695 data->wow_rssi_breach_wake_up_count);
7696 hdd_info("wow_low_rssi_wake_up_count %d",
7697 data->wow_low_rssi_wake_up_count);
7698 hdd_info("wow_gscan_wake_up_count %d",
7699 data->wow_gscan_wake_up_count);
7700 hdd_info("wow_pno_complete_wake_up_count %d",
7701 data->wow_pno_complete_wake_up_count);
7702 hdd_info("wow_pno_match_wake_up_count %d",
7703 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307704
7705 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307706 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307707
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307708 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307709 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307710
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307711 rx_multicast_cnt =
7712 data->wow_ipv4_mcast_wake_up_count +
7713 ipv6_rx_multicast_addr_cnt;
7714
7715 total_rx_data_wake =
7716 data->wow_ucast_wake_up_count +
7717 data->wow_bcast_wake_up_count +
7718 rx_multicast_cnt;
7719
7720 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7721 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7722 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7723 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7724 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7725 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7726 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7727 total_rx_data_wake) ||
7728 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7729 data->wow_ucast_wake_up_count) ||
7730 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7731 rx_multicast_cnt) ||
7732 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7733 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307734 nla_put_u32(skb, PARAM_ICMP_PKT,
7735 data->wow_icmpv4_count) ||
7736 nla_put_u32(skb, PARAM_ICMP6_PKT,
7737 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307738 nla_put_u32(skb, PARAM_ICMP6_RA,
7739 data->wow_ipv6_mcast_ra_stats) ||
7740 nla_put_u32(skb, PARAM_ICMP6_NA,
7741 data->wow_ipv6_mcast_na_stats) ||
7742 nla_put_u32(skb, PARAM_ICMP6_NS,
7743 data->wow_ipv6_mcast_ns_stats) ||
7744 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7745 data->wow_ipv4_mcast_wake_up_count) ||
7746 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7747 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307748 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
7749 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
7750 data->wow_rssi_breach_wake_up_count) ||
7751 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
7752 data->wow_low_rssi_wake_up_count) ||
7753 nla_put_u32(skb, PARAM_GSCAN_CNT,
7754 data->wow_gscan_wake_up_count) ||
7755 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
7756 data->wow_pno_complete_wake_up_count) ||
7757 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
7758 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007759 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307760 goto nla_put_failure;
7761 }
7762
7763 cfg80211_vendor_cmd_reply(skb);
7764
7765 EXIT();
7766 return 0;
7767
7768nla_put_failure:
7769 kfree_skb(skb);
7770 return -EINVAL;
7771}
7772
7773/**
7774 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7775 * @wiphy: wiphy pointer
7776 * @wdev: pointer to struct wireless_dev
7777 * @data: pointer to incoming NL vendor data
7778 * @data_len: length of @data
7779 *
7780 * This function parses the incoming NL vendor command data attributes and
7781 * invokes the SME Api and blocks on a completion variable.
7782 * WMA copies required data and invokes callback
7783 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7784 *
7785 * Return: 0 on success; error number otherwise.
7786 */
7787static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7788 struct wireless_dev *wdev,
7789 const void *data,
7790 int data_len)
7791{
7792 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7793 int status, ret;
7794 struct sir_wake_lock_stats wake_lock_stats;
7795 QDF_STATUS qdf_status;
7796
7797 ENTER();
7798
7799 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007800 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307801 return -EINVAL;
7802 }
7803
7804 status = wlan_hdd_validate_context(hdd_ctx);
7805 if (0 != status)
7806 return -EINVAL;
7807
7808 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7809 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007810 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307811 return -EINVAL;
7812 }
7813
7814 ret = hdd_send_wakelock_stats(hdd_ctx,
7815 &wake_lock_stats);
7816 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007817 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307818
7819 EXIT();
7820 return ret;
7821}
7822
7823/**
7824 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7825 * @wiphy: wiphy pointer
7826 * @wdev: pointer to struct wireless_dev
7827 * @data: pointer to incoming NL vendor data
7828 * @data_len: length of @data
7829 *
7830 * This function parses the incoming NL vendor command data attributes and
7831 * invokes the SME Api and blocks on a completion variable.
7832 * WMA copies required data and invokes callback
7833 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7834 *
7835 * Return: 0 on success; error number otherwise.
7836 */
7837static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7838 struct wireless_dev *wdev,
7839 const void *data, int data_len)
7840{
7841 int ret;
7842
7843 cds_ssr_protect(__func__);
7844 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7845 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007846 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307847
7848 return ret;
7849}
7850
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307851/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307852 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7853 * @wiphy: wiphy structure pointer
7854 * @wdev: Wireless device structure pointer
7855 * @data: Pointer to the data received
7856 * @data_len: Length of @data
7857 *
7858 * This function reads wmi max bus size and fill in the skb with
7859 * NL attributes and send up the NL event.
7860 * Return: 0 on success; errno on failure
7861 */
7862static int
7863__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7864 struct wireless_dev *wdev,
7865 const void *data, int data_len)
7866{
7867 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7868 int ret_val;
7869 struct sk_buff *skb;
7870 uint32_t nl_buf_len;
7871
7872 ENTER();
7873
7874 ret_val = wlan_hdd_validate_context(hdd_ctx);
7875 if (ret_val)
7876 return ret_val;
7877
7878 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7879 hdd_err("Command not allowed in FTM mode");
7880 return -EINVAL;
7881 }
7882
7883 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7884
7885 nl_buf_len = NLMSG_HDRLEN;
7886 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7887
7888 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7889 if (!skb) {
7890 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7891 return -ENOMEM;
7892 }
7893
7894 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7895 hdd_ctx->wmi_max_len)) {
7896 hdd_err("nla put failure");
7897 goto nla_put_failure;
7898 }
7899
7900 cfg80211_vendor_cmd_reply(skb);
7901
7902 EXIT();
7903
7904 return 0;
7905
7906nla_put_failure:
7907 kfree_skb(skb);
7908 return -EINVAL;
7909}
7910
7911/**
7912 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7913 * @wiphy: wiphy structure pointer
7914 * @wdev: Wireless device structure pointer
7915 * @data: Pointer to the data received
7916 * @data_len: Length of @data
7917 *
7918 * Return: 0 on success; errno on failure
7919 */
7920static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7921 struct wireless_dev *wdev,
7922 const void *data, int data_len)
7923{
7924 int ret;
7925
7926 cds_ssr_protect(__func__);
7927 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7928 cds_ssr_unprotect(__func__);
7929
7930 return ret;
7931}
7932
7933/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307934 *__wlan_hdd_cfg80211_setband() - set band
7935 * @wiphy: Pointer to wireless phy
7936 * @wdev: Pointer to wireless device
7937 * @data: Pointer to data
7938 * @data_len: Length of @data
7939 *
7940 * Return: 0 on success, negative errno on failure
7941 */
7942static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7943 struct wireless_dev *wdev,
7944 const void *data, int data_len)
7945{
7946 struct net_device *dev = wdev->netdev;
7947 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7948 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7949 int ret;
7950 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7951 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7952
7953 ENTER();
7954
7955 ret = wlan_hdd_validate_context(hdd_ctx);
7956 if (ret)
7957 return ret;
7958
7959 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7960 hdd_err(FL("Invalid ATTR"));
7961 return -EINVAL;
7962 }
7963
7964 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7965 hdd_err(FL("attr SETBAND_VALUE failed"));
7966 return -EINVAL;
7967 }
7968
7969 ret = hdd_set_band(dev,
7970 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7971
7972 EXIT();
7973 return ret;
7974}
7975
7976/**
7977 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7978 * @wiphy: wiphy structure pointer
7979 * @wdev: Wireless device structure pointer
7980 * @data: Pointer to the data received
7981 * @data_len: Length of @data
7982 *
7983 * Return: 0 on success; 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 int ret;
7990
7991 cds_ssr_protect(__func__);
7992 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7993 cds_ssr_unprotect(__func__);
7994
7995 return ret;
7996}
7997
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08007998/**
7999 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8000 * @nl80211_value: Vendor command attribute value
8001 * @wmi_value: Pointer to return converted WMI return value
8002 *
8003 * Convert NL80211 vendor command value for SAR limit set to WMI value
8004 * Return: 0 on success, -1 on invalid value
8005 */
8006static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8007 u32 *wmi_value)
8008{
8009 int ret = 0;
8010
8011 switch (nl80211_value) {
8012 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8013 *wmi_value = WMI_SAR_FEATURE_OFF;
8014 break;
8015 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8016 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8017 break;
8018 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8019 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8020 break;
8021 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8022 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8023 break;
8024 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8025 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8026 break;
8027 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8028 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8029 break;
8030 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8031 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8032 break;
8033 default:
8034 ret = -1;
8035 }
8036 return ret;
8037}
8038
8039/**
8040 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8041 * @nl80211_value: Vendor command attribute value
8042 * @wmi_value: Pointer to return converted WMI return value
8043 *
8044 * Convert NL80211 vendor command value for SAR BAND to WMI value
8045 * Return: 0 on success, -1 on invalid value
8046 */
8047static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8048{
8049 int ret = 0;
8050
8051 switch (nl80211_value) {
8052 case NL80211_BAND_2GHZ:
8053 *wmi_value = WMI_SAR_2G_ID;
8054 break;
8055 case NL80211_BAND_5GHZ:
8056 *wmi_value = WMI_SAR_5G_ID;
8057 break;
8058 default:
8059 ret = -1;
8060 }
8061 return ret;
8062}
8063
8064/**
8065 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8066 * @nl80211_value: Vendor command attribute value
8067 * @wmi_value: Pointer to return converted WMI return value
8068 *
8069 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8070 * Return: 0 on success, -1 on invalid value
8071 */
8072static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8073 u32 *wmi_value)
8074{
8075 int ret = 0;
8076
8077 switch (nl80211_value) {
8078 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8079 *wmi_value = WMI_SAR_MOD_CCK;
8080 break;
8081 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8082 *wmi_value = WMI_SAR_MOD_OFDM;
8083 break;
8084 default:
8085 ret = -1;
8086 }
8087 return ret;
8088}
8089
8090
8091/**
8092 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8093 * @wiphy: Pointer to wireless phy
8094 * @wdev: Pointer to wireless device
8095 * @data: Pointer to data
8096 * @data_len: Length of @data
8097 *
8098 * This function is used to setup Specific Absorption Rate limit specs.
8099 *
8100 * Return: 0 on success, negative errno on failure
8101 */
8102static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8103 struct wireless_dev *wdev,
8104 const void *data, int data_len)
8105{
8106 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8107 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8108 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8109 *sar_spec_list;
8110 struct sar_limit_cmd_params sar_limit_cmd = {0};
8111 int ret = -EINVAL, i = 0, rem = 0;
8112
8113 ENTER();
8114
8115 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8116 hdd_err("Command not allowed in FTM mode");
8117 return -EPERM;
8118 }
8119
8120 if (wlan_hdd_validate_context(hdd_ctx))
8121 return -EINVAL;
8122
8123 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8124 data, data_len, NULL)) {
8125 hdd_err("Invalid SAR attributes");
8126 return -EINVAL;
8127 }
8128
8129 /* Vendor command manadates all SAR Specs in single call */
8130 sar_limit_cmd.commit_limits = 1;
8131 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
8132 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
8133 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
8134 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
8135 &sar_limit_cmd.sar_enable) < 0) {
8136 hdd_err("Invalid SAR Enable attr");
8137 goto fail;
8138 }
8139 }
8140 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
8141
8142 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
8143 sar_limit_cmd.num_limit_rows = nla_get_u32(
8144 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
8145 hdd_info("attr sar num_limit_rows %d",
8146 sar_limit_cmd.num_limit_rows);
8147 }
8148 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
8149 hdd_err("SAR Spec list exceed supported size");
8150 goto fail;
8151 }
8152 if (sar_limit_cmd.num_limit_rows == 0)
8153 goto send_sar_limits;
8154 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
8155 struct sar_limit_cmd_row) *
8156 sar_limit_cmd.num_limit_rows);
8157 if (!sar_limit_cmd.sar_limit_row_list) {
8158 ret = -ENOMEM;
8159 goto fail;
8160 }
8161 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
8162 hdd_err("Invalid SAR SPECs list");
8163 goto fail;
8164 }
8165
8166 nla_for_each_nested(sar_spec_list,
8167 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
8168 if (i == sar_limit_cmd.num_limit_rows) {
8169 hdd_warn("SAR Cmd has excess SPECs in list");
8170 break;
8171 }
8172
8173 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8174 nla_data(sar_spec_list), nla_len(sar_spec_list),
8175 NULL)) {
8176 hdd_err("nla_parse failed for SAR Spec list");
8177 goto fail;
8178 }
8179 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
8180 if (sar_spec[
8181 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
8182 sar_limit_cmd.sar_limit_row_list[i].limit_value =
8183 nla_get_u32(sar_spec[
8184 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
8185 } else {
8186 hdd_err("SAR Spec does not have power limit value");
8187 goto fail;
8188 }
8189
8190 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
8191 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
8192 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
8193 &sar_limit_cmd.sar_limit_row_list[i].band_id)
8194 < 0) {
8195 hdd_err("Invalid SAR Band attr");
8196 goto fail;
8197 }
8198 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8199 WMI_SAR_BAND_ID_VALID_MASK;
8200 }
8201 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
8202 sar_limit_cmd.sar_limit_row_list[i].chain_id =
8203 nla_get_u32(sar_spec[
8204 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
8205 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8206 WMI_SAR_CHAIN_ID_VALID_MASK;
8207 }
8208 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
8209 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
8210 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
8211 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
8212 < 0) {
8213 hdd_err("Invalid SAR Modulation attr");
8214 goto fail;
8215 }
8216 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8217 WMI_SAR_MOD_ID_VALID_MASK;
8218 }
8219 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
8220 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
8221 sar_limit_cmd.sar_limit_row_list[i].chain_id,
8222 sar_limit_cmd.sar_limit_row_list[i].mod_id,
8223 sar_limit_cmd.sar_limit_row_list[i].limit_value,
8224 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
8225 i++;
8226 }
8227
8228 if (i < sar_limit_cmd.num_limit_rows) {
8229 hdd_warn("SAR Cmd has less SPECs in list");
8230 sar_limit_cmd.num_limit_rows = i;
8231 }
8232
8233send_sar_limits:
8234 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
8235 QDF_STATUS_SUCCESS)
8236 ret = 0;
8237fail:
8238 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
8239 return ret;
8240}
8241
8242/**
8243 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
8244 * @wiphy: Pointer to wireless phy
8245 * @wdev: Pointer to wireless device
8246 * @data: Pointer to data
8247 * @data_len: Length of @data
8248 *
8249 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
8250 *
8251 * Return: 0 on success, negative errno on failure
8252 */
8253static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
8254 struct wireless_dev *wdev,
8255 const void *data,
8256 int data_len)
8257{
8258 int ret;
8259
8260 cds_ssr_protect(__func__);
8261 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
8262 data_len);
8263 cds_ssr_unprotect(__func__);
8264
8265 return ret;
8266}
8267
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308268static const struct
8269nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
8270 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
8271 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
8272 .len = QDF_MAC_ADDR_SIZE},
8273};
8274
8275/**
8276 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8277 * @wiphy: Pointer to wireless phy
8278 * @wdev: Pointer to wireless device
8279 * @data: Pointer to data
8280 * @data_len: Length of @data
8281 *
8282 * This function is used to enable/disable roaming using vendor commands
8283 *
8284 * Return: 0 on success, negative errno on failure
8285 */
8286static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8287 struct wireless_dev *wdev,
8288 const void *data, int data_len)
8289{
8290 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8291 struct net_device *dev = wdev->netdev;
8292 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8293 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8294 uint32_t is_fast_roam_enabled;
8295 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308296 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308297
8298 ENTER_DEV(dev);
8299
8300 ret = wlan_hdd_validate_context(hdd_ctx);
8301 if (0 != ret)
8302 return ret;
8303
8304 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8305 hdd_err("Command not allowed in FTM mode");
8306 return -EINVAL;
8307 }
8308
8309 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
8310 qca_wlan_vendor_attr);
8311 if (ret) {
8312 hdd_err("Invalid ATTR");
8313 return -EINVAL;
8314 }
8315
8316 /* Parse and fetch Enable flag */
8317 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
8318 hdd_err("attr enable failed");
8319 return -EINVAL;
8320 }
8321
8322 is_fast_roam_enabled = nla_get_u32(
8323 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008324 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
8325 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308326
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008327 if (!adapter->fast_roaming_allowed) {
8328 hdd_err("fast roaming not allowed on %s interface",
8329 adapter->dev->name);
8330 return -EINVAL;
8331 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308332 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308333 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008334 (is_fast_roam_enabled &&
8335 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308336 if (qdf_status != QDF_STATUS_SUCCESS)
8337 hdd_err("sme_config_fast_roaming failed with status=%d",
8338 qdf_status);
8339 ret = qdf_status_to_os_return(qdf_status);
8340
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308341 EXIT();
8342 return ret;
8343}
8344
8345/**
8346 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8347 * @wiphy: Pointer to wireless phy
8348 * @wdev: Pointer to wireless device
8349 * @data: Pointer to data
8350 * @data_len: Length of @data
8351 *
8352 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8353 *
8354 * Return: 0 on success, negative errno on failure
8355 */
8356static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8357 struct wireless_dev *wdev,
8358 const void *data, int data_len)
8359{
8360 int ret;
8361
8362 cds_ssr_protect(__func__);
8363 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8364 cds_ssr_unprotect(__func__);
8365
8366 return ret;
8367}
8368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008369const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8370 {
8371 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8372 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8373 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308374 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008375 .doit = is_driver_dfs_capable
8376 },
8377
8378#ifdef WLAN_FEATURE_NAN
8379 {
8380 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8381 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8382 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8383 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8384 .doit = wlan_hdd_cfg80211_nan_request
8385 },
8386#endif
8387
8388#ifdef WLAN_FEATURE_STATS_EXT
8389 {
8390 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8391 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8392 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8393 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8394 .doit = wlan_hdd_cfg80211_stats_ext_request
8395 },
8396#endif
8397#ifdef FEATURE_WLAN_EXTSCAN
8398 {
8399 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8400 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8401 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8402 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8403 .doit = wlan_hdd_cfg80211_extscan_start
8404 },
8405 {
8406 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8407 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8408 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8409 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8410 .doit = wlan_hdd_cfg80211_extscan_stop
8411 },
8412 {
8413 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8414 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8415 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8416 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8417 },
8418 {
8419 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8420 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8421 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8422 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8423 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8424 },
8425 {
8426 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8427 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8428 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8429 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8430 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8431 },
8432 {
8433 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8434 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8435 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8436 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8437 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8438 },
8439 {
8440 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8441 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8442 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8443 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8444 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8445 },
8446 {
8447 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8448 .info.subcmd =
8449 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8450 .flags =
8451 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8452 WIPHY_VENDOR_CMD_NEED_RUNNING,
8453 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8454 },
8455 {
8456 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8457 .info.subcmd =
8458 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8459 .flags =
8460 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8461 WIPHY_VENDOR_CMD_NEED_RUNNING,
8462 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8463 },
8464 {
8465 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8466 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8467 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8468 WIPHY_VENDOR_CMD_NEED_NETDEV |
8469 WIPHY_VENDOR_CMD_NEED_RUNNING,
8470 .doit = wlan_hdd_cfg80211_set_epno_list
8471 },
8472#endif /* FEATURE_WLAN_EXTSCAN */
8473
8474#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8475 {
8476 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8477 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8478 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8479 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8480 .doit = wlan_hdd_cfg80211_ll_stats_clear
8481 },
8482
8483 {
8484 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8485 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8486 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8487 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8488 .doit = wlan_hdd_cfg80211_ll_stats_set
8489 },
8490
8491 {
8492 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8493 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8494 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8495 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8496 .doit = wlan_hdd_cfg80211_ll_stats_get
8497 },
8498#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8499#ifdef FEATURE_WLAN_TDLS
8500 {
8501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8504 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8505 .doit = wlan_hdd_cfg80211_exttdls_enable
8506 },
8507 {
8508 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8509 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8510 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8511 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8512 .doit = wlan_hdd_cfg80211_exttdls_disable
8513 },
8514 {
8515 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8516 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8517 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8518 .doit = wlan_hdd_cfg80211_exttdls_get_status
8519 },
8520#endif
8521 {
8522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8525 .doit = wlan_hdd_cfg80211_get_supported_features
8526 },
8527 {
8528 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8529 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8530 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8531 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8532 },
8533 {
8534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308537 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008538 },
8539 {
8540 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8541 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8542 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8543 WIPHY_VENDOR_CMD_NEED_NETDEV,
8544 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8545 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008546 {
8547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8550 WIPHY_VENDOR_CMD_NEED_NETDEV,
8551 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8552 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008553 {
8554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308555 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8556 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8557 WIPHY_VENDOR_CMD_NEED_NETDEV |
8558 WIPHY_VENDOR_CMD_NEED_RUNNING,
8559 .doit = hdd_cfg80211_get_station_cmd
8560 },
8561 {
8562 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8564 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8565 WIPHY_VENDOR_CMD_NEED_NETDEV |
8566 WIPHY_VENDOR_CMD_NEED_RUNNING,
8567 .doit = wlan_hdd_cfg80211_do_acs
8568 },
8569
8570 {
8571 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8572 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8573 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8574 WIPHY_VENDOR_CMD_NEED_NETDEV,
8575 .doit = wlan_hdd_cfg80211_get_features
8576 },
8577#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8578 {
8579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8582 WIPHY_VENDOR_CMD_NEED_NETDEV |
8583 WIPHY_VENDOR_CMD_NEED_RUNNING,
8584 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8585 },
8586#endif
8587#ifdef FEATURE_WLAN_EXTSCAN
8588 {
8589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8592 WIPHY_VENDOR_CMD_NEED_NETDEV |
8593 WIPHY_VENDOR_CMD_NEED_RUNNING,
8594 .doit = wlan_hdd_cfg80211_set_passpoint_list
8595 },
8596 {
8597 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8598 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8599 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8600 WIPHY_VENDOR_CMD_NEED_NETDEV |
8601 WIPHY_VENDOR_CMD_NEED_RUNNING,
8602 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8603 },
8604 {
8605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8608 WIPHY_VENDOR_CMD_NEED_NETDEV |
8609 WIPHY_VENDOR_CMD_NEED_RUNNING,
8610 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8611 },
8612 {
8613 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8614 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8616 WIPHY_VENDOR_CMD_NEED_NETDEV |
8617 WIPHY_VENDOR_CMD_NEED_RUNNING,
8618 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8619 },
8620#endif /* FEATURE_WLAN_EXTSCAN */
8621 {
8622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8625 WIPHY_VENDOR_CMD_NEED_NETDEV,
8626 .doit = wlan_hdd_cfg80211_get_wifi_info
8627 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008628#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008629 {
8630 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8631 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8632 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8633 WIPHY_VENDOR_CMD_NEED_NETDEV |
8634 WIPHY_VENDOR_CMD_NEED_RUNNING,
8635 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8636 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008637#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008638 {
8639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8642 WIPHY_VENDOR_CMD_NEED_NETDEV,
8643 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8644 },
8645 {
8646 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8647 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8648 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8649 WIPHY_VENDOR_CMD_NEED_NETDEV,
8650 .doit = wlan_hdd_cfg80211_wifi_logger_start
8651 },
8652 {
8653 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8654 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8655 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8656 WIPHY_VENDOR_CMD_NEED_NETDEV,
8657 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8658 },
8659 {
8660 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8661 .info.subcmd =
8662 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8664 WIPHY_VENDOR_CMD_NEED_NETDEV |
8665 WIPHY_VENDOR_CMD_NEED_RUNNING,
8666 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8667 },
8668 {
8669 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8670 .info.subcmd =
8671 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8672 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8673 WIPHY_VENDOR_CMD_NEED_NETDEV |
8674 WIPHY_VENDOR_CMD_NEED_RUNNING,
8675 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8676 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008677#ifdef WLAN_FEATURE_TSF
8678 {
8679 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8680 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8681 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8682 WIPHY_VENDOR_CMD_NEED_NETDEV |
8683 WIPHY_VENDOR_CMD_NEED_RUNNING,
8684 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8685 },
8686#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008687#ifdef FEATURE_WLAN_TDLS
8688 {
8689 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8690 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8691 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8692 WIPHY_VENDOR_CMD_NEED_NETDEV |
8693 WIPHY_VENDOR_CMD_NEED_RUNNING,
8694 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8695 },
8696#endif
8697#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8698 {
8699 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8700 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8701 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8702 WIPHY_VENDOR_CMD_NEED_NETDEV |
8703 WIPHY_VENDOR_CMD_NEED_RUNNING,
8704 .doit = wlan_hdd_cfg80211_offloaded_packets
8705 },
8706#endif
8707 {
8708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8709 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8710 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8711 WIPHY_VENDOR_CMD_NEED_NETDEV |
8712 WIPHY_VENDOR_CMD_NEED_RUNNING,
8713 .doit = wlan_hdd_cfg80211_monitor_rssi
8714 },
8715 {
8716 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308717 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8718 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8719 WIPHY_VENDOR_CMD_NEED_NETDEV |
8720 WIPHY_VENDOR_CMD_NEED_RUNNING,
8721 .doit = wlan_hdd_cfg80211_set_ns_offload
8722 },
8723 {
8724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008725 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8726 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8727 WIPHY_VENDOR_CMD_NEED_NETDEV |
8728 WIPHY_VENDOR_CMD_NEED_RUNNING,
8729 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8730 },
8731#ifdef WLAN_FEATURE_MEMDUMP
8732 {
8733 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8734 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8735 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8736 WIPHY_VENDOR_CMD_NEED_NETDEV |
8737 WIPHY_VENDOR_CMD_NEED_RUNNING,
8738 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8739 },
8740#endif /* WLAN_FEATURE_MEMDUMP */
8741 {
8742 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8743 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8744 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8745 WIPHY_VENDOR_CMD_NEED_NETDEV |
8746 WIPHY_VENDOR_CMD_NEED_RUNNING,
8747 .doit = wlan_hdd_cfg80211_vendor_scan
8748 },
8749
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05308750 /* Vendor abort scan */
8751 {
8752 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8753 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
8754 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8755 WIPHY_VENDOR_CMD_NEED_NETDEV |
8756 WIPHY_VENDOR_CMD_NEED_RUNNING,
8757 .doit = wlan_hdd_vendor_abort_scan
8758 },
8759
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008760 /* OCB commands */
8761 {
8762 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8763 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8764 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8765 WIPHY_VENDOR_CMD_NEED_NETDEV |
8766 WIPHY_VENDOR_CMD_NEED_RUNNING,
8767 .doit = wlan_hdd_cfg80211_ocb_set_config
8768 },
8769 {
8770 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8771 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8772 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8773 WIPHY_VENDOR_CMD_NEED_NETDEV |
8774 WIPHY_VENDOR_CMD_NEED_RUNNING,
8775 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8776 },
8777 {
8778 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8779 .info.subcmd =
8780 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8782 WIPHY_VENDOR_CMD_NEED_NETDEV |
8783 WIPHY_VENDOR_CMD_NEED_RUNNING,
8784 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8785 },
8786 {
8787 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8788 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8789 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8790 WIPHY_VENDOR_CMD_NEED_NETDEV |
8791 WIPHY_VENDOR_CMD_NEED_RUNNING,
8792 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8793 },
8794 {
8795 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8796 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8797 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8798 WIPHY_VENDOR_CMD_NEED_NETDEV |
8799 WIPHY_VENDOR_CMD_NEED_RUNNING,
8800 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8801 },
8802 {
8803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8804 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8805 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8806 WIPHY_VENDOR_CMD_NEED_NETDEV |
8807 WIPHY_VENDOR_CMD_NEED_RUNNING,
8808 .doit = wlan_hdd_cfg80211_dcc_get_stats
8809 },
8810 {
8811 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8812 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8813 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8814 WIPHY_VENDOR_CMD_NEED_NETDEV |
8815 WIPHY_VENDOR_CMD_NEED_RUNNING,
8816 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8817 },
8818 {
8819 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8820 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8821 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8822 WIPHY_VENDOR_CMD_NEED_NETDEV |
8823 WIPHY_VENDOR_CMD_NEED_RUNNING,
8824 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8825 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308826 {
8827 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8828 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8829 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8830 WIPHY_VENDOR_CMD_NEED_NETDEV |
8831 WIPHY_VENDOR_CMD_NEED_RUNNING,
8832 .doit = wlan_hdd_cfg80211_get_link_properties
8833 },
Peng Xu278d0122015-09-24 16:34:17 -07008834 {
Peng Xud2220962016-07-11 17:59:17 -07008835 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008836 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8837 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8838 WIPHY_VENDOR_CMD_NEED_NETDEV |
8839 WIPHY_VENDOR_CMD_NEED_RUNNING,
8840 .doit = wlan_hdd_cfg80211_set_ota_test
8841 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008842#ifdef FEATURE_LFR_SUBNET_DETECTION
8843 {
8844 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8845 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8846 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8847 WIPHY_VENDOR_CMD_NEED_NETDEV |
8848 WIPHY_VENDOR_CMD_NEED_RUNNING,
8849 .doit = wlan_hdd_cfg80211_set_gateway_params
8850 },
8851#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008852 {
Peng Xud2220962016-07-11 17:59:17 -07008853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8856 WIPHY_VENDOR_CMD_NEED_NETDEV |
8857 WIPHY_VENDOR_CMD_NEED_RUNNING,
8858 .doit = wlan_hdd_cfg80211_txpower_scale
8859 },
8860 {
8861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8862 .info.subcmd =
8863 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8864 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8865 WIPHY_VENDOR_CMD_NEED_NETDEV |
8866 WIPHY_VENDOR_CMD_NEED_RUNNING,
8867 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8868 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308869 {
8870 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8871 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8872 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8873 WIPHY_VENDOR_CMD_NEED_NETDEV |
8874 WIPHY_VENDOR_CMD_NEED_RUNNING,
8875 .doit = wlan_hdd_cfg80211_bpf_offload
8876 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308877 {
8878 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308879 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8880 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8881 WIPHY_VENDOR_CMD_NEED_NETDEV |
8882 WIPHY_VENDOR_CMD_NEED_RUNNING,
8883 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8884 },
8885 {
8886 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308887 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8888 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8889 WIPHY_VENDOR_CMD_NEED_NETDEV |
8890 WIPHY_VENDOR_CMD_NEED_RUNNING,
8891 .doit = wlan_hdd_cfg80211_sta_roam_policy
8892 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308893#ifdef FEATURE_WLAN_CH_AVOID
8894 {
8895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8898 WIPHY_VENDOR_CMD_NEED_NETDEV |
8899 WIPHY_VENDOR_CMD_NEED_RUNNING,
8900 .doit = wlan_hdd_cfg80211_avoid_freq
8901 },
8902#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308903 {
8904 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308905 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8907 WIPHY_VENDOR_CMD_NEED_NETDEV |
8908 WIPHY_VENDOR_CMD_NEED_RUNNING,
8909 .doit = wlan_hdd_cfg80211_sap_configuration_set
8910 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008911 {
Peng Xu4225c152016-07-14 21:18:14 -07008912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008913 .info.subcmd =
8914 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8915 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8916 WIPHY_VENDOR_CMD_NEED_NETDEV |
8917 WIPHY_VENDOR_CMD_NEED_RUNNING,
8918 .doit = wlan_hdd_cfg80211_p2p_lo_start
8919 },
8920 {
8921 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8922 .info.subcmd =
8923 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8924 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8925 WIPHY_VENDOR_CMD_NEED_NETDEV |
8926 WIPHY_VENDOR_CMD_NEED_RUNNING,
8927 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8928 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308929 {
8930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8931 .info.subcmd =
8932 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8934 WIPHY_VENDOR_CMD_NEED_NETDEV |
8935 WIPHY_VENDOR_CMD_NEED_RUNNING,
8936 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8937 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008938#ifdef WLAN_FEATURE_NAN_DATAPATH
8939 {
8940 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8941 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8943 WIPHY_VENDOR_CMD_NEED_NETDEV |
8944 WIPHY_VENDOR_CMD_NEED_RUNNING,
8945 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8946 },
8947#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308948 {
8949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8952 WIPHY_VENDOR_CMD_NEED_NETDEV |
8953 WIPHY_VENDOR_CMD_NEED_RUNNING,
8954 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8955 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308956 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8958 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8960 WIPHY_VENDOR_CMD_NEED_NETDEV |
8961 WIPHY_VENDOR_CMD_NEED_RUNNING,
8962 .doit = wlan_hdd_cfg80211_get_bus_size
8963 },
8964 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308965 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8966 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8967 WIPHY_VENDOR_CMD_NEED_NETDEV |
8968 WIPHY_VENDOR_CMD_NEED_RUNNING,
8969 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308970 },
8971 {
8972 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8973 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8974 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8975 WIPHY_VENDOR_CMD_NEED_NETDEV |
8976 WIPHY_VENDOR_CMD_NEED_RUNNING,
8977 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308978 },
8979#ifdef WLAN_FEATURE_DISA
8980 {
8981 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8982 .info.subcmd =
8983 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8985 WIPHY_VENDOR_CMD_NEED_NETDEV |
8986 WIPHY_VENDOR_CMD_NEED_RUNNING,
8987 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8988 },
8989#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008990#ifdef FEATURE_WLAN_TDLS
8991 {
8992 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8993 .info.subcmd =
8994 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
8995 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8996 WIPHY_VENDOR_CMD_NEED_NETDEV |
8997 WIPHY_VENDOR_CMD_NEED_RUNNING,
8998 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008999 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009000#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009001 {
9002 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9003 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
9004 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9005 WIPHY_VENDOR_CMD_NEED_RUNNING,
9006 .doit = wlan_hdd_cfg80211_set_sar_power_limits
9007 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009008#ifdef WLAN_UMAC_CONVERGENCE
9009 COMMON_VENDOR_COMMANDS
9010#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009011};
9012
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309013#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
9014 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
9015 defined(FEATURE_WLAN_SCAN_PNO)
9016/**
9017 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
9018 * @wiphy: pointer to wiphy
9019 * @config: pointer to config
9020 *
9021 * Return: None
9022 */
9023static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9024 struct hdd_config *config)
9025{
9026 if (config->configPNOScanSupport) {
9027 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9028 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
9029 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
9030 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
9031 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
9032 if (config->max_sched_scan_plan_interval)
9033 wiphy->max_sched_scan_plan_interval =
9034 config->max_sched_scan_plan_interval;
9035 if (config->max_sched_scan_plan_iterations)
9036 wiphy->max_sched_scan_plan_iterations =
9037 config->max_sched_scan_plan_iterations;
9038 }
9039}
9040#else
9041static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9042 struct hdd_config *config)
9043{
9044}
9045#endif
9046
9047
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009048/**
9049 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
9050 * @priv_size: Size of the hdd context.
9051 *
9052 * Allocate wiphy context and hdd context.
9053 *
9054 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009055 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009056hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009057{
9058 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009059 hdd_context_t *hdd_ctx;
9060
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009061 ENTER();
9062
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009063 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
9064
9065 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009066 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009067 return NULL;
9068 }
9069
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009070 hdd_ctx = wiphy_priv(wiphy);
9071
9072 hdd_ctx->wiphy = wiphy;
9073
9074 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009075}
9076
9077/*
9078 * FUNCTION: wlan_hdd_cfg80211_update_band
9079 * This function is called from the supplicant through a
9080 * private ioctl to change the band value
9081 */
9082int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
9083{
9084 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07009085 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009086
9087 ENTER();
9088
Dustin Browna30892e2016-10-12 17:28:36 -07009089 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009090
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009091 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009092 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009093
9094 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9095 struct ieee80211_supported_band *band = wiphy->bands[i];
9096
9097 channelEnabledState =
9098 cds_get_channel_state(band->channels[j].
9099 hw_value);
9100
Dustin Browna30892e2016-10-12 17:28:36 -07009101 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009102 /* 5G only */
9103#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9104 /* Enable Social channels for P2P */
9105 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9106 (band->channels[j].center_freq)
9107 && CHANNEL_STATE_ENABLE ==
9108 channelEnabledState)
9109 band->channels[j].flags &=
9110 ~IEEE80211_CHAN_DISABLED;
9111 else
9112#endif
9113 band->channels[j].flags |=
9114 IEEE80211_CHAN_DISABLED;
9115 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009116 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117 eCSR_BAND_24 == eBand) {
9118 /* 2G only */
9119 band->channels[j].flags |=
9120 IEEE80211_CHAN_DISABLED;
9121 continue;
9122 }
9123
Amar Singhal6842e8f2016-02-23 16:30:32 -08009124 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009125 band->channels[j].flags &=
9126 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009127 }
9128 }
9129 return 0;
9130}
9131
9132/*
9133 * FUNCTION: wlan_hdd_cfg80211_init
9134 * This function is called by hdd_wlan_startup()
9135 * during initialization.
9136 * This function is used to initialize and register wiphy structure.
9137 */
9138int wlan_hdd_cfg80211_init(struct device *dev,
9139 struct wiphy *wiphy, struct hdd_config *pCfg)
9140{
9141 int i, j;
9142 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9143
9144 ENTER();
9145
9146 /* Now bind the underlying wlan device with wiphy */
9147 set_wiphy_dev(wiphy, dev);
9148
9149 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
9150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009151#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9152 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009153 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009154#else
9155 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009156 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009157#endif
9158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009159 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
9160 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
9161 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
9162#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
9163 | WIPHY_FLAG_4ADDR_STATION
9164#endif
9165 | WIPHY_FLAG_OFFCHAN_TX;
9166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009167#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9168 wiphy->wowlan = &wowlan_support_cfg80211_init;
9169#else
9170 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
9171 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
9172 wiphy->wowlan.pattern_min_len = 1;
9173 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
9174#endif
9175
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07009176 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009177#ifdef FEATURE_WLAN_ESE
9178 || pCfg->isEseIniFeatureEnabled
9179#endif
9180 ) {
9181 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9182 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009183#ifdef FEATURE_WLAN_TDLS
9184 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
9185 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
9186#endif
9187
9188 wiphy->features |= NL80211_FEATURE_HT_IBSS;
9189
Naveen Rawatc77e6e72016-08-05 15:19:03 -07009190#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
9191 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
9192#endif
9193
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309194 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009195
9196#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05309197 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009198#endif
9199
9200 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009201 * driver can still register regulatory callback and
9202 * it will get regulatory settings in wiphy->band[], but
9203 * driver need to determine what to do with both
9204 * regulatory settings
9205 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009206
9207 wiphy->reg_notifier = hdd_reg_notifier;
9208
9209#if defined QCA_WIFI_FTM
9210}
9211#endif
9212
9213 wiphy->max_scan_ssids = MAX_SCAN_SSID;
9214
9215 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
9216
9217 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
9218
Arun Khandavallifae92942016-08-01 13:31:08 +05309219 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
9220 | BIT(NL80211_IFTYPE_ADHOC)
9221 | BIT(NL80211_IFTYPE_P2P_CLIENT)
9222 | BIT(NL80211_IFTYPE_P2P_GO)
9223 | BIT(NL80211_IFTYPE_AP)
9224 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009225
Arun Khandavallifae92942016-08-01 13:31:08 +05309226 if (pCfg->advertiseConcurrentOperation) {
9227 if (pCfg->enableMCC) {
9228 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07009229
Arun Khandavallifae92942016-08-01 13:31:08 +05309230 for (i = 0;
9231 i < ARRAY_SIZE(wlan_hdd_iface_combination);
9232 i++) {
9233 if (!pCfg->allowMCCGODiffBI)
9234 wlan_hdd_iface_combination[i].
9235 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009236 }
9237 }
9238 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05309239 ARRAY_SIZE(wlan_hdd_iface_combination);
9240 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009241 }
9242
9243 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009244 * on ini values
9245 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009246 if (!pCfg->ShortGI20MhzEnable) {
9247 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
9248 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009249 }
9250
9251 if (!pCfg->ShortGI40MhzEnable) {
9252 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
9253 }
9254
9255 if (!pCfg->nChannelBondingMode5GHz) {
9256 wlan_hdd_band_5_ghz.ht_cap.cap &=
9257 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
9258 }
9259
Abhishek Singhf512bf32016-05-04 16:47:46 +05309260 /*
9261 * In case of static linked driver at the time of driver unload,
9262 * module exit doesn't happens. Module cleanup helps in cleaning
9263 * of static memory.
9264 * If driver load happens statically, at the time of driver unload,
9265 * wiphy flags don't get reset because of static memory.
9266 * It's better not to store channel in static memory.
9267 */
Dustin Browna30892e2016-10-12 17:28:36 -07009268 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
9269 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309270 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009271 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309272 hdd_err("Not enough memory to allocate channels");
9273 return -ENOMEM;
9274 }
Dustin Browna30892e2016-10-12 17:28:36 -07009275 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309276 &hdd_channels_2_4_ghz[0],
9277 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05309278 if ((hdd_is_5g_supported(pHddCtx)) &&
9279 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
9280 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
9281 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
9282 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07009283 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
9284 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309285 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009286 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309287 hdd_err("Not enough memory to allocate channels");
9288 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07009289 bands[NL80211_BAND_2GHZ]->channels);
9290 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05309291 return -ENOMEM;
9292 }
Dustin Browna30892e2016-10-12 17:28:36 -07009293 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309294 &hdd_channels_5_ghz[0],
9295 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009296 }
9297
Dustin Browna30892e2016-10-12 17:28:36 -07009298 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009300 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009301 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009302
9303 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9304 struct ieee80211_supported_band *band = wiphy->bands[i];
9305
Dustin Browna30892e2016-10-12 17:28:36 -07009306 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009307 eCSR_BAND_5G == pCfg->nBandCapability) {
9308 /* 5G only */
9309#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9310 /* Enable social channels for P2P */
9311 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9312 (band->channels[j].center_freq))
9313 band->channels[j].flags &=
9314 ~IEEE80211_CHAN_DISABLED;
9315 else
9316#endif
9317 band->channels[j].flags |=
9318 IEEE80211_CHAN_DISABLED;
9319 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009320 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009321 eCSR_BAND_24 == pCfg->nBandCapability) {
9322 /* 2G only */
9323 band->channels[j].flags |=
9324 IEEE80211_CHAN_DISABLED;
9325 continue;
9326 }
9327 }
9328 }
9329 /*Initialise the supported cipher suite details */
9330 wiphy->cipher_suites = hdd_cipher_suites;
9331 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
9332
9333 /*signal strength in mBm (100*dBm) */
9334 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9335 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
9336
Anurag Chouhan6d760662016-02-20 16:05:43 +05309337 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009338 wiphy->n_vendor_commands =
9339 ARRAY_SIZE(hdd_wiphy_vendor_commands);
9340 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
9341
9342 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
9343 wiphy->n_vendor_events =
9344 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
9345 }
9346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347 if (pCfg->enableDFSMasterCap) {
9348 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
9349 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009350
9351 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
9352
9353#ifdef QCA_HT_2040_COEX
9354 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9355#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309356 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309357 hdd_add_channel_switch_support(&wiphy->flags);
9358
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009359 EXIT();
9360 return 0;
9361}
9362
Abhishek Singhf512bf32016-05-04 16:47:46 +05309363/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009364 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9365 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309366 *
9367 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309368 * memory allocated in wlan_hdd_cfg80211_init also
9369 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309370 *
9371 * Return: void
9372 */
9373void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9374{
9375 int i;
9376
Dustin Browna30892e2016-10-12 17:28:36 -07009377 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309378 if (NULL != wiphy->bands[i] &&
9379 (NULL != wiphy->bands[i]->channels)) {
9380 qdf_mem_free(wiphy->bands[i]->channels);
9381 wiphy->bands[i]->channels = NULL;
9382 }
9383 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309384 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309385}
9386
Yingying Tang80e15f32016-09-27 18:23:01 +08009387/**
9388 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9389 * @hdd_ctx: HDD context
9390 *
9391 * this function will update capabilities for supported bands
9392 *
9393 * Return: void
9394 */
9395static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9396{
9397 uint32_t val32;
9398 uint16_t val16;
9399 tSirMacHTCapabilityInfo *ht_cap_info;
9400 QDF_STATUS status;
9401
9402 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9403 if (QDF_STATUS_SUCCESS != status) {
9404 hdd_err("could not get HT capability info");
9405 val32 = 0;
9406 }
9407 val16 = (uint16_t)val32;
9408 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9409
9410 if (ht_cap_info->txSTBC == true) {
9411 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9412 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9413 IEEE80211_HT_CAP_TX_STBC;
9414 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9415 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9416 IEEE80211_HT_CAP_TX_STBC;
9417 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009418
9419 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9420 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9421 vht_cap.vht_supported = 0;
9422 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9423 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9424 vht_cap.vht_supported = 0;
9425 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9426 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009427}
9428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009429/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309430 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009431 * initialization. In wlan_hdd_cfg80211_init, only the
9432 * default values will be initialized. The final initialization
9433 * of all required members can be done here.
9434 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009435void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009436{
Yingying Tang80e15f32016-09-27 18:23:01 +08009437 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9438
9439 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440}
9441
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009442/**
9443 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9444 * @cfg: hdd cfg
9445 *
9446 * this function update 11n mode in hdd cfg
9447 *
9448 * Return: void
9449 */
9450void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9451{
9452 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9453 hdd_notice("support 11ac");
9454 } else {
9455 hdd_notice("not support 11ac");
9456 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9457 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9458 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9459 cfg->sap_p2p_11ac_override = 0;
9460 }
9461 }
9462}
9463
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009464/* In this function we are registering wiphy. */
9465int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9466{
9467 ENTER();
9468 /* Register our wiphy dev with cfg80211 */
9469 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009470 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009471 return -EIO;
9472 }
9473
9474 EXIT();
9475 return 0;
9476}
9477
9478/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009479 * HDD function to update wiphy capability based on target offload status.
9480 *
9481 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
9482 * capability even before downloading firmware to the target. In discrete
9483 * case, host will get know certain offload capability (say sched_scan
9484 * caps) only after downloading firmware to the target and target boots up.
9485 * This function is used to override setting done in wlan_hdd_cfg80211_init()
9486 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009487 */
9488void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9489{
9490#ifdef FEATURE_WLAN_SCAN_PNO
9491 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9492 struct hdd_config *pCfg = pHddCtx->config;
9493
9494 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9495 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009496 * have PNO support.
9497 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009498 if (!pCfg->PnoOffload) {
9499 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9500 wiphy->max_sched_scan_ssids = 0;
9501 wiphy->max_match_sets = 0;
9502 wiphy->max_sched_scan_ie_len = 0;
9503 }
9504#endif
9505}
9506
9507/* This function registers for all frame which supplicant is interested in */
9508void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9509{
9510 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9511 /* Register for all P2P action, public action etc frames */
9512 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9513
9514 ENTER();
9515
Abhishek Singh7996eb72015-12-30 17:24:02 +05309516 /* Register frame indication call back */
9517 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9518
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309519 /* Register for p2p ack indication */
9520 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9521
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009522 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009523 * initialized. Once we will move to 2.6.37 kernel, in which we have
9524 * frame register ops, we will move this code as a part of that
9525 */
9526
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009527 /* GAS Initial Request */
9528 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9529 (uint8_t *) GAS_INITIAL_REQ,
9530 GAS_INITIAL_REQ_SIZE);
9531
9532 /* GAS Initial Response */
9533 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9534 (uint8_t *) GAS_INITIAL_RSP,
9535 GAS_INITIAL_RSP_SIZE);
9536
9537 /* GAS Comeback Request */
9538 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9539 (uint8_t *) GAS_COMEBACK_REQ,
9540 GAS_COMEBACK_REQ_SIZE);
9541
9542 /* GAS Comeback Response */
9543 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9544 (uint8_t *) GAS_COMEBACK_RSP,
9545 GAS_COMEBACK_RSP_SIZE);
9546
9547 /* P2P Public Action */
9548 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9549 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9550 P2P_PUBLIC_ACTION_FRAME_SIZE);
9551
9552 /* P2P Action */
9553 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9554 (uint8_t *) P2P_ACTION_FRAME,
9555 P2P_ACTION_FRAME_SIZE);
9556
9557 /* WNM BSS Transition Request frame */
9558 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9559 (uint8_t *) WNM_BSS_ACTION_FRAME,
9560 WNM_BSS_ACTION_FRAME_SIZE);
9561
9562 /* WNM-Notification */
9563 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9564 (uint8_t *) WNM_NOTIFICATION_FRAME,
9565 WNM_NOTIFICATION_FRAME_SIZE);
9566}
9567
9568void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9569{
9570 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9571 /* Register for all P2P action, public action etc frames */
9572 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9573
9574 ENTER();
9575
9576 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009577 * initialized. Once we will move to 2.6.37 kernel, in which we have
9578 * frame register ops, we will move this code as a part of that
9579 */
9580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581 /* GAS Initial Request */
9582
9583 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9584 (uint8_t *) GAS_INITIAL_REQ,
9585 GAS_INITIAL_REQ_SIZE);
9586
9587 /* GAS Initial Response */
9588 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9589 (uint8_t *) GAS_INITIAL_RSP,
9590 GAS_INITIAL_RSP_SIZE);
9591
9592 /* GAS Comeback Request */
9593 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9594 (uint8_t *) GAS_COMEBACK_REQ,
9595 GAS_COMEBACK_REQ_SIZE);
9596
9597 /* GAS Comeback Response */
9598 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9599 (uint8_t *) GAS_COMEBACK_RSP,
9600 GAS_COMEBACK_RSP_SIZE);
9601
9602 /* P2P Public Action */
9603 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9604 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9605 P2P_PUBLIC_ACTION_FRAME_SIZE);
9606
9607 /* P2P Action */
9608 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9609 (uint8_t *) P2P_ACTION_FRAME,
9610 P2P_ACTION_FRAME_SIZE);
9611
9612 /* WNM-Notification */
9613 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9614 (uint8_t *) WNM_NOTIFICATION_FRAME,
9615 WNM_NOTIFICATION_FRAME_SIZE);
9616}
9617
9618#ifdef FEATURE_WLAN_WAPI
9619void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9620 const uint8_t *mac_addr, const uint8_t *key,
9621 int key_Len)
9622{
9623 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9624 tCsrRoamSetKey setKey;
9625 bool isConnected = true;
9626 int status = 0;
9627 uint32_t roamId = 0xFF;
9628 uint8_t *pKeyPtr = NULL;
9629 int n = 0;
9630
Jeff Johnson46b40792016-06-29 14:03:14 -07009631 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009632 hdd_device_mode_to_string(pAdapter->device_mode),
9633 pAdapter->device_mode);
9634
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309635 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009636 setKey.keyId = key_index; /* Store Key ID */
9637 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9638 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9639 setKey.paeRole = 0; /* the PAE role */
9640 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309641 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309643 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009644 }
9645 setKey.keyLength = key_Len;
9646 pKeyPtr = setKey.Key;
9647 memcpy(pKeyPtr, key, key_Len);
9648
Jeff Johnson46b40792016-06-29 14:03:14 -07009649 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009650 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009651 hdd_notice("WAPI KEY Data[%d]:%02x ",
9652 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009653
9654 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9655 if (isConnected) {
9656 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9657 pAdapter->sessionId, &setKey, &roamId);
9658 }
9659 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009660 hdd_err("sme_roam_set_key returned ERROR status= %d",
9661 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009662 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9663 }
9664}
9665#endif /* FEATURE_WLAN_WAPI */
9666
9667uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9668 uint8_t eid)
9669{
9670 int left = length;
9671 uint8_t *ptr = (uint8_t *)ies_ptr;
9672 uint8_t elem_id, elem_len;
9673
9674 while (left >= 2) {
9675 elem_id = ptr[0];
9676 elem_len = ptr[1];
9677 left -= 2;
9678 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009679 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009680 eid, elem_len, left);
9681 return NULL;
9682 }
9683 if (elem_id == eid) {
9684 return ptr;
9685 }
9686
9687 left -= elem_len;
9688 ptr += (elem_len + 2);
9689 }
9690 return NULL;
9691}
9692
9693/*
9694 * FUNCTION: wlan_hdd_validate_operation_channel
9695 * called by wlan_hdd_cfg80211_start_bss() and
9696 * wlan_hdd_set_channel()
9697 * This function validates whether given channel is part of valid
9698 * channel list.
9699 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309700QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701 int channel)
9702{
9703
9704 uint32_t num_ch = 0;
9705 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9706 u32 indx = 0;
9707 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9708 uint8_t fValidChannel = false, count = 0;
9709 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9710
9711 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9712
9713 if (hdd_pConfig_ini->sapAllowAllChannel) {
9714 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009715 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009716 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717 fValidChannel = true;
9718 break;
9719 }
9720 }
9721 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009722 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309723 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724 }
9725 } else {
9726 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9727 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009728 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309729 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009730 }
9731 for (indx = 0; indx < num_ch; indx++) {
9732 if (channel == valid_ch[indx]) {
9733 break;
9734 }
9735 }
9736
9737 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009738 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309739 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009740 }
9741 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309742 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743
9744}
9745
9746#ifdef DHCP_SERVER_OFFLOAD
9747static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9748{
9749 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9750 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9751 uint8_t numEntries = 0;
9752 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9753 uint8_t num;
9754 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309755 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009756 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009757 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 return;
9759 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9761 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9762 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9763 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9764 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9765 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009766 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009767 goto end;
9768 }
9769 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009770 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009771 goto end;
9772 }
9773 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009774 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009775 goto end;
9776 }
9777 for (num = 0; num < numEntries; num++) {
9778 temp = srv_ip[num];
9779 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9780 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309781 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009782 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009783 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009784 goto end;
9785 }
Jeff Johnson77848112016-06-29 14:52:06 -07009786 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009787end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309788 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009789 return;
9790}
9791#endif /* DHCP_SERVER_OFFLOAD */
9792
9793static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9794 struct net_device *dev,
9795 struct bss_parameters *params)
9796{
9797 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9798 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9799 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309800 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009801
9802 ENTER();
9803
Anurag Chouhan6d760662016-02-20 16:05:43 +05309804 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009805 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009806 return -EINVAL;
9807 }
9808
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309809 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9810 hdd_err("invalid session id: %d", pAdapter->sessionId);
9811 return -EINVAL;
9812 }
9813
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309814 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009815 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9816 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009817 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818 hdd_device_mode_to_string(pAdapter->device_mode),
9819 pAdapter->device_mode, params->ap_isolate);
9820
9821 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9822 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309823 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009824 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009825
Krunal Sonib4326f22016-03-10 13:05:51 -08009826 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9827 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009828 return -EOPNOTSUPP;
9829 }
9830
9831 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009832 * want to update this parameter
9833 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834 if (-1 != params->ap_isolate) {
9835 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9836 !!params->ap_isolate;
9837
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309838 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009839 pAdapter->sessionId,
9840 pAdapter->sessionCtx.
9841 ap.
9842 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309843 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009844 ret = -EINVAL;
9845 }
9846 }
9847
9848 EXIT();
9849 return ret;
9850}
9851
Krunal Soni8c37e322016-02-03 16:08:37 -08009852/**
9853 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9854 * @ndev: pointer to net device provided by supplicant
9855 * @type: type of the interface, upper layer wanted to change
9856 *
9857 * Upper layer provides the new interface mode that needs to be changed
9858 * for given net device
9859 *
9860 * Return: success or failure in terms of integer value
9861 */
9862static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009863 enum nl80211_iftype type)
9864{
Krunal Soni8c37e322016-02-03 16:08:37 -08009865 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9866 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9867 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009868 hdd_wext_state_t *wext;
9869 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309870 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009871
9872 ENTER();
9873
Krunal Soni8c37e322016-02-03 16:08:37 -08009874 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009875 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009876 return 0;
9877 }
9878
9879 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009880 hdd_stop_adapter(hdd_ctx, adapter, true);
9881 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882 wdev->iftype = type;
9883 /*Check for sub-string p2p to confirm its a p2p interface */
9884 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009885 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009886 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009887 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009888 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009889 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009890 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009891 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009892 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009893 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009894 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009895 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9896 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009897 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9898 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009899 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009900 adapter->scan_info.scanAddIE.length;
9901 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309902 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009903 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9904 wext->roamProfile.phyMode =
9905 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9906 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009907 EXIT();
9908 return status;
9909}
9910
9911static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9912 struct net_device *dev,
9913 struct bss_parameters *params)
9914{
9915 int ret;
9916
9917 cds_ssr_protect(__func__);
9918 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9919 cds_ssr_unprotect(__func__);
9920
9921 return ret;
9922}
9923
9924/* FUNCTION: wlan_hdd_change_country_code_cd
9925 * to wait for contry code completion
9926 */
9927void *wlan_hdd_change_country_code_cb(void *pAdapter)
9928{
9929 hdd_adapter_t *call_back_pAdapter = pAdapter;
9930 complete(&call_back_pAdapter->change_country_code);
9931 return NULL;
9932}
9933
Rajeev Kumar98edb772016-01-19 12:42:19 -08009934/**
9935 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9936 * @wiphy: Pointer to the wiphy structure
9937 * @ndev: Pointer to the net device
9938 * @type: Interface type
9939 * @flags: Flags for change interface
9940 * @params: Pointer to change interface parameters
9941 *
9942 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009943 */
9944static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9945 struct net_device *ndev,
9946 enum nl80211_iftype type,
9947 u32 *flags,
9948 struct vif_params *params)
9949{
9950 struct wireless_dev *wdev;
9951 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9952 hdd_context_t *pHddCtx;
9953 tCsrRoamProfile *pRoamProfile = NULL;
9954 eCsrRoamBssType LastBSSType;
9955 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309956 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957 int status;
9958
9959 ENTER();
9960
Anurag Chouhan6d760662016-02-20 16:05:43 +05309961 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009962 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009963 return -EINVAL;
9964 }
9965
9966 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9967 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309968 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009969 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009970
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309971 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9973 pAdapter->sessionId, type));
9974
Jeff Johnson77848112016-06-29 14:52:06 -07009975 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009976 pAdapter->device_mode, type);
9977
Arun Khandavallifae92942016-08-01 13:31:08 +05309978 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9979 if (status) {
9980 hdd_err("Failed to start modules");
9981 return -EINVAL;
9982 }
9983
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009984 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009985 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9986 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009987 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009988 return -EINVAL;
9989 }
9990
9991 pConfig = pHddCtx->config;
9992 wdev = ndev->ieee80211_ptr;
9993
9994 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009995 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009996
9997 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9998
Krunal Sonib4326f22016-03-10 13:05:51 -08009999 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10000 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
10001 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
10002 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010003 hdd_wext_state_t *pWextState =
10004 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10005
10006 pRoamProfile = &pWextState->roamProfile;
10007 LastBSSType = pRoamProfile->BSSType;
10008
10009 switch (type) {
10010 case NL80211_IFTYPE_STATION:
10011 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080010012 case NL80211_IFTYPE_ADHOC:
10013 if (type == NL80211_IFTYPE_ADHOC) {
10014 wlan_hdd_tdls_exit(pAdapter);
10015 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070010016 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080010017 }
10018 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
10019 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010020 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010021 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010022 if (hdd_start_adapter(pAdapter)) {
10023 hdd_err("Failed to start adapter :%d",
10024 pAdapter->device_mode);
10025 return -EINVAL;
10026 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010028 case NL80211_IFTYPE_AP:
10029 case NL80211_IFTYPE_P2P_GO:
10030 {
Jeff Johnson77848112016-06-29 14:52:06 -070010031 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010032 (type ==
10033 NL80211_IFTYPE_AP) ? "SoftAP" :
10034 "P2pGo");
10035
10036 /* Cancel any remain on channel for GO mode */
10037 if (NL80211_IFTYPE_P2P_GO == type) {
10038 wlan_hdd_cancel_existing_remain_on_channel
10039 (pAdapter);
10040 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010041
Arun Khandavallifae92942016-08-01 13:31:08 +053010042 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010043 /* De-init the adapter */
10044 hdd_deinit_adapter(pHddCtx, pAdapter, true);
10045 memset(&pAdapter->sessionCtx, 0,
10046 sizeof(pAdapter->sessionCtx));
10047 pAdapter->device_mode =
10048 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080010049 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
10050 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010051
10052 /*
10053 * Fw will take care incase of concurrency
10054 */
10055
Krunal Sonib4326f22016-03-10 13:05:51 -080010056 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010057 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010058 /* To meet Android requirements create
10059 * a randomized MAC address of the
10060 * form 02:1A:11:Fx:xx:xx
10061 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010062 get_random_bytes(&ndev->dev_addr[3], 3);
10063 ndev->dev_addr[0] = 0x02;
10064 ndev->dev_addr[1] = 0x1A;
10065 ndev->dev_addr[2] = 0x11;
10066 ndev->dev_addr[3] |= 0xF0;
10067 memcpy(pAdapter->macAddressCurrent.
10068 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010069 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 pr_info("wlan: Generated HotSpot BSSID "
10071 MAC_ADDRESS_STR "\n",
10072 MAC_ADDR_ARRAY(ndev->dev_addr));
10073 }
10074
10075 hdd_set_ap_ops(pAdapter->dev);
10076
Arun Khandavallifae92942016-08-01 13:31:08 +053010077 if (hdd_start_adapter(pAdapter)) {
10078 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010079 return -EINVAL;
10080 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010081 /* Interface type changed update in wiphy structure */
10082 if (wdev) {
10083 wdev->iftype = type;
10084 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010085 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010086 return -EINVAL;
10087 }
10088 goto done;
10089 }
10090
10091 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010092 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 type);
10094 return -EOPNOTSUPP;
10095 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010096 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10097 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010098 switch (type) {
10099 case NL80211_IFTYPE_STATION:
10100 case NL80211_IFTYPE_P2P_CLIENT:
10101 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080010102 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
10103 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010104 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010105 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010106 if (hdd_start_adapter(pAdapter)) {
10107 hdd_err("Failed to start adapter :%d",
10108 pAdapter->device_mode);
10109 return -EINVAL;
10110 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010111 goto done;
10112
10113 case NL80211_IFTYPE_AP:
10114 case NL80211_IFTYPE_P2P_GO:
10115 wdev->iftype = type;
10116 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010117 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118 goto done;
10119
10120 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010121 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010122 type);
10123 return -EOPNOTSUPP;
10124 }
10125 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010126 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010127 pAdapter->device_mode);
10128 return -EOPNOTSUPP;
10129 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010130done:
10131 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010132 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010133
Jeff Johnson2ae6f712016-09-23 15:08:48 -070010134 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135
10136 EXIT();
10137 return 0;
10138}
10139
Rajeev Kumar98edb772016-01-19 12:42:19 -080010140/**
10141 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10142 * @wiphy: Pointer to the wiphy structure
10143 * @ndev: Pointer to the net device
10144 * @type: Interface type
10145 * @flags: Flags for change interface
10146 * @params: Pointer to change interface parameters
10147 *
10148 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149 */
10150static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10151 struct net_device *ndev,
10152 enum nl80211_iftype type,
10153 u32 *flags,
10154 struct vif_params *params)
10155{
10156 int ret;
10157
10158 cds_ssr_protect(__func__);
10159 ret =
10160 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
10161 cds_ssr_unprotect(__func__);
10162
10163 return ret;
10164}
10165
10166#ifdef FEATURE_WLAN_TDLS
10167static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
10168 int index, uint8_t match)
10169{
10170 int i;
10171 for (i = 0; i < index; i++) {
10172 if (arr[i] == match)
10173 return true;
10174 }
10175 return false;
10176}
10177#endif
10178
10179/**
10180 * __wlan_hdd_change_station() - change station
10181 * @wiphy: Pointer to the wiphy structure
10182 * @dev: Pointer to the net device.
10183 * @mac: bssid
10184 * @params: Pointer to station parameters
10185 *
10186 * Return: 0 for success, error number on failure.
10187 */
10188#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10189static int __wlan_hdd_change_station(struct wiphy *wiphy,
10190 struct net_device *dev,
10191 const uint8_t *mac,
10192 struct station_parameters *params)
10193#else
10194static int __wlan_hdd_change_station(struct wiphy *wiphy,
10195 struct net_device *dev,
10196 uint8_t *mac,
10197 struct station_parameters *params)
10198#endif
10199{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010200 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10202 hdd_context_t *pHddCtx;
10203 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053010204 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010205#ifdef FEATURE_WLAN_TDLS
10206 tCsrStaParams StaParams = { 0 };
10207 uint8_t isBufSta = 0;
10208 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053010209 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010210#endif
10211 int ret;
10212
10213 ENTER();
10214
Anurag Chouhan6d760662016-02-20 16:05:43 +053010215 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010216 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010217 return -EINVAL;
10218 }
10219
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010220 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221 TRACE_CODE_HDD_CHANGE_STATION,
10222 pAdapter->sessionId, params->listen_interval));
10223
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010224 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10225 hdd_err("invalid session id: %d", pAdapter->sessionId);
10226 return -EINVAL;
10227 }
10228
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010229 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10230 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010231 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010232 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010233
10234 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10235
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010236 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010237
Krunal Sonib4326f22016-03-10 13:05:51 -080010238 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10239 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010240 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
10241 status =
10242 hdd_softap_change_sta_state(pAdapter,
10243 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080010244 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010245
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010246 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010247 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010248 return -EINVAL;
10249 }
10250 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010251 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10252 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253#ifdef FEATURE_WLAN_TDLS
10254 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070010255
10256 if (cds_is_sub_20_mhz_enabled()) {
10257 hdd_err("TDLS not allowed with sub 20 MHz");
10258 return -EINVAL;
10259 }
10260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261 StaParams.capability = params->capability;
10262 StaParams.uapsd_queues = params->uapsd_queues;
10263 StaParams.max_sp = params->max_sp;
10264
10265 /* Convert (first channel , number of channels) tuple to
10266 * the total list of channels. This goes with the assumption
10267 * that if the first channel is < 14, then the next channels
10268 * are an incremental of 1 else an incremental of 4 till the number
10269 * of channels.
10270 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010271 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010272 if (0 != params->supported_channels_len) {
10273 int i = 0, j = 0, k = 0, no_of_channels = 0;
10274 int num_unique_channels;
10275 int next;
10276 for (i = 0;
10277 i < params->supported_channels_len
10278 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
10279 int wifi_chan_index;
10280 if (!wlan_hdd_is_duplicate_channel
10281 (StaParams.supported_channels, j,
10282 params->supported_channels[i])) {
10283 StaParams.
10284 supported_channels[j] =
10285 params->
10286 supported_channels[i];
10287 } else {
10288 continue;
10289 }
10290 wifi_chan_index =
10291 ((StaParams.supported_channels[j] <=
10292 HDD_CHANNEL_14) ? 1 : 4);
10293 no_of_channels =
10294 params->supported_channels[i + 1];
10295
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010296 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 -080010297 StaParams.
10298 supported_channels[j],
10299 wifi_chan_index,
10300 no_of_channels);
10301 for (k = 1; k <= no_of_channels &&
10302 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
10303 k++) {
10304 next =
10305 StaParams.
10306 supported_channels[j] +
10307 wifi_chan_index;
10308 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
10309 StaParams.
10310 supported_channels[j
10311 +
10312 1]
10313 = next;
10314 } else {
10315 continue;
10316 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010317 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 j + 1,
10319 StaParams.
10320 supported_channels[j +
10321 1]);
10322 j += 1;
10323 }
10324 }
10325 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010326 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010327 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010328 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010329 StaParams.
10330 supported_channels[i]);
10331 }
10332 if (MAX_CHANNEL < num_unique_channels)
10333 num_unique_channels = MAX_CHANNEL;
10334 StaParams.supported_channels_len =
10335 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010336 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010337 StaParams.supported_channels_len);
10338 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010339 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340 params->supported_oper_classes,
10341 params->supported_oper_classes_len);
10342 StaParams.supported_oper_classes_len =
10343 params->supported_oper_classes_len;
10344
10345 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010346 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010347 params->ext_capab,
10348 sizeof(StaParams.extn_capability));
10349
10350 if (NULL != params->ht_capa) {
10351 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010352 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010353 sizeof(tSirHTCap));
10354 }
10355
10356 StaParams.supported_rates_len =
10357 params->supported_rates_len;
10358
10359 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
10360 * The supported_rates array , for all the structures propogating till Add Sta
10361 * to the firmware has to be modified , if the supplicant (ieee80211) is
10362 * modified to send more rates.
10363 */
10364
10365 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10366 */
10367 if (StaParams.supported_rates_len >
10368 SIR_MAC_MAX_SUPP_RATES)
10369 StaParams.supported_rates_len =
10370 SIR_MAC_MAX_SUPP_RATES;
10371
10372 if (0 != StaParams.supported_rates_len) {
10373 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010374 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010375 params->supported_rates,
10376 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010377 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010378 StaParams.supported_rates_len);
10379 for (i = 0; i < StaParams.supported_rates_len;
10380 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010381 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010382 StaParams.supported_rates[i]);
10383 }
10384
10385 if (NULL != params->vht_capa) {
10386 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010387 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010388 params->vht_capa,
10389 sizeof(tSirVHTCap));
10390 }
10391
10392 if (0 != params->ext_capab_len) {
10393 /*Define A Macro : TODO Sunil */
10394 if ((1 << 4) & StaParams.extn_capability[3]) {
10395 isBufSta = 1;
10396 }
10397 /* TDLS Channel Switching Support */
10398 if ((1 << 6) & StaParams.extn_capability[3]) {
10399 isOffChannelSupported = 1;
10400 }
10401 }
10402
Nitesh Shah99934ac2016-09-05 15:54:08 +053010403 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010404 (params->ht_capa || params->vht_capa ||
10405 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010406 is_qos_wmm_sta = true;
10407
10408 hdd_notice("%s: TDLS Peer is QOS capable"
10409 " is_qos_wmm_sta= %d HTcapPresent = %d",
10410 __func__, is_qos_wmm_sta,
10411 StaParams.htcap_present);
10412
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010413 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010414 &StaParams,
10415 isBufSta,
10416 isOffChannelSupported,
10417 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010418 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010419 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010420 return -EINVAL;
10421 }
10422
10423 status =
10424 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10425 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010426 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010427 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010428 return -EINVAL;
10429 }
10430 }
10431#endif
10432 }
10433 EXIT();
10434 return ret;
10435}
10436
10437/**
10438 * wlan_hdd_change_station() - cfg80211 change station handler function
10439 * @wiphy: Pointer to the wiphy structure
10440 * @dev: Pointer to the net device.
10441 * @mac: bssid
10442 * @params: Pointer to station parameters
10443 *
10444 * This is the cfg80211 change station handler function which invokes
10445 * the internal function @__wlan_hdd_change_station with
10446 * SSR protection.
10447 *
10448 * Return: 0 for success, error number on failure.
10449 */
10450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10451static int wlan_hdd_change_station(struct wiphy *wiphy,
10452 struct net_device *dev,
10453 const u8 *mac,
10454 struct station_parameters *params)
10455#else
10456static int wlan_hdd_change_station(struct wiphy *wiphy,
10457 struct net_device *dev,
10458 u8 *mac,
10459 struct station_parameters *params)
10460#endif
10461{
10462 int ret;
10463
10464 cds_ssr_protect(__func__);
10465 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10466 cds_ssr_unprotect(__func__);
10467
10468 return ret;
10469}
10470
10471/*
10472 * FUNCTION: __wlan_hdd_cfg80211_add_key
10473 * This function is used to initialize the key information
10474 */
10475static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10476 struct net_device *ndev,
10477 u8 key_index, bool pairwise,
10478 const u8 *mac_addr,
10479 struct key_params *params)
10480{
10481 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10482 tCsrRoamSetKey setKey;
10483 int status;
10484 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010485 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010486 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010487 hdd_context_t *pHddCtx;
10488 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10489
10490 ENTER();
10491
Anurag Chouhan6d760662016-02-20 16:05:43 +053010492 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010493 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010494 return -EINVAL;
10495 }
10496
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010497 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10498 hdd_err("invalid session id: %d", pAdapter->sessionId);
10499 return -EINVAL;
10500 }
10501
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010502 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10504 pAdapter->sessionId, params->key_len));
10505 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10506 status = wlan_hdd_validate_context(pHddCtx);
10507
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010508 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010510
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010511 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010512 hdd_device_mode_to_string(pAdapter->device_mode),
10513 pAdapter->device_mode);
10514
10515 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010516 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010517
10518 return -EINVAL;
10519 }
10520
10521 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010522 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010523
10524 return -EINVAL;
10525 }
10526
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010527 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010528
10529 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010530 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010531 setKey.keyId = key_index;
10532 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010533 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010534
10535 switch (params->cipher) {
10536 case WLAN_CIPHER_SUITE_WEP40:
10537 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10538 break;
10539
10540 case WLAN_CIPHER_SUITE_WEP104:
10541 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10542 break;
10543
10544 case WLAN_CIPHER_SUITE_TKIP:
10545 {
10546 u8 *pKey = &setKey.Key[0];
10547 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10548
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010549 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010550
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010551 /* Supplicant sends the 32bytes key in this order
10552 *
10553 * |--------------|----------|----------|
10554 * | Tk1 |TX-MIC | RX Mic |
10555 * |--------------|----------|----------|
10556 * <---16bytes---><--8bytes--><--8bytes-->
10557 *
10558 * Sme expects the 32 bytes key to be in the below order
10559 *
10560 * |--------------|----------|----------|
10561 * | Tk1 |RX-MIC | TX Mic |
10562 * |--------------|----------|----------|
10563 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010564 */
10565 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010566 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567
10568 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010569 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010570
10571 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010572 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010573
10574 break;
10575 }
10576
10577 case WLAN_CIPHER_SUITE_CCMP:
10578 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10579 break;
10580
10581#ifdef FEATURE_WLAN_WAPI
10582 case WLAN_CIPHER_SUITE_SMS4:
10583 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010584 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010585 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10586 mac_addr, params->key,
10587 params->key_len);
10588 return 0;
10589 }
10590#endif
10591
10592#ifdef FEATURE_WLAN_ESE
10593 case WLAN_CIPHER_SUITE_KRK:
10594 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10595 break;
10596#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10597 case WLAN_CIPHER_SUITE_BTK:
10598 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10599 break;
10600#endif
10601#endif
10602
10603#ifdef WLAN_FEATURE_11W
10604 case WLAN_CIPHER_SUITE_AES_CMAC:
10605 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10606 break;
10607#endif
10608
10609 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010610 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010611 return -EOPNOTSUPP;
10612 }
10613
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010614 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010615
10616 if (!pairwise) {
10617 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010618 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010619 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010620 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010621 } else {
10622 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010623 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010624 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010625 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010626 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010627 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010628 /* if a key is already installed, block all subsequent ones */
10629 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010630 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010631 return 0;
10632 }
10633
10634 setKey.keyDirection = eSIR_TX_RX;
10635 /*Set the group key */
10636 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10637 pAdapter->sessionId, &setKey, &roamId);
10638
10639 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010640 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010641 return -EINVAL;
10642 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010643 /* Save the keys here and call sme_roam_set_key for setting
10644 * the PTK after peer joins the IBSS network
10645 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010646 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010647 &setKey, sizeof(tCsrRoamSetKey));
10648
10649 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10650 return status;
10651 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010652 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10653 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010654 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10655 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010656 status = wlansap_set_key_sta(
10657 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010658 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010659 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010660 __LINE__, status);
10661 }
10662 }
10663
10664 /* Save the key in ap ctx for use on START_BASS and restart */
10665 if (pairwise ||
10666 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10667 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010668 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010669 sizeof(tCsrRoamSetKey));
10670 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010671 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010672 sizeof(tCsrRoamSetKey));
10673
Krunal Sonib4326f22016-03-10 13:05:51 -080010674 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10675 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010676 hdd_wext_state_t *pWextState =
10677 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10678 hdd_station_ctx_t *pHddStaCtx =
10679 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10680
10681 if (!pairwise) {
10682 /* set group key */
10683 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010684 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010685 __func__, __LINE__);
10686 hdd_perform_roam_set_key_complete(pAdapter);
10687 }
10688 }
10689
10690 pWextState->roamProfile.Keys.KeyLength[key_index] =
10691 (u8) params->key_len;
10692
10693 pWextState->roamProfile.Keys.defaultIndex = key_index;
10694
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010695 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010696 KeyMaterial[key_index][0], params->key,
10697 params->key_len);
10698
10699 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10700
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010701 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010702 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10703 setKey.keyDirection);
10704
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010705 /* The supplicant may attempt to set the PTK once
10706 * pre-authentication is done. Save the key in the
10707 * UMAC and include it in the ADD BSS request
10708 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010709 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010710 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010711 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010712 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010713 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010714 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010715 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010716 return -EINVAL;
10717 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010718
10719 /* issue set key request to SME */
10720 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10721 pAdapter->sessionId, &setKey, &roamId);
10722
10723 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010724 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010725 pHddStaCtx->roam_info.roamingState =
10726 HDD_ROAM_STATE_NONE;
10727 return -EINVAL;
10728 }
10729
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010730 /* in case of IBSS as there was no information
10731 * available about WEP keys during IBSS join, group
10732 * key intialized with NULL key, so re-initialize
10733 * group key with correct value
10734 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010735 if ((eCSR_BSS_TYPE_START_IBSS ==
10736 pWextState->roamProfile.BSSType)
10737 &&
10738 !((IW_AUTH_KEY_MGMT_802_1X ==
10739 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10740 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10741 pHddStaCtx->conn_info.authType)
10742 )
10743 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10744 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10745 )
10746 ) {
10747 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010748 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010749
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010750 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10752 setKey.keyDirection);
10753
10754 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10755 pAdapter->sessionId, &setKey,
10756 &roamId);
10757
10758 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010759 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760 pHddStaCtx->roam_info.roamingState =
10761 HDD_ROAM_STATE_NONE;
10762 return -EINVAL;
10763 }
10764 }
10765 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010766 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010767 return 0;
10768}
10769
10770static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10771 struct net_device *ndev,
10772 u8 key_index, bool pairwise,
10773 const u8 *mac_addr,
10774 struct key_params *params)
10775{
10776 int ret;
10777 cds_ssr_protect(__func__);
10778 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10779 mac_addr, params);
10780 cds_ssr_unprotect(__func__);
10781
10782 return ret;
10783}
10784
10785/*
10786 * FUNCTION: __wlan_hdd_cfg80211_get_key
10787 * This function is used to get the key information
10788 */
10789static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10790 struct net_device *ndev,
10791 u8 key_index, bool pairwise,
10792 const u8 *mac_addr, void *cookie,
10793 void (*callback)(void *cookie,
10794 struct key_params *)
10795 )
10796{
10797 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10798 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10799 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10800 struct key_params params;
10801
10802 ENTER();
10803
Anurag Chouhan6d760662016-02-20 16:05:43 +053010804 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010805 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 return -EINVAL;
10807 }
10808
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010809 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810 hdd_device_mode_to_string(pAdapter->device_mode),
10811 pAdapter->device_mode);
10812
10813 memset(&params, 0, sizeof(params));
10814
10815 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010816 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010817 key_index);
10818 return -EINVAL;
10819 }
10820
10821 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10822 case eCSR_ENCRYPT_TYPE_NONE:
10823 params.cipher = IW_AUTH_CIPHER_NONE;
10824 break;
10825
10826 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10827 case eCSR_ENCRYPT_TYPE_WEP40:
10828 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10829 break;
10830
10831 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10832 case eCSR_ENCRYPT_TYPE_WEP104:
10833 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10834 break;
10835
10836 case eCSR_ENCRYPT_TYPE_TKIP:
10837 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10838 break;
10839
10840 case eCSR_ENCRYPT_TYPE_AES:
10841 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10842 break;
10843
10844 default:
10845 params.cipher = IW_AUTH_CIPHER_NONE;
10846 break;
10847 }
10848
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010849 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 TRACE_CODE_HDD_CFG80211_GET_KEY,
10851 pAdapter->sessionId, params.cipher));
10852
10853 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10854 params.seq_len = 0;
10855 params.seq = NULL;
10856 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10857 callback(cookie, &params);
10858
10859 EXIT();
10860 return 0;
10861}
10862
10863static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10864 struct net_device *ndev,
10865 u8 key_index, bool pairwise,
10866 const u8 *mac_addr, void *cookie,
10867 void (*callback)(void *cookie,
10868 struct key_params *)
10869 )
10870{
10871 int ret;
10872
10873 cds_ssr_protect(__func__);
10874 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10875 mac_addr, cookie, callback);
10876 cds_ssr_unprotect(__func__);
10877
10878 return ret;
10879}
10880
10881/**
10882 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10883 * @wiphy: wiphy interface context
10884 * @ndev: pointer to net device
10885 * @key_index: Key index used in 802.11 frames
10886 * @unicast: true if it is unicast key
10887 * @multicast: true if it is multicast key
10888 *
10889 * This function is required for cfg80211_ops API.
10890 * It is used to delete the key information
10891 * Underlying hardware implementation does not have API to delete the
10892 * encryption key. It is automatically deleted when the peer is
10893 * removed. Hence this function currently does nothing.
10894 * Future implementation may interprete delete key operation to
10895 * replacing the key with a random junk value, effectively making it
10896 * useless.
10897 *
10898 * Return: status code, always 0.
10899 */
10900
10901static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10902 struct net_device *ndev,
10903 u8 key_index,
10904 bool pairwise, const u8 *mac_addr)
10905{
10906 EXIT();
10907 return 0;
10908}
10909
10910/**
10911 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10912 * @wiphy: Pointer to wiphy structure.
10913 * @dev: Pointer to net_device structure.
10914 * @key_index: key index
10915 * @pairwise: pairwise
10916 * @mac_addr: mac address
10917 *
10918 * This is the cfg80211 delete key handler function which invokes
10919 * the internal function @__wlan_hdd_cfg80211_del_key with
10920 * SSR protection.
10921 *
10922 * Return: 0 for success, error number on failure.
10923 */
10924static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10925 struct net_device *dev,
10926 u8 key_index,
10927 bool pairwise, const u8 *mac_addr)
10928{
10929 int ret;
10930
10931 cds_ssr_protect(__func__);
10932 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10933 pairwise, mac_addr);
10934 cds_ssr_unprotect(__func__);
10935
10936 return ret;
10937}
10938
10939/*
10940 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10941 * This function is used to set the default tx key index
10942 */
10943static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10944 struct net_device *ndev,
10945 u8 key_index,
10946 bool unicast, bool multicast)
10947{
10948 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10949 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10950 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10951 hdd_context_t *pHddCtx;
10952 int status;
10953
10954 ENTER();
10955
Anurag Chouhan6d760662016-02-20 16:05:43 +053010956 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010957 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010958 return -EINVAL;
10959 }
10960
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010961 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10962 hdd_err("invalid session id: %d", pAdapter->sessionId);
10963 return -EINVAL;
10964 }
10965
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010966 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10968 pAdapter->sessionId, key_index));
10969
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010970 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971 hdd_device_mode_to_string(pAdapter->device_mode),
10972 pAdapter->device_mode, key_index);
10973
10974 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010975 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010976 return -EINVAL;
10977 }
10978
10979 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10980 status = wlan_hdd_validate_context(pHddCtx);
10981
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010982 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010983 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010984
Krunal Sonib4326f22016-03-10 13:05:51 -080010985 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10986 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10988 pHddStaCtx->conn_info.ucEncryptionType) &&
10989 (eCSR_ENCRYPT_TYPE_AES !=
10990 pHddStaCtx->conn_info.ucEncryptionType)) {
10991 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010992 * then update the default key index
10993 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010994
10995 tCsrRoamSetKey setKey;
10996 uint32_t roamId = 0xFF;
10997 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10998
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010999 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011000
11001 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011002 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011003 setKey.keyId = key_index;
11004 setKey.keyLength = Keys->KeyLength[key_index];
11005
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011006 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 &Keys->KeyMaterial[key_index][0],
11008 Keys->KeyLength[key_index]);
11009
11010 setKey.keyDirection = eSIR_TX_RX;
11011
Anurag Chouhanc5548422016-02-24 18:33:27 +053011012 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013 &pHddStaCtx->conn_info.bssId);
11014
11015 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
11016 pWextState->roamProfile.EncryptionType.
11017 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011018 /* In the case of dynamic wep
11019 * supplicant hardcodes DWEP type to
11020 * eCSR_ENCRYPT_TYPE_WEP104 even
11021 * though ap is configured for WEP-40
11022 * encryption. In this canse the key
11023 * length is 5 but the encryption type
11024 * is 104 hence checking the key
11025 * lenght(5) and encryption type(104)
11026 * and switching encryption type to 40
11027 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011028 pWextState->roamProfile.EncryptionType.
11029 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11030 pWextState->roamProfile.mcEncryptionType.
11031 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11032 }
11033
11034 setKey.encType =
11035 pWextState->roamProfile.EncryptionType.
11036 encryptionType[0];
11037
11038 /* Issue set key request */
11039 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11040 pAdapter->sessionId, &setKey,
11041 &roamId);
11042
11043 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011044 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 status);
11046 return -EINVAL;
11047 }
11048 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011049 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011050 /* In SoftAp mode setting key direction for default mode */
11051 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11052 pWextState->roamProfile.EncryptionType.encryptionType[0])
11053 && (eCSR_ENCRYPT_TYPE_AES !=
11054 pWextState->roamProfile.EncryptionType.
11055 encryptionType[0])) {
11056 /* Saving key direction for default key index to TX default */
11057 hdd_ap_ctx_t *pAPCtx =
11058 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11059 pAPCtx->wepKey[key_index].keyDirection =
11060 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011061 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053011062 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011063 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011064 }
11065 }
11066
11067 EXIT();
11068 return status;
11069}
11070
11071static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11072 struct net_device *ndev,
11073 u8 key_index,
11074 bool unicast, bool multicast)
11075{
11076 int ret;
11077 cds_ssr_protect(__func__);
11078 ret =
11079 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
11080 multicast);
11081 cds_ssr_unprotect(__func__);
11082
11083 return ret;
11084}
11085
Abhishek Singhc9941602016-08-09 16:06:22 +053011086/*
11087 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
11088 * @wiphy: wiphy pointer
11089 * @channel: channel of the BSS
11090 * @bssid: Bssid of BSS
11091 * @ssid: Ssid of the BSS
11092 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011093 *
Abhishek Singhc9941602016-08-09 16:06:22 +053011094 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095 */
Abhishek Singhc9941602016-08-09 16:06:22 +053011096#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011097static
Abhishek Singhc9941602016-08-09 16:06:22 +053011098struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
11099 struct ieee80211_channel *channel, const u8 *bssid,
11100 const u8 *ssid, size_t ssid_len)
11101{
11102 return cfg80211_get_bss(wiphy, channel, bssid,
11103 ssid,
11104 ssid_len,
11105 WLAN_CAPABILITY_ESS,
11106 WLAN_CAPABILITY_ESS);
11107}
11108#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011109static
Abhishek Singhc9941602016-08-09 16:06:22 +053011110struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
11111 struct ieee80211_channel *channel, const u8 *bssid,
11112 const u8 *ssid, size_t ssid_len)
11113{
11114 return cfg80211_get_bss(wiphy, channel, bssid,
11115 ssid,
11116 ssid_len,
11117 IEEE80211_BSS_TYPE_ESS,
11118 IEEE80211_PRIVACY_ANY);
11119}
11120#endif
11121
11122
11123/*
11124 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
11125 * interface that BSS might have been lost.
11126 * @pAdapter: adaptor
11127 * @bssid: bssid which might have been lost
11128 *
11129 * Return: bss which is unlinked from kernel cache
11130 */
11131struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
11132 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011133{
11134 struct net_device *dev = pAdapter->dev;
11135 struct wireless_dev *wdev = dev->ieee80211_ptr;
11136 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011137 struct cfg80211_bss *bss = NULL;
11138
Abhishek Singhc9941602016-08-09 16:06:22 +053011139 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
11140 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011141 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011142 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053011144 hdd_info("cfg80211_unlink_bss called for BSSID "
11145 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146 cfg80211_unlink_bss(wiphy, bss);
11147 }
11148 return bss;
11149}
11150
Abhishek Singhc9941602016-08-09 16:06:22 +053011151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152/**
11153 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
11154 * @pAdapter: Pointer to adapter
11155 * @bss_desc: Pointer to bss descriptor
11156 *
11157 * This function is used to inform the BSS details to nl80211 interface.
11158 *
11159 * Return: struct cfg80211_bss pointer
11160 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053011161struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
11162 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011163{
11164 /*
11165 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
11166 * already exists in bss data base of cfg80211 for that particular BSS
11167 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
11168 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
11169 * As of now there is no possibility to get the mgmt(probe response)
11170 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
11171 * and passing to cfg80211_inform_bss_frame.
11172 */
11173 struct net_device *dev = pAdapter->dev;
11174 struct wireless_dev *wdev = dev->ieee80211_ptr;
11175 struct wiphy *wiphy = wdev->wiphy;
11176 int chan_no = bss_desc->channelId;
11177#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11178 qcom_ie_age *qie_age = NULL;
11179 int ie_length =
11180 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
11181#else
11182 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
11183#endif
11184 const char *ie =
11185 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
11186 unsigned int freq;
11187 struct ieee80211_channel *chan;
11188 struct ieee80211_mgmt *mgmt = NULL;
11189 struct cfg80211_bss *bss_status = NULL;
11190 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
11191 int rssi = 0;
11192 hdd_context_t *pHddCtx;
11193 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011194 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011195 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196
11197 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11198 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011199 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011200 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011202 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011203 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
11204 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011205 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011206 return NULL;
11207 }
11208
11209 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
11210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011211 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011212 * Instead it wants a monotonic increasing value
11213 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070011214 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011215 mgmt->u.probe_resp.timestamp =
11216 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011217
11218 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
11219 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
11220
11221#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11222 /* GPS Requirement: need age ie per entry. Using vendor specific. */
11223 /* Assuming this is the last IE, copy at the end */
11224 ie_length -= sizeof(qcom_ie_age);
11225 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
11226 qie_age->element_id = QCOM_VENDOR_IE_ID;
11227 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
11228 qie_age->oui_1 = QCOM_OUI1;
11229 qie_age->oui_2 = QCOM_OUI2;
11230 qie_age->oui_3 = QCOM_OUI3;
11231 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053011232 /*
11233 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
11234 * all bss related timestamp is in units of ms. Due to this when scan
11235 * results are sent to lowi the scan age is high.To address this,
11236 * send age in units of 1/10 ms.
11237 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053011239 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011240 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070011241 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
11242 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070011243 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
11244 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011245#endif
11246
11247 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
11248 if (bss_desc->fProbeRsp) {
11249 mgmt->frame_control |=
11250 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
11251 } else {
11252 mgmt->frame_control |=
11253 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
11254 }
11255
11256 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070011257 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 freq =
11259 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011260 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011261 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070011262 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263 freq =
11264 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011265 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011266 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011267 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011268 kfree(mgmt);
11269 return NULL;
11270 }
11271
11272 chan = __ieee80211_get_channel(wiphy, freq);
11273 /* When the band is changed on the fly using the GUI, three things are done
11274 * 1. scan abort
11275 * 2. flush scan results from cache
11276 * 3. update the band with the new band user specified (refer to the
11277 * hdd_set_band_helper function) as part of the scan abort, message will be
11278 * queued to PE and we proceed with flushing and changinh the band.
11279 * PE will stop the scanning further and report back the results what ever
11280 * it had till now by calling the call back function.
11281 * if the time between update band and scandone call back is sufficient
11282 * enough the band change reflects in SME, SME validates the channels
11283 * and discards the channels correponding to previous band and calls back
11284 * with zero bss results. but if the time between band update and scan done
11285 * callback is very small then band change will not reflect in SME and SME
11286 * reports to HDD all the channels correponding to previous band.this is due
11287 * to race condition.but those channels are invalid to the new band and so
11288 * this function __ieee80211_get_channel will return NULL.Each time we
11289 * report scan result with this pointer null warning kernel trace is printed.
11290 * if the scan results contain large number of APs continuosly kernel
11291 * warning trace is printed and it will lead to apps watch dog bark.
11292 * So drop the bss and continue to next bss.
11293 */
11294 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053011295 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
11296 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011297 kfree(mgmt);
11298 return NULL;
11299 }
11300
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011301 /* Based on .ini configuration, raw rssi can be reported for bss.
11302 * Raw rssi is typically used for estimating power.
11303 */
11304
11305 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
11306 bss_desc->rssi;
11307
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011308 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053011309 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011310
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053011311 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070011313 (int)(rssi / 100),
11314 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011315
11316 bss_status =
11317 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
11318 GFP_KERNEL);
11319 kfree(mgmt);
11320 return bss_status;
11321}
11322
11323/**
11324 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
11325 * @pAdapter: Pointer to adapter
11326 * @pRoamInfo: Pointer to roam info
11327 *
11328 * This function is used to update the BSS data base of CFG8011
11329 *
11330 * Return: struct cfg80211_bss pointer
11331 */
11332struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
11333 tCsrRoamInfo *pRoamInfo)
11334{
11335 tCsrRoamConnectedProfile roamProfile;
11336 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11337 struct cfg80211_bss *bss = NULL;
11338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
11340 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
11341
11342 if (NULL != roamProfile.pBssDesc) {
11343 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11344 roamProfile.pBssDesc);
11345
11346 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011347 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080011349 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011350 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011351 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011352 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 return bss;
11354}
11355/**
11356 * wlan_hdd_cfg80211_update_bss() - update bss
11357 * @wiphy: Pointer to wiphy
11358 * @pAdapter: Pointer to adapter
11359 * @scan_time: scan request timestamp
11360 *
11361 * Return: zero if success, non-zero otherwise
11362 */
11363int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
11364 hdd_adapter_t *pAdapter,
11365 uint32_t scan_time)
11366{
11367 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11368 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011369 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 tScanResultHandle pResult;
11371 struct cfg80211_bss *bss_status = NULL;
11372 hdd_context_t *pHddCtx;
11373 int ret;
11374
11375 ENTER();
11376
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011377 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11378 hdd_err("invalid session id: %d", pAdapter->sessionId);
11379 return -EINVAL;
11380 }
11381
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011382 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011383 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11384 NO_SESSION, pAdapter->sessionId));
11385
11386 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11387 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011388 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011389 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390
11391 /* start getting scan results and populate cgf80211 BSS database */
11392 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11393
11394 /* no scan results */
11395 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011396 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011397 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011398 }
11399
11400 pScanResult = sme_scan_result_get_first(hHal, pResult);
11401
11402 while (pScanResult) {
11403 /*
11404 * - cfg80211_inform_bss() is not updating ie field of bss
11405 * entry if entry already exists in bss data base of cfg80211
11406 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11407 * to update thebss entry instead of cfg80211_inform_bss,
11408 * But this call expects mgmt packet as input. As of now
11409 * there is no possibility to get the mgmt(probe response)
11410 * frame from PE, converting bss_desc to
11411 * ieee80211_mgmt(probe response) and passing to c
11412 * fg80211_inform_bss_frame.
11413 * - Update BSS only if beacon timestamp is later than
11414 * scan request timestamp.
11415 */
11416 if ((scan_time == 0) ||
11417 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011418 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419 bss_status =
11420 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11421 &pScanResult->BssDescriptor);
11422
11423 if (NULL == bss_status) {
11424 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11425 } else {
11426 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011427 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 bss_status);
11429 }
11430 } else {
11431 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11432 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11433 }
11434 pScanResult = sme_scan_result_get_next(hHal, pResult);
11435 }
11436
11437 sme_scan_result_purge(hHal, pResult);
11438 /*
11439 * For SAP mode, scan is invoked by hostapd during SAP start
11440 * if hostapd is restarted, we need to flush previous scan
11441 * result so that it will reflect environment change
11442 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011443 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011444#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11445 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11446#endif
11447 )
11448 sme_scan_flush_result(hHal);
11449
11450 EXIT();
11451 return 0;
11452}
11453
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011454/**
11455 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11456 * @pAdapter: Pointer to adapter
11457 * @pRoamInfo: Pointer to roam info
11458 * @index: Index
11459 * @preauth: Preauth flag
11460 *
11461 * This function is used to notify the supplicant of a new PMKSA candidate.
11462 *
11463 * Return: 0 for success, non-zero for failure
11464 */
11465int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11466 tCsrRoamInfo *pRoamInfo,
11467 int index, bool preauth)
11468{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011469 struct net_device *dev = pAdapter->dev;
11470 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11471
11472 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011473 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011474
11475 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011476 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 return -EINVAL;
11478 }
11479
11480 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011481 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011482 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11483 cfg80211_pmksa_candidate_notify(dev, index,
11484 pRoamInfo->bssid.bytes,
11485 preauth, GFP_KERNEL);
11486 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011487 return 0;
11488}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011489
11490#ifdef FEATURE_WLAN_LFR_METRICS
11491/**
11492 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11493 * @pAdapter: Pointer to adapter
11494 * @pRoamInfo: Pointer to roam info
11495 *
11496 * 802.11r/LFR metrics reporting function to report preauth initiation
11497 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011498 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011499 */
11500#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011501QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 tCsrRoamInfo *pRoamInfo)
11503{
11504 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11505 union iwreq_data wrqu;
11506
11507 ENTER();
11508
11509 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011510 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011511 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011512 }
11513
11514 /* create the event */
11515 memset(&wrqu, 0, sizeof(wrqu));
11516 memset(metrics_notification, 0, sizeof(metrics_notification));
11517
11518 wrqu.data.pointer = metrics_notification;
11519 wrqu.data.length = scnprintf(metrics_notification,
11520 sizeof(metrics_notification),
11521 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11522 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11523
11524 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11525 metrics_notification);
11526
11527 EXIT();
11528
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011529 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011530}
11531
11532/**
11533 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11534 * @pAdapter: Pointer to adapter
11535 * @pRoamInfo: Pointer to roam info
11536 * @preauth_status: Preauth status
11537 *
11538 * 802.11r/LFR metrics reporting function to report handover initiation
11539 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011540 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011542QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11544 tCsrRoamInfo *pRoamInfo,
11545 bool preauth_status)
11546{
11547 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11548 union iwreq_data wrqu;
11549
11550 ENTER();
11551
11552 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011553 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011554 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011555 }
11556
11557 /* create the event */
11558 memset(&wrqu, 0, sizeof(wrqu));
11559 memset(metrics_notification, 0, sizeof(metrics_notification));
11560
11561 scnprintf(metrics_notification, sizeof(metrics_notification),
11562 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11563 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11564
11565 if (1 == preauth_status)
11566 strlcat(metrics_notification, " true",
11567 sizeof(metrics_notification));
11568 else
11569 strlcat(metrics_notification, " false",
11570 sizeof(metrics_notification));
11571
11572 wrqu.data.pointer = metrics_notification;
11573 wrqu.data.length = strlen(metrics_notification);
11574
11575 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11576 metrics_notification);
11577
11578 EXIT();
11579
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011580 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011581}
11582
11583/**
11584 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11585 * @pAdapter: Pointer to adapter
11586 * @pRoamInfo: Pointer to roam info
11587 *
11588 * 802.11r/LFR metrics reporting function to report handover initiation
11589 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011590 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011591 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011592QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011593 tCsrRoamInfo *pRoamInfo)
11594{
11595 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11596 union iwreq_data wrqu;
11597
11598 ENTER();
11599
11600 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011601 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011602 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011603 }
11604
11605 /* create the event */
11606 memset(&wrqu, 0, sizeof(wrqu));
11607 memset(metrics_notification, 0, sizeof(metrics_notification));
11608
11609 wrqu.data.pointer = metrics_notification;
11610 wrqu.data.length = scnprintf(metrics_notification,
11611 sizeof(metrics_notification),
11612 "QCOM: LFR_PREAUTH_HANDOVER "
11613 MAC_ADDRESS_STR,
11614 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11615
11616 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11617 metrics_notification);
11618
11619 EXIT();
11620
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011621 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622}
11623#endif
11624
11625/**
11626 * hdd_select_cbmode() - select channel bonding mode
11627 * @pAdapter: Pointer to adapter
11628 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011629 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011630 *
11631 * Return: none
11632 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011633void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11634 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011635{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011636 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011637 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011638 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011639
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011640 /*
11641 * CDS api expects secondary channel for calculating
11642 * the channel params
11643 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011644 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011645 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11646 if (operationChannel >= 1 && operationChannel <= 5)
11647 sec_ch = operationChannel + 4;
11648 else if (operationChannel >= 6 && operationChannel <= 13)
11649 sec_ch = operationChannel - 4;
11650 }
11651
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011653 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011654
11655 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011656 eHddDot11Mode hdd_dot11_mode;
11657 uint8_t iniDot11Mode =
11658 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11659
11660 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11661 switch (iniDot11Mode) {
11662 case eHDD_DOT11_MODE_AUTO:
11663 case eHDD_DOT11_MODE_11ac:
11664 case eHDD_DOT11_MODE_11ac_ONLY:
11665 if (sme_is_feature_supported_by_fw(DOT11AC))
11666 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11667 else
11668 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11669 break;
11670 case eHDD_DOT11_MODE_11n:
11671 case eHDD_DOT11_MODE_11n_ONLY:
11672 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11673 break;
11674 default:
11675 hdd_dot11_mode = iniDot11Mode;
11676 break;
11677 }
11678 ch_info->channel_width = ch_params->ch_width;
11679 ch_info->phy_mode =
11680 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011681 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011682 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011683 hdd_info("ch_info width %d, phymode %d channel %d",
11684 ch_info->channel_width, ch_info->phy_mode,
11685 ch_info->channel);
11686 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687}
11688
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011689/**
11690 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11691 * @adapter: STA adapter
11692 * @roam_profile: STA roam profile
11693 *
11694 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11695 *
11696 * Return: false if sta-sap conc is not allowed, else return true
11697 */
11698static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11699 tCsrRoamProfile *roam_profile)
11700{
11701 hdd_context_t *hdd_ctx;
11702 hdd_adapter_t *ap_adapter;
11703 hdd_ap_ctx_t *hdd_ap_ctx;
11704 hdd_hostapd_state_t *hostapd_state;
11705 uint8_t channel = 0;
11706 QDF_STATUS status;
11707
11708 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11709 if (!hdd_ctx) {
11710 hdd_err("HDD context is NULL");
11711 return true;
11712 }
11713
11714 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11715 /* probably no sap running, no handling required */
11716 if (ap_adapter == NULL)
11717 return true;
11718
11719 /*
11720 * sap is not in started state, so it is fine to go ahead with sta.
11721 * if sap is currently doing CAC then don't allow sta to go further.
11722 */
11723 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11724 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11725 return true;
11726
11727 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11728 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11729 return false;
11730 }
11731
11732 /*
11733 * log and return error, if we allow STA to go through, we don't
11734 * know what is going to happen better stop sta connection
11735 */
11736 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11737 if (NULL == hdd_ap_ctx) {
11738 hdd_err("AP context not found");
11739 return false;
11740 }
11741
11742 /* sap is on non-dfs channel, nothing to handle */
11743 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11744 hdd_info("sap is on non-dfs channel, sta is allowed");
11745 return true;
11746 }
11747 /*
11748 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011749 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011750 */
11751 status = cds_get_channel_from_scan_result(adapter,
11752 roam_profile, &channel);
11753
Nitesh Shah59774522016-09-16 15:14:21 +053011754 /*
11755 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11756 * channels for roaming case.
11757 */
11758 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11759 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11760 return true;
11761 }
11762
11763 /*
11764 * If channel is 0 or DFS then better to call pcl and find out the
11765 * best channel. If channel is non-dfs 5 GHz then better move SAP
11766 * to STA's channel to make scc, so we have room for 3port MCC
11767 * scenario.
11768 */
11769 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011770 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11771 true);
11772
11773 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11774 qdf_event_reset(&hostapd_state->qdf_event);
11775 status = wlansap_set_channel_change_with_csa(
11776 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11777 hdd_ap_ctx->sapConfig.ch_width_orig);
11778
11779 if (QDF_STATUS_SUCCESS != status) {
11780 hdd_err("Set channel with CSA IE failed, can't allow STA");
11781 return false;
11782 }
11783
11784 /*
11785 * wait here for SAP to finish the channel switch. When channel
11786 * switch happens, SAP sends few beacons with CSA_IE. After
11787 * successfully Transmission of those beacons, it will move its
11788 * state from started to disconnected and move to new channel.
11789 * once it moves to new channel, sap again moves its state
11790 * machine from disconnected to started and set this event.
11791 * wait for 10 secs to finish this.
11792 */
11793 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11794 if (!QDF_IS_STATUS_SUCCESS(status)) {
11795 hdd_err("wait for qdf_event failed, STA not allowed!!");
11796 return false;
11797 }
11798
11799 return true;
11800}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801
Krunal Soni31949422016-07-29 17:17:53 -070011802/**
11803 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011805 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 * @ssid_len: Length of ssid
11807 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011808 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011810 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011811 *
11812 * This function is used to start the association process
11813 *
11814 * Return: 0 for success, non-zero for failure
11815 */
Krunal Soni31949422016-07-29 17:17:53 -070011816static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011817 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011818 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011819 u8 operatingChannel,
11820 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821{
11822 int status = 0;
11823 hdd_wext_state_t *pWextState;
11824 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011825 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 uint32_t roamId;
11827 tCsrRoamProfile *pRoamProfile;
11828 eCsrAuthType RSNAuthType;
11829 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011830 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011831
11832 ENTER();
11833
11834 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11835 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011836 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837
11838 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011839 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841
11842 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011843 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011844 return -EINVAL;
11845 }
11846
11847 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011848 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11849 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850
11851 if (pRoamProfile) {
11852 hdd_station_ctx_t *pHddStaCtx;
11853 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11854
11855 if (HDD_WMM_USER_MODE_NO_QOS ==
11856 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11857 /*QoS not enabled in cfg file */
11858 pRoamProfile->uapsd_mask = 0;
11859 } else {
11860 /*QoS enabled, update uapsd mask from cfg file */
11861 pRoamProfile->uapsd_mask =
11862 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11863 }
11864
11865 pRoamProfile->SSIDs.numOfSSIDs = 1;
11866 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011867 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011868 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011869 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870 ssid, ssid_len);
11871
Deepak Dhamdherea2785822016-11-17 01:17:45 -080011872 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011873 if (bssid) {
11874 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011875 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011876 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011877 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011878 /*
11879 * Save BSSID in seperate variable as
11880 * pRoamProfile's BSSID is getting zeroed out in the
11881 * association process. In case of join failure
11882 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011883 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011884 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011885 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011886 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011887 } else if (bssid_hint) {
11888 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011889 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011890 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011891 /*
11892 * Save BSSID in a separate variable as
11893 * pRoamProfile's BSSID is getting zeroed out in the
11894 * association process. In case of join failure
11895 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011896 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011897 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011898 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011899 hdd_info("bssid_hint is given by upper layer %pM",
11900 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011901 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011902 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011903 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011904 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 }
11906
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011907 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011908 pRoamProfile->SSIDs.SSIDList->SSID.length,
11909 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11910 operatingChannel);
11911
11912 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11913 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011914 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011915 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11916 }
11917#ifdef FEATURE_WLAN_WAPI
11918 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011919 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011920 switch (pAdapter->wapi_info.wapiAuthMode) {
11921 case WAPI_AUTH_MODE_PSK:
11922 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011923 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011924 pAdapter->wapi_info.wapiAuthMode);
11925 pRoamProfile->AuthType.authType[0] =
11926 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11927 break;
11928 }
11929 case WAPI_AUTH_MODE_CERT:
11930 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011931 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011932 pAdapter->wapi_info.wapiAuthMode);
11933 pRoamProfile->AuthType.authType[0] =
11934 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11935 break;
11936 }
11937 } /* End of switch */
11938 if (pAdapter->wapi_info.wapiAuthMode ==
11939 WAPI_AUTH_MODE_PSK
11940 || pAdapter->wapi_info.wapiAuthMode ==
11941 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011942 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011943 pRoamProfile->AuthType.numEntries = 1;
11944 pRoamProfile->EncryptionType.numEntries = 1;
11945 pRoamProfile->EncryptionType.encryptionType[0] =
11946 eCSR_ENCRYPT_TYPE_WPI;
11947 pRoamProfile->mcEncryptionType.numEntries = 1;
11948 pRoamProfile->mcEncryptionType.
11949 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11950 }
11951 }
Krunal Soni31949422016-07-29 17:17:53 -070011952#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011953#ifdef WLAN_FEATURE_GTK_OFFLOAD
11954 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011955 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11956 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011957 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11958 sizeof(tSirGtkOffloadParams));
11959 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11960 GTK_OFFLOAD_DISABLE;
11961 }
11962#endif
11963 pRoamProfile->csrPersona = pAdapter->device_mode;
11964
11965 if (operatingChannel) {
11966 pRoamProfile->ChannelInfo.ChannelList =
11967 &operatingChannel;
11968 pRoamProfile->ChannelInfo.numOfChannels = 1;
11969 } else {
11970 pRoamProfile->ChannelInfo.ChannelList = NULL;
11971 pRoamProfile->ChannelInfo.numOfChannels = 0;
11972 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011973 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974 && operatingChannel) {
11975 /*
11976 * Need to post the IBSS power save parameters
11977 * to WMA. WMA will configure this parameters
11978 * to firmware if power save is enabled by the
11979 * firmware.
11980 */
11981 status = hdd_set_ibss_power_save_params(pAdapter);
11982
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011983 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011984 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011985 return -EINVAL;
11986 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011987 pRoamProfile->ch_params.ch_width =
11988 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011989 /*
11990 * In IBSS mode while operating in 2.4 GHz,
11991 * the device supports only 20 MHz.
11992 */
11993 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11994 pRoamProfile->ch_params.ch_width =
11995 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011996 hdd_select_cbmode(pAdapter, operatingChannel,
11997 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011998 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011999 /*
12000 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12001 * or pmf=2 is an explicit configuration in the supplicant
12002 * configuration, drop the connection request.
12003 */
12004 if (pWextState->roamProfile.MFPEnabled &&
12005 !(pWextState->roamProfile.MFPRequired ||
12006 pWextState->roamProfile.MFPCapable)) {
12007 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12008 pWextState->roamProfile.MFPEnabled,
12009 pWextState->roamProfile.MFPRequired,
12010 pWextState->roamProfile.MFPCapable);
12011 return -EINVAL;
12012 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012013
Krunal Soni3091bcc2016-06-23 12:28:21 -070012014 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012015 hdd_err("Connection refused: conn in progress");
12016 return -EINVAL;
12017 }
12018
Krunal Soni31949422016-07-29 17:17:53 -070012019 /*
12020 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012021 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070012022 * enhancements, the supplicant is not issuing the scan command
12023 * now. So the unicast frames which are sent from the host are
12024 * not having the additional IEs. If it is P2P CLIENT and there
12025 * is no additional IE present in roamProfile, then use the
12026 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 */
12028
Krunal Sonib4326f22016-03-10 13:05:51 -080012029 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 (!pRoamProfile->pAddIEScan)) {
12031 pRoamProfile->pAddIEScan =
12032 &pAdapter->scan_info.scanAddIE.addIEdata[0];
12033 pRoamProfile->nAddIEScanLength =
12034 pAdapter->scan_info.scanAddIE.length;
12035 }
12036 /*
12037 * When policy manager is enabled from ini file, we shouldn't
12038 * check for other concurrency rules.
12039 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070012040 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080012041 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012042 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 pAdapter, pRoamProfile, &roamId))
12044 return 0;
12045 }
12046
Krunal Soni3091bcc2016-06-23 12:28:21 -070012047 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012048 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
12049 pRoamProfile))) {
12050 hdd_err("sap-sta conc will fail, can't allow sta");
12051 hdd_conn_set_connection_state(pAdapter,
12052 eConnectionState_NotConnected);
12053 return -ENOMEM;
12054 }
12055
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012056 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012057 if (!sme_config) {
12058 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012059 hdd_conn_set_connection_state(pAdapter,
12060 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 return -ENOMEM;
12062 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012063 sme_get_config_param(pHddCtx->hHal, sme_config);
12064 /* These values are not sessionized. So, any change in these SME
12065 * configs on an older or parallel interface will affect the
12066 * cb mode. So, restoring the default INI params before starting
12067 * interfaces such as sta, cli etc.,
12068 */
12069 sme_config->csrConfig.channelBondingMode5GHz =
12070 pHddCtx->config->nChannelBondingMode5GHz;
12071 sme_config->csrConfig.channelBondingMode24GHz =
12072 pHddCtx->config->nChannelBondingMode24GHz;
12073 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012074 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053012075 /*
12076 * Change conn_state to connecting before sme_roam_connect(),
12077 * because sme_roam_connect() has a direct path to call
12078 * hdd_sme_roam_callback(), which will change the conn_state
12079 * If direct path, conn_state will be accordingly changed to
12080 * NotConnected or Associated by either
12081 * hdd_association_completion_handler() or
12082 * hdd_dis_connect_handler() in sme_RoamCallback()if
12083 * sme_RomConnect is to be queued,
12084 * Connecting state will remain until it is completed.
12085 *
12086 * If connection state is not changed, connection state will
12087 * remain in eConnectionState_NotConnected state.
12088 * In hdd_association_completion_handler, "hddDisconInProgress"
12089 * is set to true if conn state is
12090 * eConnectionState_NotConnected.
12091 * If "hddDisconInProgress" is set to true then cfg80211 layer
12092 * is not informed of connect result indication which
12093 * is an issue.
12094 */
12095 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053012096 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053012097 hdd_conn_set_connection_state(pAdapter,
12098 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012099
Komal Seelama89be8d2016-09-29 11:09:26 +053012100 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
12101 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012102 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12103 pAdapter->sessionId, pRoamProfile,
12104 &roamId);
12105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012106 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080012107 (QDF_STA_MODE == pAdapter->device_mode ||
12108 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012109 hdd_err("sme_roam_connect (session %d) failed with "
12110 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012111 pAdapter->sessionId, status);
12112 /* change back to NotAssociated */
12113 hdd_conn_set_connection_state(pAdapter,
12114 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053012115 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
12116 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 }
12118
12119 pRoamProfile->ChannelInfo.ChannelList = NULL;
12120 pRoamProfile->ChannelInfo.numOfChannels = 0;
12121
Nitesh Shah044fd672016-10-13 18:53:25 +053012122 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080012123 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053012124 cds_get_channel_from_scan_result(pAdapter,
12125 pRoamProfile, &channel);
12126 if (channel)
12127 cds_checkn_update_hw_mode_single_mac_mode
12128 (channel);
12129 }
12130
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012132 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012133 return -EINVAL;
12134 }
12135 EXIT();
12136 return status;
12137}
12138
12139/**
12140 * wlan_hdd_cfg80211_set_auth_type() - set auth type
12141 * @pAdapter: Pointer to adapter
12142 * @auth_type: Auth type
12143 *
12144 * This function is used to set the authentication type (OPEN/SHARED).
12145 *
12146 * Return: 0 for success, non-zero for failure
12147 */
12148static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
12149 enum nl80211_auth_type auth_type)
12150{
12151 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12152 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012154 /*set authentication type */
12155 switch (auth_type) {
12156 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012157 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012158 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
12159 break;
12160
12161 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012162 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012163 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012164 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12165 break;
12166
12167 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012168 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
12170 break;
12171#ifdef FEATURE_WLAN_ESE
12172 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012173 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
12175 break;
12176#endif
12177
12178 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012179 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
12181 return -EINVAL;
12182 }
12183
12184 pWextState->roamProfile.AuthType.authType[0] =
12185 pHddStaCtx->conn_info.authType;
12186 return 0;
12187}
12188
12189/**
12190 * wlan_hdd_set_akm_suite() - set key management type
12191 * @pAdapter: Pointer to adapter
12192 * @key_mgmt: Key management type
12193 *
12194 * This function is used to set the key mgmt type(PSK/8021x).
12195 *
12196 * Return: 0 for success, non-zero for failure
12197 */
12198static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
12199{
12200 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012202#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
12203#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
12204 /*set key mgmt type */
12205 switch (key_mgmt) {
12206 case WLAN_AKM_SUITE_PSK:
12207 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012208 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012209 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012210 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
12211 break;
12212
12213 case WLAN_AKM_SUITE_8021X_SHA256:
12214 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012215 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012216 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012217 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12218 break;
12219#ifdef FEATURE_WLAN_ESE
12220#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
12221#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
12222 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012223 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
12225 break;
12226#endif
12227#ifndef WLAN_AKM_SUITE_OSEN
12228#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
12229#endif
12230 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012231 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012232 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12233 break;
12234
12235 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012236 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012237 return -EINVAL;
12238
12239 }
12240 return 0;
12241}
12242
12243/**
12244 * wlan_hdd_cfg80211_set_cipher() - set encryption type
12245 * @pAdapter: Pointer to adapter
12246 * @cipher: Cipher type
12247 * @ucast: Unicast flag
12248 *
12249 * This function is used to set the encryption type
12250 * (NONE/WEP40/WEP104/TKIP/CCMP).
12251 *
12252 * Return: 0 for success, non-zero for failure
12253 */
12254static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
12255 u32 cipher, bool ucast)
12256{
12257 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12258 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12259 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012261 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012262 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12264 } else {
12265
12266 /*set encryption method */
12267 switch (cipher) {
12268 case IW_AUTH_CIPHER_NONE:
12269 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12270 break;
12271
12272 case WLAN_CIPHER_SUITE_WEP40:
12273 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
12274 break;
12275
12276 case WLAN_CIPHER_SUITE_WEP104:
12277 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
12278 break;
12279
12280 case WLAN_CIPHER_SUITE_TKIP:
12281 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
12282 break;
12283
12284 case WLAN_CIPHER_SUITE_CCMP:
12285 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12286 break;
12287#ifdef FEATURE_WLAN_WAPI
12288 case WLAN_CIPHER_SUITE_SMS4:
12289 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
12290 break;
12291#endif
12292
12293#ifdef FEATURE_WLAN_ESE
12294 case WLAN_CIPHER_SUITE_KRK:
12295 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
12296 break;
12297#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12298 case WLAN_CIPHER_SUITE_BTK:
12299 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
12300 break;
12301#endif
12302#endif
12303 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012304 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305 return -EOPNOTSUPP;
12306 }
12307 }
12308
12309 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012310 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012311 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12312 pWextState->roamProfile.EncryptionType.numEntries = 1;
12313 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12314 encryptionType;
12315 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012316 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012317 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
12318 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
12319 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
12320 encryptionType;
12321 }
12322
12323 return 0;
12324}
12325
12326/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012327 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
12328 * @wext_state: Pointer to wext state
12329 * @gen_ie: Pointer to IE data
12330 * @len: length of IE data
12331 *
12332 * Return: 0 for success, non-zero for failure
12333 */
12334static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
12335 const uint8_t *gen_ie, uint16_t len)
12336{
12337 uint16_t cur_add_ie_len =
12338 wext_state->assocAddIE.length;
12339
12340 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12341 (wext_state->assocAddIE.length + len)) {
12342 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12343 QDF_ASSERT(0);
12344 return -ENOMEM;
12345 }
12346 memcpy(wext_state->assocAddIE.addIEdata +
12347 cur_add_ie_len, gen_ie, len);
12348 wext_state->assocAddIE.length += len;
12349
12350 wext_state->roamProfile.pAddIEAssoc =
12351 wext_state->assocAddIE.addIEdata;
12352 wext_state->roamProfile.nAddIEAssocLength =
12353 wext_state->assocAddIE.length;
12354 return 0;
12355}
12356
12357/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012358 * wlan_hdd_cfg80211_set_ie() - set IEs
12359 * @pAdapter: Pointer to adapter
12360 * @ie: Pointer ot ie
12361 * @ie: IE length
12362 *
12363 * Return: 0 for success, non-zero for failure
12364 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012365static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012366 size_t ie_len)
12367{
12368 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12369 const uint8_t *genie = ie;
12370 uint16_t remLen = ie_len;
12371#ifdef FEATURE_WLAN_WAPI
12372 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12373 u16 *tmp;
12374 uint16_t akmsuiteCount;
12375 int *akmlist;
12376#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012377 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012378
12379 /* clear previous assocAddIE */
12380 pWextState->assocAddIE.length = 0;
12381 pWextState->roamProfile.bWPSAssociation = false;
12382 pWextState->roamProfile.bOSENAssociation = false;
12383
12384 while (remLen >= 2) {
12385 uint16_t eLen = 0;
12386 uint8_t elementId;
12387 elementId = *genie++;
12388 eLen = *genie++;
12389 remLen -= 2;
12390
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012391 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392
12393 switch (elementId) {
12394 case DOT11F_EID_WPA:
12395 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 -070012396 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012397 return -EINVAL;
12398 } else if (0 ==
12399 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12400 uint16_t curAddIELen =
12401 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012402 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403
12404 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12405 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012406 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012407 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 return -ENOMEM;
12409 }
12410 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12411 memcpy(pWextState->assocAddIE.addIEdata +
12412 curAddIELen, genie - 2, eLen + 2);
12413 pWextState->assocAddIE.length += eLen + 2;
12414
12415 pWextState->roamProfile.bWPSAssociation = true;
12416 pWextState->roamProfile.pAddIEAssoc =
12417 pWextState->assocAddIE.addIEdata;
12418 pWextState->roamProfile.nAddIEAssocLength =
12419 pWextState->assocAddIE.length;
12420 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012421 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012422 memset(pWextState->WPARSNIE, 0,
12423 MAX_WPA_RSN_IE_LEN);
12424 memcpy(pWextState->WPARSNIE, genie - 2,
12425 (eLen + 2));
12426 pWextState->roamProfile.pWPAReqIE =
12427 pWextState->WPARSNIE;
12428 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12429 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12430 P2P_OUI_TYPE_SIZE))) {
12431 uint16_t curAddIELen =
12432 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012433 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012434
12435 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12436 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012437 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012438 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439 return -ENOMEM;
12440 }
12441 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12442 memcpy(pWextState->assocAddIE.addIEdata +
12443 curAddIELen, genie - 2, eLen + 2);
12444 pWextState->assocAddIE.length += eLen + 2;
12445
12446 pWextState->roamProfile.pAddIEAssoc =
12447 pWextState->assocAddIE.addIEdata;
12448 pWextState->roamProfile.nAddIEAssocLength =
12449 pWextState->assocAddIE.length;
12450 }
12451#ifdef WLAN_FEATURE_WFD
12452 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12453 WFD_OUI_TYPE_SIZE)) &&
12454 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012455 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012456 pAdapter->device_mode)) {
12457 uint16_t curAddIELen =
12458 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012459 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012460
12461 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12462 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012463 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012464 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012465 return -ENOMEM;
12466 }
12467 /* WFD IE is saved to Additional IE ; it should
12468 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012469 * WFD IE
12470 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 memcpy(pWextState->assocAddIE.addIEdata +
12472 curAddIELen, genie - 2, eLen + 2);
12473 pWextState->assocAddIE.length += eLen + 2;
12474
12475 pWextState->roamProfile.pAddIEAssoc =
12476 pWextState->assocAddIE.addIEdata;
12477 pWextState->roamProfile.nAddIEAssocLength =
12478 pWextState->assocAddIE.length;
12479 }
12480#endif
12481 /* Appending HS 2.0 Indication Element in Assiciation Request */
12482 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12483 HS20_OUI_TYPE_SIZE))) {
12484 uint16_t curAddIELen =
12485 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012486 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012487
12488 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12489 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012490 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012491 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492 return -ENOMEM;
12493 }
12494 memcpy(pWextState->assocAddIE.addIEdata +
12495 curAddIELen, genie - 2, eLen + 2);
12496 pWextState->assocAddIE.length += eLen + 2;
12497
12498 pWextState->roamProfile.pAddIEAssoc =
12499 pWextState->assocAddIE.addIEdata;
12500 pWextState->roamProfile.nAddIEAssocLength =
12501 pWextState->assocAddIE.length;
12502 }
12503 /* Appending OSEN Information Element in Assiciation Request */
12504 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12505 OSEN_OUI_TYPE_SIZE))) {
12506 uint16_t curAddIELen =
12507 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012508 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012509
12510 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12511 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012512 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012513 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012514 return -ENOMEM;
12515 }
12516 memcpy(pWextState->assocAddIE.addIEdata +
12517 curAddIELen, genie - 2, eLen + 2);
12518 pWextState->assocAddIE.length += eLen + 2;
12519
12520 pWextState->roamProfile.bOSENAssociation = true;
12521 pWextState->roamProfile.pAddIEAssoc =
12522 pWextState->assocAddIE.addIEdata;
12523 pWextState->roamProfile.nAddIEAssocLength =
12524 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012525 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12526 MBO_OUI_TYPE_SIZE))){
12527 hdd_info("Set MBO IE(len %d)", eLen + 2);
12528 status = wlan_hdd_add_assoc_ie(pWextState,
12529 genie - 2, eLen + 2);
12530 if (status)
12531 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012532 } else {
12533 uint16_t add_ie_len =
12534 pWextState->assocAddIE.length;
12535
12536 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12537
12538 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12539 (pWextState->assocAddIE.length + eLen)) {
12540 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012541 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012542 return -ENOMEM;
12543 }
12544
12545 memcpy(pWextState->assocAddIE.addIEdata +
12546 add_ie_len, genie - 2, eLen + 2);
12547 pWextState->assocAddIE.length += eLen + 2;
12548
12549 pWextState->roamProfile.pAddIEAssoc =
12550 pWextState->assocAddIE.addIEdata;
12551 pWextState->roamProfile.nAddIEAssocLength =
12552 pWextState->assocAddIE.length;
12553 }
12554 break;
12555 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012556 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012557 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12558 memcpy(pWextState->WPARSNIE, genie - 2,
12559 (eLen + 2));
12560 pWextState->roamProfile.pRSNReqIE =
12561 pWextState->WPARSNIE;
12562 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12563 break;
12564 /*
12565 * Appending Extended Capabilities with Interworking bit set
12566 * in Assoc Req.
12567 *
12568 * In assoc req this EXT Cap will only be taken into account if
12569 * interworkingService bit is set to 1. Currently
12570 * driver is only interested in interworkingService capability
12571 * from supplicant. If in future any other EXT Cap info is
12572 * required from supplicat, it needs to be handled while
12573 * sending Assoc Req in LIM.
12574 */
12575 case DOT11F_EID_EXTCAP:
12576 {
12577 uint16_t curAddIELen =
12578 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012579 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012580
12581 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12582 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012583 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012584 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012585 return -ENOMEM;
12586 }
12587 memcpy(pWextState->assocAddIE.addIEdata +
12588 curAddIELen, genie - 2, eLen + 2);
12589 pWextState->assocAddIE.length += eLen + 2;
12590
12591 pWextState->roamProfile.pAddIEAssoc =
12592 pWextState->assocAddIE.addIEdata;
12593 pWextState->roamProfile.nAddIEAssocLength =
12594 pWextState->assocAddIE.length;
12595 break;
12596 }
12597#ifdef FEATURE_WLAN_WAPI
12598 case WLAN_EID_WAPI:
12599 /* Setting WAPI Mode to ON=1 */
12600 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012601 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012602 tmp = (u16 *) ie;
12603 tmp = tmp + 2; /* Skip element Id and Len, Version */
12604 akmsuiteCount = WPA_GET_LE16(tmp);
12605 tmp = tmp + 1;
12606 akmlist = (int *)(tmp);
12607 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12608 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12609 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012610 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012611 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 return -EINVAL;
12613 }
12614
12615 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012616 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 pAdapter->wapi_info.wapiAuthMode =
12618 WAPI_AUTH_MODE_PSK;
12619 }
12620 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012621 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622 pAdapter->wapi_info.wapiAuthMode =
12623 WAPI_AUTH_MODE_CERT;
12624 }
12625 break;
12626#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012627 case DOT11F_EID_SUPPOPERATINGCLASSES:
12628 {
12629 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12630 status = wlan_hdd_add_assoc_ie(pWextState,
12631 genie - 2, eLen + 2);
12632 if (status)
12633 return status;
12634 break;
12635 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012636 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012637 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012638 /* when Unknown IE is received we break
12639 * and continue to the next IE in the buffer
12640 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012641 break;
12642 }
12643 genie += eLen;
12644 remLen -= eLen;
12645 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012646 return 0;
12647}
12648
12649/**
12650 * hdd_is_wpaie_present() - check for WPA ie
12651 * @ie: Pointer to ie
12652 * @ie_len: Ie length
12653 *
12654 * Parse the received IE to find the WPA IE
12655 *
12656 * Return: true if wpa ie is found else false
12657 */
12658static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12659{
12660 uint8_t eLen = 0;
12661 uint16_t remLen = ie_len;
12662 uint8_t elementId = 0;
12663
12664 while (remLen >= 2) {
12665 elementId = *ie++;
12666 eLen = *ie++;
12667 remLen -= 2;
12668 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012669 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012670 return false;
12671 }
12672 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12673 /* OUI - 0x00 0X50 0XF2
12674 * WPA Information Element - 0x01
12675 * WPA version - 0x01
12676 */
12677 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12678 return true;
12679 }
12680 ie += eLen;
12681 remLen -= eLen;
12682 }
12683 return false;
12684}
12685
12686/**
12687 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12688 * @pAdapter: Pointer to adapter
12689 * @req: Pointer to security parameters
12690 *
12691 * Return: 0 for success, non-zero for failure
12692 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012693static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12694 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012695{
12696 int status = 0;
12697 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12698 ENTER();
12699
12700 /*set wpa version */
12701 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12702
12703 if (req->crypto.wpa_versions) {
12704 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12705 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12706 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12707 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12708 }
12709 }
12710
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012711 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012712
12713 /*set authentication type */
12714 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12715
12716 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012717 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 return status;
12719 }
12720
12721 /*set key mgmt type */
12722 if (req->crypto.n_akm_suites) {
12723 status =
12724 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12725 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012726 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012727 return status;
12728 }
12729 }
12730
12731 /*set pairwise cipher type */
12732 if (req->crypto.n_ciphers_pairwise) {
12733 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12734 req->crypto.
12735 ciphers_pairwise[0],
12736 true);
12737 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012738 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 return status;
12740 }
12741 } else {
12742 /*Reset previous cipher suite to none */
12743 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12744 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012745 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012746 return status;
12747 }
12748 }
12749
12750 /*set group cipher type */
12751 status =
12752 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12753 false);
12754
12755 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012756 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012757 return status;
12758 }
12759#ifdef WLAN_FEATURE_11W
12760 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12761#endif
12762
12763 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12764 if (req->ie_len) {
12765 status =
12766 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12767 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012768 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769 return status;
12770 }
12771 }
12772
12773 /*incase of WEP set default key information */
12774 if (req->key && req->key_len) {
12775 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12776 || (WLAN_CIPHER_SUITE_WEP104 ==
12777 req->crypto.ciphers_pairwise[0])
12778 ) {
12779 if (IW_AUTH_KEY_MGMT_802_1X
12780 ==
12781 (pWextState->
12782 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012783 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784 return -EOPNOTSUPP;
12785 } else {
12786 u8 key_len = req->key_len;
12787 u8 key_idx = req->key_idx;
12788
12789 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12790 key_len)
12791 && (CSR_MAX_NUM_KEY > key_idx)
12792 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012793 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012794 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012795 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012796 Keys.
12797 KeyMaterial[key_idx][0],
12798 req->key, key_len);
12799 pWextState->roamProfile.Keys.
12800 KeyLength[key_idx] = (u8) key_len;
12801 pWextState->roamProfile.Keys.
12802 defaultIndex = (u8) key_idx;
12803 }
12804 }
12805 }
12806 }
12807
12808 return status;
12809}
12810
12811/**
12812 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12813 * @pAdapter: Pointer to adapter
12814 *
12815 * This function is used to disconnect from previous connection
12816 *
12817 * Return: 0 for success, non-zero for failure
12818 */
12819static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12820{
12821 unsigned long rc;
12822 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012823 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824
12825 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12826
Jeff Johnson9edf9572016-10-03 15:24:49 -070012827 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012828 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12829 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12830 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012831 hdd_conn_set_connection_state(pAdapter,
12832 eConnectionState_Disconnecting);
12833 /* Issue disconnect to CSR */
12834 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012835
12836 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12837 pAdapter->sessionId,
12838 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12839 /*
12840 * Wait here instead of returning directly, this will block the
12841 * next connect command and allow processing of the scan for
12842 * ssid and the previous connect command in CSR. Else we might
12843 * hit some race conditions leading to SME and HDD out of sync.
12844 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012845 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012846 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12847 } else if (0 != status) {
12848 hdd_err("csrRoamDisconnect failure, returned %d",
12849 (int)status);
12850 pHddStaCtx->staDebugState = status;
12851 result = -EINVAL;
12852 goto disconnected;
12853 }
12854
12855 rc = wait_for_completion_timeout(
12856 &pAdapter->disconnect_comp_var,
12857 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012858 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012859 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12860 pAdapter->sessionId, pHddStaCtx->staDebugState);
12861 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012862 }
12863 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012864 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012865 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012866 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012868 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012869 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012870 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012871 }
12872 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012873disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012874 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12875 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012876}
12877
12878/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012879 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12880 * @adapter: Pointer to the HDD adapter
12881 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012882 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012883 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012884 * This function will start reassociation if prev_bssid is set and bssid/
12885 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012886 *
Naveen Rawat07332902016-07-27 09:13:17 -070012887 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012888 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012889#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12890 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012891static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12892 struct cfg80211_connect_params *req,
12893 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012894{
Naveen Rawat07332902016-07-27 09:13:17 -070012895 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012896 const uint8_t *bssid = NULL;
12897 uint16_t channel = 0;
12898
12899 if (req->bssid)
12900 bssid = req->bssid;
12901 else if (req->bssid_hint)
12902 bssid = req->bssid_hint;
12903
12904 if (req->channel)
12905 channel = req->channel->hw_value;
12906 else if (req->channel_hint)
12907 channel = req->channel_hint->hw_value;
12908
12909 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012910 reassoc = true;
12911 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012912 channel, MAC_ADDR_ARRAY(bssid));
12913 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012914 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012915 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012916 }
Naveen Rawat07332902016-07-27 09:13:17 -070012917 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012918}
12919#else
Naveen Rawat07332902016-07-27 09:13:17 -070012920static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12921 struct cfg80211_connect_params *req,
12922 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012923{
Naveen Rawat07332902016-07-27 09:13:17 -070012924 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012925}
12926#endif
12927
12928/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012929 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12930 * @wiphy: Pointer to wiphy
12931 * @dev: Pointer to network device
12932 * @req: Pointer to cfg80211 connect request
12933 *
12934 * This function is used to start the association process
12935 *
12936 * Return: 0 for success, non-zero for failure
12937 */
12938static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12939 struct net_device *ndev,
12940 struct cfg80211_connect_params *req)
12941{
12942 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012943 u16 channel;
12944#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12945 const u8 *bssid_hint = req->bssid_hint;
12946#else
12947 const u8 *bssid_hint = NULL;
12948#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12950 hdd_context_t *pHddCtx;
12951
12952 ENTER();
12953
Anurag Chouhan6d760662016-02-20 16:05:43 +053012954 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012955 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012956 return -EINVAL;
12957 }
12958
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012959 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12960 hdd_err("invalid session id: %d", pAdapter->sessionId);
12961 return -EINVAL;
12962 }
12963
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012964 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965 TRACE_CODE_HDD_CFG80211_CONNECT,
12966 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012967 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012968 hdd_device_mode_to_string(pAdapter->device_mode),
12969 pAdapter->device_mode);
12970
Krunal Sonib4326f22016-03-10 13:05:51 -080012971 if (pAdapter->device_mode != QDF_STA_MODE &&
12972 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012973 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 hdd_device_mode_to_string(pAdapter->device_mode),
12975 pAdapter->device_mode);
12976 return -EINVAL;
12977 }
12978
12979 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12980 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012981 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 return -EINVAL;
12983 }
12984
12985 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012986 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012988
Naveen Rawat07332902016-07-27 09:13:17 -070012989 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012990 return status;
12991
Agrawal Ashishf156e942016-08-04 14:54:47 +053012992 /* Try disconnecting if already in connected state */
12993 status = wlan_hdd_try_disconnect(pAdapter);
12994 if (0 > status) {
12995 hdd_err("Failed to disconnect the existing connection");
12996 return -EALREADY;
12997 }
12998
12999 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013000 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013001 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013002 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013003 pAdapter->device_mode),
13004 req->channel->hw_value, HW_MODE_20_MHZ)) {
13005 hdd_err("This concurrency combination is not allowed");
13006 return -ECONNREFUSED;
13007 }
13008 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013009 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013010 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013011 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
13012 hdd_err("This concurrency combination is not allowed");
13013 return -ECONNREFUSED;
13014 }
13015 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013016
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013017 /*initialise security parameters */
13018 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
13019
13020 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013021 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022 return status;
13023 }
13024
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013025 if (req->channel)
13026 channel = req->channel->hw_value;
13027 else
13028 channel = 0;
13029 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
13030 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013031 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013032 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013033 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013034 return status;
13035 }
13036 EXIT();
13037 return status;
13038}
13039
13040/**
13041 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
13042 * @wiphy: Pointer to wiphy
13043 * @dev: Pointer to network device
13044 * @req: Pointer to cfg80211 connect request
13045 *
13046 * Return: 0 for success, non-zero for failure
13047 */
13048static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13049 struct net_device *ndev,
13050 struct cfg80211_connect_params *req)
13051{
13052 int ret;
13053 cds_ssr_protect(__func__);
13054 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
13055 cds_ssr_unprotect(__func__);
13056
13057 return ret;
13058}
13059
13060/**
13061 * wlan_hdd_disconnect() - hdd disconnect api
13062 * @pAdapter: Pointer to adapter
13063 * @reason: Disconnect reason code
13064 *
13065 * This function is used to issue a disconnect request to SME
13066 *
13067 * Return: 0 for success, non-zero for failure
13068 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013069static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070{
13071 int status, result = 0;
13072 unsigned long rc;
13073 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13074 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13075
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013076 ENTER();
13077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013078 status = wlan_hdd_validate_context(pHddCtx);
13079
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013080 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013081 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082
13083 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013084 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
13086 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013087 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013088 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
13089 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13090
13091 /*issue disconnect */
13092
13093 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13094 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053013095 /*
13096 * Wait here instead of returning directly, this will block the next
13097 * connect command and allow processing of the scan for ssid and
13098 * the previous connect command in CSR. Else we might hit some
13099 * race conditions leading to SME and HDD out of sync.
13100 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013101 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013102 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013103 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013104 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 (int)status);
13106 pHddStaCtx->staDebugState = status;
13107 result = -EINVAL;
13108 goto disconnected;
13109 }
13110 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13111 msecs_to_jiffies
13112 (WLAN_WAIT_TIME_DISCONNECT));
13113
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013114 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013115 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013116 result = -ETIMEDOUT;
13117 }
13118disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013119 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13120#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
13121 /* Sending disconnect event to userspace for kernel version < 3.11
13122 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
13123 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013124 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053013125 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
13126 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013127#endif
13128
13129 return result;
13130}
13131
13132/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013133 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
13134 * @reason: ieee80211 reason code.
13135 *
13136 * This utility function helps log string conversion of reason code.
13137 *
13138 * Return: string conversion of reason code, if match found;
13139 * "Unknown" otherwise.
13140 */
13141static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
13142{
13143 switch (reason) {
13144 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
13145 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
13146 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
13147 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
13148 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
13149 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13150 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
13151 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
13152 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
13153 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
13154 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
13155 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
13156 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
13157 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
13158 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
13159 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
13160 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
13161 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
13162 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
13163 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
13164 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
13165 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
13166 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
13167 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
13168 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
13169 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
13170 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
13171 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
13172 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
13173 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
13174 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
13175 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
13176 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
13177 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
13178 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
13179 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
13180 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
13181 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
13182 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
13183 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
13184 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
13185 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
13186 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
13187 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
13188 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
13189 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
13190 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
13191 default:
13192 return "Unknown";
13193 }
13194}
13195
13196/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013197 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13198 * @wiphy: Pointer to wiphy
13199 * @dev: Pointer to network device
13200 * @reason: Disconnect reason code
13201 *
13202 * This function is used to issue a disconnect request to SME
13203 *
13204 * Return: 0 for success, non-zero for failure
13205 */
13206static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13207 struct net_device *dev, u16 reason)
13208{
13209 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13210 int status;
13211 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13212 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13213#ifdef FEATURE_WLAN_TDLS
13214 uint8_t staIdx;
13215#endif
13216
13217 ENTER();
13218
Anurag Chouhan6d760662016-02-20 16:05:43 +053013219 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013220 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013221 return -EINVAL;
13222 }
13223
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013224 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13225 hdd_err("invalid session id: %d", pAdapter->sessionId);
13226 return -EINVAL;
13227 }
13228
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013229 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230 TRACE_CODE_HDD_CFG80211_DISCONNECT,
13231 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013232 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 hdd_device_mode_to_string(pAdapter->device_mode),
13234 pAdapter->device_mode, reason);
13235
13236 status = wlan_hdd_validate_context(pHddCtx);
13237
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080013238 if (hdd_is_roaming_in_progress()) {
13239 hdd_err("Roaming In Progress. Ignore!!!");
13240 return -EAGAIN;
13241 }
13242
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013243 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013244 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245
13246 /* Issue disconnect request to SME, if station is in connected state */
13247 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
13248 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
13249 eCsrRoamDisconnectReason reasonCode =
13250 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13251 hdd_scaninfo_t *pScanInfo;
13252
13253 switch (reason) {
13254 case WLAN_REASON_MIC_FAILURE:
13255 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
13256 break;
13257
13258 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
13259 case WLAN_REASON_DISASSOC_AP_BUSY:
13260 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
13261 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
13262 break;
13263
13264 case WLAN_REASON_PREV_AUTH_NOT_VALID:
13265 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
13266 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
13267 break;
13268
13269 case WLAN_REASON_DEAUTH_LEAVING:
13270 reasonCode =
13271 pHddCtx->config->
13272 gEnableDeauthToDisassocMap ?
13273 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
13274 eCSR_DISCONNECT_REASON_DEAUTH;
13275 break;
13276 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
13277 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
13278 break;
13279 default:
13280 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
13281 break;
13282 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013283 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013285 pScanInfo = &pAdapter->scan_info;
13286 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013287 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013288 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053013289 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 eCSR_SCAN_ABORT_DEFAULT);
13291 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053013292 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013293#ifdef FEATURE_WLAN_TDLS
13294 /* First clean up the tdls peers if any */
13295 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
13296 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
13297 pAdapter->sessionId)
13298 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
13299 uint8_t *mac;
13300 mac =
13301 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013302 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
13303 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304 pHddCtx->tdlsConnInfo[staIdx].staId,
13305 pAdapter->sessionId,
13306 MAC_ADDR_ARRAY(mac));
13307 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
13308 (pAdapter),
13309 pAdapter->sessionId, mac);
13310 }
13311 }
13312#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013313 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013315 hdd_info("Disconnect request from user space with reason: %s",
13316 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013317 status = wlan_hdd_disconnect(pAdapter, reasonCode);
13318 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013319 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013320 return -EINVAL;
13321 }
13322 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013323 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013324 pHddStaCtx->conn_info.connState);
13325 }
13326
13327 return status;
13328}
13329
13330/**
13331 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13332 * @wiphy: Pointer to wiphy
13333 * @dev: Pointer to network device
13334 * @reason: Disconnect reason code
13335 *
13336 * Return: 0 for success, non-zero for failure
13337 */
13338static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13339 struct net_device *dev, u16 reason)
13340{
13341 int ret;
13342 cds_ssr_protect(__func__);
13343 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13344 cds_ssr_unprotect(__func__);
13345
13346 return ret;
13347}
13348
13349/**
13350 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13351 * @pAdapter: Pointer to adapter
13352 * @param: Pointer to IBSS parameters
13353 *
13354 * This function is used to initialize the security settings in IBSS mode
13355 *
13356 * Return: 0 for success, non-zero for failure
13357 */
13358static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13359 struct cfg80211_ibss_params
13360 *params)
13361{
13362 int status = 0;
13363 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13364 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13365 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13366
13367 ENTER();
13368
13369 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013370 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 pHddStaCtx->ibss_enc_key_installed = 0;
13372
13373 if (params->ie_len && (NULL != params->ie)) {
13374 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13375 params->ie_len, WLAN_EID_RSN)) {
13376 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13377 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13378 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13379 tDot11fIEWPA dot11WPAIE;
13380 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13381 u8 *ie;
13382
13383 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13384 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13385 params->ie_len,
13386 DOT11F_EID_WPA);
13387 if (NULL != ie) {
13388 pWextState->wpaVersion =
13389 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013390 /* Unpack the WPA IE
13391 * Skip past the EID byte and length byte
13392 * and four byte WiFi OUI
13393 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13395 &ie[2 + 4],
13396 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013397 /* Extract the multicast cipher, the
13398 * encType for unicast cipher for
13399 * wpa-none is none
13400 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013401 encryptionType =
13402 hdd_translate_wpa_to_csr_encryption_type
13403 (dot11WPAIE.multicast_cipher);
13404 }
13405 }
13406
13407 status =
13408 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13409 params->ie_len);
13410
13411 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013412 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413 return status;
13414 }
13415 }
13416
13417 pWextState->roamProfile.AuthType.authType[0] =
13418 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13419
13420 if (params->privacy) {
13421 /* Security enabled IBSS, At this time there is no information
13422 * available about the security paramters, so initialise the
13423 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13424 * The correct security parameters will be updated later in
13425 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13426 * set inorder enable privacy bit in beacons
13427 */
13428
13429 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13430 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013431 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13433 pWextState->roamProfile.EncryptionType.numEntries = 1;
13434 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13435 encryptionType;
13436 return status;
13437}
13438
13439/**
13440 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13441 * @wiphy: Pointer to wiphy
13442 * @dev: Pointer to network device
13443 * @param: Pointer to IBSS join parameters
13444 *
13445 * This function is used to create/join an IBSS network
13446 *
13447 * Return: 0 for success, non-zero for failure
13448 */
13449static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13450 struct net_device *dev,
13451 struct cfg80211_ibss_params *params)
13452{
13453 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13454 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13455 tCsrRoamProfile *pRoamProfile;
13456 int status;
13457 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13458 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013459 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013460 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013461
13462 ENTER();
13463
Anurag Chouhan6d760662016-02-20 16:05:43 +053013464 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013465 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013466 return -EINVAL;
13467 }
13468
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013469 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13470 hdd_err("invalid session id: %d", pAdapter->sessionId);
13471 return -EINVAL;
13472 }
13473
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013474 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013475 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13476 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013477 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013478 hdd_device_mode_to_string(pAdapter->device_mode),
13479 pAdapter->device_mode);
13480
13481 status = wlan_hdd_validate_context(pHddCtx);
13482
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013483 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013484 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013485
13486 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013487 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013488 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13489 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13490 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13491 int indx;
13492
13493 /* Get channel number */
13494 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013495 params->
13496 chandef.
13497 chan->
13498 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013499
13500 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13501 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013502 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013503 return -EOPNOTSUPP;
13504 }
13505
13506 for (indx = 0; indx < numChans; indx++) {
13507 if (channelNum == validChan[indx]) {
13508 break;
13509 }
13510 }
13511 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013512 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513 return -EINVAL;
13514 }
13515 }
13516
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013517 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013518 HW_MODE_20_MHZ)) {
13519 hdd_err("This concurrency combination is not allowed");
13520 return -ECONNREFUSED;
13521 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013522
Krunal Soni3091bcc2016-06-23 12:28:21 -070013523 status = qdf_reset_connection_update();
13524 if (!QDF_IS_STATUS_SUCCESS(status))
13525 hdd_err("ERR: clear event failed");
13526
13527 status = cds_current_connections_update(pAdapter->sessionId,
13528 channelNum,
13529 SIR_UPDATE_REASON_JOIN_IBSS);
13530 if (QDF_STATUS_E_FAILURE == status) {
13531 hdd_err("ERROR: connections update failed!!");
13532 return -EINVAL;
13533 }
13534
13535 if (QDF_STATUS_SUCCESS == status) {
13536 status = qdf_wait_for_connection_update();
13537 if (!QDF_IS_STATUS_SUCCESS(status)) {
13538 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539 return -EINVAL;
13540 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013541 }
13542
13543 /*Try disconnecting if already in connected state */
13544 status = wlan_hdd_try_disconnect(pAdapter);
13545 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013546 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013547 return -EALREADY;
13548 }
13549
13550 pRoamProfile = &pWextState->roamProfile;
13551
13552 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013553 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 return -EINVAL;
13555 }
13556
13557 /* enable selected protection checks in IBSS mode */
13558 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13559
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013560 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013561 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13562 pHddCtx->config->
13563 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013564 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565 }
13566
13567 /* BSSID is provided by upper layers hence no need to AUTO generate */
13568 if (NULL != params->bssid) {
13569 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013570 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013571 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572 return -EIO;
13573 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013574 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013575 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13576 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013577 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013578 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013579 return -EIO;
13580 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013581 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582 }
13583 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13584 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13585 pRoamProfile->beaconInterval = params->beacon_interval;
13586 else {
13587 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013588 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013589 params->beacon_interval, pRoamProfile->beaconInterval);
13590 }
13591
13592 /* Set Channel */
13593 if (channelNum) {
13594 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013595 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013596 pRoamProfile->ChannelInfo.numOfChannels = 1;
13597 pHddStaCtx->conn_info.operationChannel = channelNum;
13598 pRoamProfile->ChannelInfo.ChannelList =
13599 &pHddStaCtx->conn_info.operationChannel;
13600 }
13601
13602 /* Initialize security parameters */
13603 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13604 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013605 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 return status;
13607 }
13608
13609 /* Issue connect start */
13610 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13611 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013612 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013613 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013614 operationChannel,
13615 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013616
13617 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013618 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013619 return status;
13620 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013621 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013622 return 0;
13623}
13624
13625/**
13626 * wlan_hdd_cfg80211_join_ibss() - join ibss
13627 * @wiphy: Pointer to wiphy
13628 * @dev: Pointer to network device
13629 * @param: Pointer to IBSS join parameters
13630 *
13631 * This function is used to create/join an IBSS network
13632 *
13633 * Return: 0 for success, non-zero for failure
13634 */
13635static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13636 struct net_device *dev,
13637 struct cfg80211_ibss_params *params)
13638{
13639 int ret = 0;
13640
13641 cds_ssr_protect(__func__);
13642 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13643 cds_ssr_unprotect(__func__);
13644
13645 return ret;
13646}
13647
13648/**
13649 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13650 * @wiphy: Pointer to wiphy
13651 * @dev: Pointer to network device
13652 *
13653 * This function is used to leave an IBSS network
13654 *
13655 * Return: 0 for success, non-zero for failure
13656 */
13657static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13658 struct net_device *dev)
13659{
13660 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13661 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13662 tCsrRoamProfile *pRoamProfile;
13663 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13664 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013665 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013666 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013667 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013668
13669 ENTER();
13670
Anurag Chouhan6d760662016-02-20 16:05:43 +053013671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013672 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013673 return -EINVAL;
13674 }
13675
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013676 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13677 hdd_err("invalid session id: %d", pAdapter->sessionId);
13678 return -EINVAL;
13679 }
13680
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013681 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013682 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13683 pAdapter->sessionId,
13684 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13685 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013686 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013687 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013688
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013689 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690 hdd_device_mode_to_string(pAdapter->device_mode),
13691 pAdapter->device_mode);
13692 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013693 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 return -EIO;
13695 }
13696
13697 pRoamProfile = &pWextState->roamProfile;
13698
13699 /* Issue disconnect only if interface type is set to IBSS */
13700 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013701 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 return -EINVAL;
13703 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013704 /* Clearing add IE of beacon */
13705 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13706 sizeof(tSirMacAddr));
13707 updateIE.smeSessionId = pAdapter->sessionId;
13708 updateIE.ieBufferlength = 0;
13709 updateIE.pAdditionIEBuffer = NULL;
13710 updateIE.append = true;
13711 updateIE.notify = true;
13712 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13713 &updateIE,
13714 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013715 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013716 }
13717
13718 /* Reset WNI_CFG_PROBE_RSP Flags */
13719 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720
13721 /* Issue Disconnect request */
13722 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13723 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13724 pAdapter->sessionId,
13725 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013726 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013727 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013728 hal_status);
13729 return -EAGAIN;
13730 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013731
13732 /* wait for mc thread to cleanup and then return to upper stack
13733 * so by the time upper layer calls the change interface, we are
13734 * all set to proceed further
13735 */
13736 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13737 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13738 if (!rc) {
13739 hdd_err("Failed to disconnect, timed out");
13740 return -ETIMEDOUT;
13741 }
13742
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013743 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 return 0;
13745}
13746
13747/**
13748 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13749 * @wiphy: Pointer to wiphy
13750 * @dev: Pointer to network device
13751 *
13752 * This function is used to leave an IBSS network
13753 *
13754 * Return: 0 for success, non-zero for failure
13755 */
13756static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13757 struct net_device *dev)
13758{
13759 int ret = 0;
13760
13761 cds_ssr_protect(__func__);
13762 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13763 cds_ssr_unprotect(__func__);
13764
13765 return ret;
13766}
13767
13768/**
13769 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13770 * @wiphy: Pointer to wiphy
13771 * @changed: Parameters changed
13772 *
13773 * This function is used to set the phy parameters. RTS Threshold/FRAG
13774 * Threshold/Retry Count etc.
13775 *
13776 * Return: 0 for success, non-zero for failure
13777 */
13778static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13779 u32 changed)
13780{
13781 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13782 tHalHandle hHal = pHddCtx->hHal;
13783 int status;
13784
13785 ENTER();
13786
Anurag Chouhan6d760662016-02-20 16:05:43 +053013787 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013788 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789 return -EINVAL;
13790 }
13791
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013792 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013793 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13794 NO_SESSION, wiphy->rts_threshold));
13795 status = wlan_hdd_validate_context(pHddCtx);
13796
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013797 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013798 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799
13800 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13801 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13802 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13803
13804 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13805 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013806 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013807 rts_threshold);
13808 return -EINVAL;
13809 }
13810
13811 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13812 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013813 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013814 rts_threshold);
13815 return -EIO;
13816 }
13817
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013818 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013819 }
13820
13821 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13822 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13823 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13824 wiphy->frag_threshold;
13825
13826 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13827 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013828 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829 frag_threshold);
13830 return -EINVAL;
13831 }
13832
13833 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13834 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013835 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013836 frag_threshold);
13837 return -EIO;
13838 }
13839
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013840 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013841 }
13842
13843 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13844 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13845 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13846 wiphy->retry_short : wiphy->retry_long;
13847
13848 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13849 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013850 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 return -EINVAL;
13852 }
13853
13854 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13855 if (0 != sme_cfg_set_int(hHal,
13856 WNI_CFG_LONG_RETRY_LIMIT,
13857 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013858 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013859 retry_value);
13860 return -EIO;
13861 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013862 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013863 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13864 if (0 != sme_cfg_set_int(hHal,
13865 WNI_CFG_SHORT_RETRY_LIMIT,
13866 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013867 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013868 retry_value);
13869 return -EIO;
13870 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013871 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013872 }
13873 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013874 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013875 return 0;
13876}
13877
13878/**
13879 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13880 * @wiphy: Pointer to wiphy
13881 * @changed: Parameters changed
13882 *
13883 * Return: 0 for success, non-zero for failure
13884 */
13885static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13886{
13887 int ret;
13888
13889 cds_ssr_protect(__func__);
13890 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13891 cds_ssr_unprotect(__func__);
13892
13893 return ret;
13894}
13895
13896/**
13897 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13898 * key
13899 * @wiphy: Pointer to wiphy
13900 * @dev: Pointer to network device
13901 * @key_index: Key index
13902 *
13903 * Return: 0
13904 */
13905static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13906 struct net_device *netdev,
13907 u8 key_index)
13908{
13909 ENTER();
13910 return 0;
13911}
13912
13913/**
13914 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13915 * wlan_hdd_set_default_mgmt_key
13916 * @wiphy: pointer to wiphy
13917 * @netdev: pointer to net_device structure
13918 * @key_index: key index
13919 *
13920 * Return: 0 on success, error number on failure
13921 */
13922static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13923 struct net_device *netdev,
13924 u8 key_index)
13925{
13926 int ret;
13927
13928 cds_ssr_protect(__func__);
13929 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13930 cds_ssr_unprotect(__func__);
13931
13932 return ret;
13933}
13934
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013935/**
13936 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13937 * @wiphy: Pointer to wiphy
13938 * @dev: Pointer to network device
13939 * @params: Pointer to tx queue parameters
13940 *
13941 * Return: 0
13942 */
13943static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13944 struct net_device *dev,
13945 struct ieee80211_txq_params *params)
13946{
13947 ENTER();
13948 return 0;
13949}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950
13951/**
13952 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13953 * @wiphy: pointer to wiphy
13954 * @netdev: pointer to net_device structure
13955 * @params: pointer to ieee80211_txq_params
13956 *
13957 * Return: 0 on success, error number on failure
13958 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013959static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13960 struct net_device *dev,
13961 struct ieee80211_txq_params *params)
13962{
13963 int ret;
13964
13965 cds_ssr_protect(__func__);
13966 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13967 cds_ssr_unprotect(__func__);
13968
13969 return ret;
13970}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013971
13972/**
13973 * __wlan_hdd_cfg80211_del_station() - delete station v2
13974 * @wiphy: Pointer to wiphy
13975 * @param: Pointer to delete station parameter
13976 *
13977 * Return: 0 for success, non-zero for failure
13978 */
13979static
13980int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13981 struct net_device *dev,
13982 struct tagCsrDelStaParams *pDelStaParams)
13983{
13984 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13985 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013986 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013987 hdd_hostapd_state_t *hapd_state;
13988 int status;
13989 uint8_t staId;
13990 uint8_t *mac;
13991
13992 ENTER();
13993
Anurag Chouhan6d760662016-02-20 16:05:43 +053013994 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013995 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013996 return -EINVAL;
13997 }
13998
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013999 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14000 hdd_err("invalid session id: %d", pAdapter->sessionId);
14001 return -EINVAL;
14002 }
14003
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014004 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014005 TRACE_CODE_HDD_CFG80211_DEL_STA,
14006 pAdapter->sessionId, pAdapter->device_mode));
14007
14008 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14009 status = wlan_hdd_validate_context(pHddCtx);
14010
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014011 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013
14014 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
14015
Krunal Sonib4326f22016-03-10 13:05:51 -080014016 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
14017 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018
14019 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14020 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014021 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014022 return 0;
14023 }
14024
Anurag Chouhanc5548422016-02-24 18:33:27 +053014025 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026 uint16_t i;
14027 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
14028 if ((pAdapter->aStaInfo[i].isUsed) &&
14029 (!pAdapter->aStaInfo[i].
14030 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014031 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014032 mac,
14033 pAdapter->aStaInfo[i].
14034 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014035 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14037 hdd_ipa_wlan_evt(pAdapter,
14038 pAdapter->
14039 aStaInfo[i].
14040 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014041 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 mac);
14043 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014044 hdd_notice("Delete STA with MAC::"
14045 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 MAC_ADDR_ARRAY(mac));
14047
14048 if (pHddCtx->dev_dfs_cac_status ==
14049 DFS_CAC_IN_PROGRESS)
14050 goto fn_end;
14051
Wei Song2f76f642016-11-18 16:32:53 +080014052 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014053 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053014054 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014055 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014056 hdd_softap_sta_deauth(pAdapter,
14057 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014058 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014059 pAdapter->aStaInfo[i].
14060 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014061 qdf_status =
14062 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014063 &hapd_state->
14064 qdf_sta_disassoc_event,
14065 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014066 if (!QDF_IS_STATUS_SUCCESS(
14067 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014068 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 }
14070 }
14071 }
14072 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014073 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014074 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014075 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014077 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014078 hdd_notice("Skip DEL STA as this is not used::"
14079 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014080 MAC_ADDR_ARRAY(mac));
14081 return -ENOENT;
14082 }
14083
14084 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14085 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014086 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087 }
14088
14089 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
14090 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014091 hdd_notice("Skip DEL STA as deauth is in progress::"
14092 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 MAC_ADDR_ARRAY(mac));
14094 return -ENOENT;
14095 }
14096
14097 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
14098
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014099 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014100 MAC_ADDR_ARRAY(mac));
14101
14102 /* Case: SAP in ACS selected DFS ch and client connected
14103 * Now Radar detected. Then if random channel is another
14104 * DFS ch then new CAC is initiated and no TX allowed.
14105 * So do not send any mgmt frames as it will timeout
14106 * during CAC.
14107 */
14108
14109 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
14110 goto fn_end;
14111
Wei Song2f76f642016-11-18 16:32:53 +080014112 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053014113 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
14114 (pAdapter), pAdapter->sessionId,
14115 (uint8_t *)&pDelStaParams->peerMacAddr,
14116 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014117 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014118 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014119 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014120 pAdapter->aStaInfo[staId].isDeauthInProgress =
14121 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014122 hdd_notice("STA removal failed for ::"
14123 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014124 MAC_ADDR_ARRAY(mac));
14125 return -ENOENT;
14126 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053014127 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014128 &hapd_state->
14129 qdf_sta_disassoc_event,
14130 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014131 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014132 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133 }
14134 }
14135 }
14136
14137fn_end:
14138 EXIT();
14139 return 0;
14140}
14141
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014142#if defined(USE_CFG80211_DEL_STA_V2)
14143/**
14144 * wlan_hdd_del_station() - delete station wrapper
14145 * @adapter: pointer to the hdd adapter
14146 *
14147 * Return: None
14148 */
14149void wlan_hdd_del_station(hdd_adapter_t *adapter)
14150{
14151 struct station_del_parameters del_sta;
14152 del_sta.mac = NULL;
14153 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
14154 del_sta.reason_code = eCsrForcedDeauthSta;
14155
14156 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
14157 &del_sta);
14158}
14159#else
14160void wlan_hdd_del_station(hdd_adapter_t *adapter)
14161{
14162 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
14163}
14164#endif
14165
14166#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014167/**
14168 * wlan_hdd_cfg80211_del_station() - delete station v2
14169 * @wiphy: Pointer to wiphy
14170 * @param: Pointer to delete station parameter
14171 *
14172 * Return: 0 for success, non-zero for failure
14173 */
14174int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14175 struct net_device *dev,
14176 struct station_del_parameters *param)
14177#else
14178/**
14179 * wlan_hdd_cfg80211_del_station() - delete station
14180 * @wiphy: Pointer to wiphy
14181 * @mac: Pointer to station mac address
14182 *
14183 * Return: 0 for success, non-zero for failure
14184 */
14185#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14186int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14187 struct net_device *dev,
14188 const uint8_t *mac)
14189#else
14190int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14191 struct net_device *dev,
14192 uint8_t *mac)
14193#endif
14194#endif
14195{
14196 int ret;
14197 struct tagCsrDelStaParams delStaParams;
14198
14199 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014200#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014201 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014202 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014203 return -EINVAL;
14204 }
14205 wlansap_populate_del_sta_params(param->mac, param->reason_code,
14206 param->subtype, &delStaParams);
14207#else
14208 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14209 (SIR_MAC_MGMT_DEAUTH >> 4),
14210 &delStaParams);
14211#endif
14212 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
14213 cds_ssr_unprotect(__func__);
14214
14215 return ret;
14216}
14217
14218/**
14219 * __wlan_hdd_cfg80211_add_station() - add station
14220 * @wiphy: Pointer to wiphy
14221 * @mac: Pointer to station mac address
14222 * @pmksa: Pointer to add station parameter
14223 *
14224 * Return: 0 for success, non-zero for failure
14225 */
14226static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14227 struct net_device *dev,
14228 const uint8_t *mac,
14229 struct station_parameters *params)
14230{
14231 int status = -EPERM;
14232#ifdef FEATURE_WLAN_TDLS
14233 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14234 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14235 u32 mask, set;
14236
14237 ENTER();
14238
Anurag Chouhan6d760662016-02-20 16:05:43 +053014239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014240 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241 return -EINVAL;
14242 }
14243
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014244 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14245 hdd_err("invalid session id: %d", pAdapter->sessionId);
14246 return -EINVAL;
14247 }
14248
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014249 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014250 TRACE_CODE_HDD_CFG80211_ADD_STA,
14251 pAdapter->sessionId, params->listen_interval));
14252
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014253 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014254 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014255
14256 mask = params->sta_flags_mask;
14257
14258 set = params->sta_flags_set;
14259
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014260 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 MAC_ADDR_ARRAY(mac));
14262
14263 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14264 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14265 status =
14266 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
14267 }
14268 }
14269#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014270 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014271 return status;
14272}
14273
14274/**
14275 * wlan_hdd_cfg80211_add_station() - add station
14276 * @wiphy: Pointer to wiphy
14277 * @mac: Pointer to station mac address
14278 * @pmksa: Pointer to add station parameter
14279 *
14280 * Return: 0 for success, non-zero for failure
14281 */
14282#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14283static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14284 struct net_device *dev,
14285 const uint8_t *mac,
14286 struct station_parameters *params)
14287#else
14288static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14289 struct net_device *dev, uint8_t *mac,
14290 struct station_parameters *params)
14291#endif
14292{
14293 int ret;
14294
14295 cds_ssr_protect(__func__);
14296 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
14297 cds_ssr_unprotect(__func__);
14298
14299 return ret;
14300}
14301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014302/**
14303 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
14304 * @wiphy: Pointer to wiphy
14305 * @dev: Pointer to network device
14306 * @pmksa: Pointer to set pmksa parameter
14307 *
14308 * Return: 0 for success, non-zero for failure
14309 */
14310static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14311 struct net_device *dev,
14312 struct cfg80211_pmksa *pmksa)
14313{
14314 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14315 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14316 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014317 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318 int status;
14319 tPmkidCacheInfo pmk_id;
14320
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014321 ENTER();
14322
Anurag Chouhan6d760662016-02-20 16:05:43 +053014323 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014324 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325 return -EINVAL;
14326 }
14327
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014328 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14329 hdd_err("invalid session id: %d", pAdapter->sessionId);
14330 return -EINVAL;
14331 }
14332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014334 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 return -EINVAL;
14336 }
14337
14338 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014339 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014340 pmksa->bssid, pmksa->pmkid);
14341 return -EINVAL;
14342 }
14343
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014344 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014345 MAC_ADDR_ARRAY(pmksa->bssid));
14346
14347 status = wlan_hdd_validate_context(pHddCtx);
14348
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014349 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014350 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014351
14352 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14353
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014354 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14355 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014356
14357 /* Add to the PMKSA ID Cache in CSR */
14358 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14359 &pmk_id, 1, false);
14360
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014361 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14363 pAdapter->sessionId, result));
14364
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014365 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014366 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367}
14368
14369/**
14370 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14371 * @wiphy: Pointer to wiphy
14372 * @dev: Pointer to network device
14373 * @pmksa: Pointer to set pmksa parameter
14374 *
14375 * Return: 0 for success, non-zero for failure
14376 */
14377static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14378 struct net_device *dev,
14379 struct cfg80211_pmksa *pmksa)
14380{
14381 int ret;
14382
14383 cds_ssr_protect(__func__);
14384 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14385 cds_ssr_unprotect(__func__);
14386
14387 return ret;
14388}
14389
14390/**
14391 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14392 * @wiphy: Pointer to wiphy
14393 * @dev: Pointer to network device
14394 * @pmksa: Pointer to pmksa parameter
14395 *
14396 * Return: 0 for success, non-zero for failure
14397 */
14398static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14399 struct net_device *dev,
14400 struct cfg80211_pmksa *pmksa)
14401{
14402 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14403 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14404 tHalHandle halHandle;
14405 int status = 0;
14406
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014407 ENTER();
14408
Anurag Chouhan6d760662016-02-20 16:05:43 +053014409 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014410 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014411 return -EINVAL;
14412 }
14413
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014414 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14415 hdd_err("invalid session id: %d", pAdapter->sessionId);
14416 return -EINVAL;
14417 }
14418
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014419 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014420 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014421 return -EINVAL;
14422 }
14423
14424 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014425 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014426 return -EINVAL;
14427 }
14428
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014429 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014430 MAC_ADDR_ARRAY(pmksa->bssid));
14431
14432 status = wlan_hdd_validate_context(pHddCtx);
14433
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014434 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014435 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014436
14437 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14438
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014439 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014440 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14441 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014442 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014443 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014444 sme_roam_del_pmkid_from_cache(halHandle,
14445 pAdapter->sessionId, pmksa->bssid,
14446 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014447 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014448 MAC_ADDR_ARRAY(pmksa->bssid));
14449 status = -EINVAL;
14450 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014451 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 return status;
14453}
14454
14455/**
14456 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14457 * @wiphy: Pointer to wiphy
14458 * @dev: Pointer to network device
14459 * @pmksa: Pointer to pmksa parameter
14460 *
14461 * Return: 0 for success, non-zero for failure
14462 */
14463static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14464 struct net_device *dev,
14465 struct cfg80211_pmksa *pmksa)
14466{
14467 int ret;
14468
14469 cds_ssr_protect(__func__);
14470 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14471 cds_ssr_unprotect(__func__);
14472
14473 return ret;
14474
14475}
14476
14477/**
14478 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14479 * @wiphy: Pointer to wiphy
14480 * @dev: Pointer to network device
14481 *
14482 * Return: 0 for success, non-zero for failure
14483 */
14484static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14485 struct net_device *dev)
14486{
14487 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14488 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14489 tHalHandle halHandle;
14490 int status = 0;
14491
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014492 ENTER();
14493
Anurag Chouhan6d760662016-02-20 16:05:43 +053014494 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014495 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496 return -EINVAL;
14497 }
14498
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014499 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14500 hdd_err("invalid session id: %d", pAdapter->sessionId);
14501 return -EINVAL;
14502 }
14503
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014504 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014505
14506 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14507 status = wlan_hdd_validate_context(pHddCtx);
14508
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014509 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014511
14512 /* Retrieve halHandle */
14513 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14514
14515 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014516 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014517 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14518 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014519 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520 status = -EINVAL;
14521 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014522 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 return status;
14524}
14525
14526/**
14527 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14528 * @wiphy: Pointer to wiphy
14529 * @dev: Pointer to network device
14530 *
14531 * Return: 0 for success, non-zero for failure
14532 */
14533static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14534 struct net_device *dev)
14535{
14536 int ret;
14537
14538 cds_ssr_protect(__func__);
14539 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14540 cds_ssr_unprotect(__func__);
14541
14542 return ret;
14543}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014545#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014546/**
14547 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14548 * @wiphy: Pointer to wiphy
14549 * @dev: Pointer to network device
14550 * @ftie: Pointer to fast transition ie parameter
14551 *
14552 * Return: 0 for success, non-zero for failure
14553 */
14554static int
14555__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14556 struct net_device *dev,
14557 struct cfg80211_update_ft_ies_params *ftie)
14558{
14559 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14560 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14561 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14562 int status;
14563
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014564 ENTER();
14565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014566 status = wlan_hdd_validate_context(hdd_ctx);
14567 if (status)
14568 return status;
14569
Anurag Chouhan6d760662016-02-20 16:05:43 +053014570 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014571 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 return -EINVAL;
14573 }
14574
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014575 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14576 hdd_err("invalid session id: %d", pAdapter->sessionId);
14577 return -EINVAL;
14578 }
14579
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014580 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014581 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14582 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14583 /* Added for debug on reception of Re-assoc Req. */
14584 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014585 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014586 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014587 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014588 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014589 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014591
14592 /* Pass the received FT IEs to SME */
14593 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14594 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014595 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014596 return 0;
14597}
14598
14599/**
14600 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14601 * @wiphy: Pointer to wiphy
14602 * @dev: Pointer to network device
14603 * @ftie: Pointer to fast transition ie parameter
14604 *
14605 * Return: 0 for success, non-zero for failure
14606 */
14607static int
14608wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14609 struct net_device *dev,
14610 struct cfg80211_update_ft_ies_params *ftie)
14611{
14612 int ret;
14613
14614 cds_ssr_protect(__func__);
14615 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14616 cds_ssr_unprotect(__func__);
14617
14618 return ret;
14619}
14620#endif
14621
14622#ifdef WLAN_FEATURE_GTK_OFFLOAD
14623/**
14624 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14625 * @callbackContext: Callback context
14626 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14627 *
14628 * Callback rountine called upon receiving response for get offload info
14629 *
14630 * Return: none
14631 */
14632void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14633 tpSirGtkOffloadGetInfoRspParams
14634 pGtkOffloadGetInfoRsp)
14635{
14636 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14637 uint8_t tempReplayCounter[8];
14638 hdd_station_ctx_t *pHddStaCtx;
14639
14640 ENTER();
14641
14642 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014643 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014644 return;
14645 }
14646
14647 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014648 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014649 return;
14650 }
14651
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014652 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014653 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014654 return;
14655 }
14656
14657 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14658 /* Update replay counter */
14659 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14660 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14661
14662 {
14663 /* changing from little to big endian since supplicant
14664 * works on big endian format
14665 */
14666 int i;
14667 uint8_t *p =
14668 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14669
14670 for (i = 0; i < 8; i++) {
14671 tempReplayCounter[7 - i] = (uint8_t) p[i];
14672 }
14673 }
14674
14675 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014676 cfg80211_gtk_rekey_notify(pAdapter->dev,
14677 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014678 tempReplayCounter, GFP_KERNEL);
14679}
14680
14681/**
14682 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14683 * @wiphy: Pointer to wiphy
14684 * @dev: Pointer to network device
14685 * @data: Pointer to rekey data
14686 *
14687 * This function is used to offload GTK rekeying job to the firmware.
14688 *
14689 * Return: 0 for success, non-zero for failure
14690 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014691static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014692int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14693 struct net_device *dev,
14694 struct cfg80211_gtk_rekey_data *data)
14695{
14696 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14697 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14698 hdd_station_ctx_t *pHddStaCtx;
14699 tHalHandle hHal;
14700 int result;
14701 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014702 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703
14704 ENTER();
14705
Anurag Chouhan6d760662016-02-20 16:05:43 +053014706 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014707 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014708 return -EINVAL;
14709 }
14710
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014711 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14712 hdd_err("invalid session id: %d", pAdapter->sessionId);
14713 return -EINVAL;
14714 }
14715
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014716 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014717 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14718 pAdapter->sessionId, pAdapter->device_mode));
14719
14720 result = wlan_hdd_validate_context(pHddCtx);
14721
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014722 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014723 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014724
14725 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14726 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14727 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014728 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014729 return -EAGAIN;
14730 }
14731
14732 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14733 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14734 NL80211_KCK_LEN);
14735 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14736 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014737 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014738 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 {
14740 /* changing from big to little endian since driver
14741 * works on little endian format
14742 */
14743 uint8_t *p =
14744 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14745 ullKeyReplayCounter;
14746 int i;
14747
14748 for (i = 0; i < 8; i++) {
14749 p[7 - i] = data->replay_ctr[i];
14750 }
14751 }
14752
14753 if (true == pHddCtx->hdd_wlan_suspended) {
14754 /* if wlan is suspended, enable GTK offload directly from here */
14755 memcpy(&hddGtkOffloadReqParams,
14756 &pHddStaCtx->gtkOffloadReqParams,
14757 sizeof(tSirGtkOffloadParams));
14758 status =
14759 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14760 pAdapter->sessionId);
14761
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014762 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014763 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014764 status);
14765 return -EINVAL;
14766 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014767 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014768 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014769 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014770 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014771 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772 return result;
14773}
14774
14775/**
14776 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14777 * @wiphy: Pointer to wiphy
14778 * @dev: Pointer to network device
14779 * @data: Pointer to rekey data
14780 *
14781 * This function is used to offload GTK rekeying job to the firmware.
14782 *
14783 * Return: 0 for success, non-zero for failure
14784 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014785static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014786int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14787 struct net_device *dev,
14788 struct cfg80211_gtk_rekey_data *data)
14789{
14790 int ret;
14791
14792 cds_ssr_protect(__func__);
14793 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14794 cds_ssr_unprotect(__func__);
14795
14796 return ret;
14797}
14798#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14799
14800/**
14801 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14802 * @wiphy: Pointer to wiphy
14803 * @dev: Pointer to network device
14804 * @param: Pointer to access control parameter
14805 *
14806 * Return: 0 for success, non-zero for failure
14807 */
14808static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14809 struct net_device *dev,
14810 const struct cfg80211_acl_data *params)
14811{
14812 int i;
14813 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14814 hdd_hostapd_state_t *pHostapdState;
14815 tsap_Config_t *pConfig;
14816 v_CONTEXT_t p_cds_context = NULL;
14817 hdd_context_t *pHddCtx;
14818 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014819 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820
14821 ENTER();
14822
Anurag Chouhan6d760662016-02-20 16:05:43 +053014823 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014824 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 return -EINVAL;
14826 }
14827
14828 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014829 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 return -EINVAL;
14831 }
14832
14833 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14834 status = wlan_hdd_validate_context(pHddCtx);
14835
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014836 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014837 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014838
14839 p_cds_context = pHddCtx->pcds_context;
14840 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14841
14842 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014843 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014844 return -EINVAL;
14845 }
14846
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014847 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014848 params->n_acl_entries);
14849
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014850 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014851 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14852 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014853 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014854 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14855
14856 /* default value */
14857 pConfig->num_accept_mac = 0;
14858 pConfig->num_deny_mac = 0;
14859
14860 /**
14861 * access control policy
14862 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14863 * listed in hostapd.deny file.
14864 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14865 * listed in hostapd.accept file.
14866 */
14867 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14868 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14869 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14870 params->acl_policy) {
14871 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14872 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014873 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014874 params->acl_policy);
14875 return -ENOTSUPP;
14876 }
14877
14878 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14879 pConfig->num_accept_mac = params->n_acl_entries;
14880 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014881 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14882 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 MAC_ADDR_ARRAY(
14884 params->mac_addrs[i].addr));
14885
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014886 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014887 params->mac_addrs[i].addr,
14888 sizeof(qcmacaddr));
14889 }
14890 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14891 pConfig->num_deny_mac = params->n_acl_entries;
14892 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014893 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14894 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014895 MAC_ADDR_ARRAY(
14896 params->mac_addrs[i].addr));
14897
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014898 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014899 params->mac_addrs[i].addr,
14900 sizeof(qcmacaddr));
14901 }
14902 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014903 qdf_status = wlansap_set_mac_acl(
14904 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014905 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014906 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014907 return -EINVAL;
14908 }
14909 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014910 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 hdd_device_mode_to_string(pAdapter->device_mode),
14912 pAdapter->device_mode);
14913 return -EINVAL;
14914 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014915 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014916 return 0;
14917}
14918
14919/**
14920 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14921 * __wlan_hdd_cfg80211_set_mac_acl
14922 * @wiphy: pointer to wiphy structure
14923 * @dev: pointer to net_device
14924 * @params: pointer to cfg80211_acl_data
14925 *
14926 * Return; 0 on success, error number otherwise
14927 */
14928static int
14929wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14930 struct net_device *dev,
14931 const struct cfg80211_acl_data *params)
14932{
14933 int ret;
14934
14935 cds_ssr_protect(__func__);
14936 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14937 cds_ssr_unprotect(__func__);
14938
14939 return ret;
14940}
14941
14942#ifdef WLAN_NL80211_TESTMODE
14943#ifdef FEATURE_WLAN_LPHB
14944/**
14945 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14946 * @pHddCtx: Pointer to hdd context
14947 * @lphbInd: Pointer to low power heart beat indication parameter
14948 *
14949 * Return: none
14950 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014951static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14952 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014953{
14954 struct sk_buff *skb;
14955
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014956 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014958 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014959 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014960
14961 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014962 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014963 return;
14964 }
14965
14966 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14967 wiphy, sizeof(tSirLPHBInd),
14968 GFP_ATOMIC);
14969 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014970 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014971 return;
14972 }
14973
14974 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014975 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014976 goto nla_put_failure;
14977 }
14978 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014979 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 goto nla_put_failure;
14981 }
14982 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014983 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014984 goto nla_put_failure;
14985 }
14986 cfg80211_testmode_event(skb, GFP_ATOMIC);
14987 return;
14988
14989nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014990 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014991 kfree_skb(skb);
14992
14993 return;
14994}
14995#endif /* FEATURE_WLAN_LPHB */
14996
14997/**
14998 * __wlan_hdd_cfg80211_testmode() - test mode
14999 * @wiphy: Pointer to wiphy
15000 * @data: Data pointer
15001 * @len: Data length
15002 *
15003 * Return: 0 for success, non-zero for failure
15004 */
15005static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15006 void *data, int len)
15007{
15008 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
15009 int err;
15010 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15011
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015012 ENTER();
15013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015014 err = wlan_hdd_validate_context(pHddCtx);
15015 if (err)
15016 return err;
15017
15018 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
15019 len, wlan_hdd_tm_policy);
15020 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015021 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 return err;
15023 }
15024
15025 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015026 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015027 return -EINVAL;
15028 }
15029
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015030 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015031 TRACE_CODE_HDD_CFG80211_TESTMODE,
15032 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015033 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
15034#ifdef FEATURE_WLAN_LPHB
15035 /* Low Power Heartbeat configuration request */
15036 case WLAN_HDD_TM_CMD_WLAN_HB:
15037 {
15038 int buf_len;
15039 void *buf;
15040 tSirLPHBReq *hb_params = NULL;
15041 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015042 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043
15044 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015045 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015046 return -EINVAL;
15047 }
15048
15049 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15050 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15051
15052 hb_params_temp = (tSirLPHBReq *) buf;
15053 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
15054 && (hb_params_temp->params.lphbTcpParamReq.
15055 timePeriodSec == 0))
15056 return -EINVAL;
15057
15058 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015059 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015060 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015061 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015062 return -ENOMEM;
15063 }
15064
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015065 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015066 smeStatus =
15067 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
15068 hb_params,
15069 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015070 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015071 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015072 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015073 }
15074 return 0;
15075 }
15076#endif /* FEATURE_WLAN_LPHB */
15077
15078#if defined(QCA_WIFI_FTM)
15079 case WLAN_HDD_TM_CMD_WLAN_FTM:
15080 {
15081 int buf_len;
15082 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015083 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015084 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015085 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015086 return -EINVAL;
15087 }
15088
15089 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15090 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15091
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015092 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015093
15094 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
15095
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015096 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015097 err = -EBUSY;
15098 break;
15099 }
15100#endif
15101
15102 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015103 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
15105 return -EOPNOTSUPP;
15106 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015107 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015108 return err;
15109}
15110
15111/**
15112 * wlan_hdd_cfg80211_testmode() - test mode
15113 * @wiphy: Pointer to wiphy
15114 * @dev: Pointer to network device
15115 * @data: Data pointer
15116 * @len: Data length
15117 *
15118 * Return: 0 for success, non-zero for failure
15119 */
15120static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15121#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
15122 struct wireless_dev *wdev,
15123#endif
15124 void *data, int len)
15125{
15126 int ret;
15127
15128 cds_ssr_protect(__func__);
15129 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
15130 cds_ssr_unprotect(__func__);
15131
15132 return ret;
15133}
15134
15135#if defined(QCA_WIFI_FTM)
15136/**
15137 * wlan_hdd_testmode_rx_event() - test mode rx event handler
15138 * @buf: Pointer to buffer
15139 * @buf_len: Buffer length
15140 *
15141 * Return: none
15142 */
15143void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
15144{
15145 struct sk_buff *skb;
15146 hdd_context_t *hdd_ctx;
15147
15148 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015149 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015150 return;
15151 }
15152
Anurag Chouhan6d760662016-02-20 16:05:43 +053015153 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015154 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015155 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015156 return;
15157 }
15158
15159 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
15160 buf_len, GFP_KERNEL);
15161 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015162 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163 return;
15164 }
15165
15166 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
15167 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
15168 goto nla_put_failure;
15169
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015170 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015171
15172 cfg80211_testmode_event(skb, GFP_KERNEL);
15173 return;
15174
15175nla_put_failure:
15176 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015177 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178}
15179#endif
15180#endif /* CONFIG_NL80211_TESTMODE */
15181
15182#ifdef QCA_HT_2040_COEX
15183/**
15184 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15185 * @wiphy: Pointer to wiphy
15186 * @dev: Pointer to network device
15187 * @chandef: Pointer to channel definition parameter
15188 *
15189 * Return: 0 for success, non-zero for failure
15190 */
15191static int
15192__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15193 struct net_device *dev,
15194 struct cfg80211_chan_def *chandef)
15195{
15196 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15197 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015198 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053015200 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015201
Anurag Chouhan6d760662016-02-20 16:05:43 +053015202 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015203 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015204 return -EINVAL;
15205 }
15206
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015207 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15208 hdd_err("invalid session id: %d", pAdapter->sessionId);
15209 return -EINVAL;
15210 }
15211
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015212 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15213 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053015214 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015215 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015216
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015217 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015218 sme_get_config_param(pHddCtx->hHal, &sme_config);
15219 switch (chandef->width) {
15220 case NL80211_CHAN_WIDTH_20:
15221 if (sme_config.csrConfig.channelBondingMode24GHz !=
15222 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15223 sme_config.csrConfig.channelBondingMode24GHz =
15224 eCSR_INI_SINGLE_CHANNEL_CENTERED;
15225 sme_update_config(pHddCtx->hHal, &sme_config);
15226 cbModeChange = true;
15227 }
15228 break;
15229
15230 case NL80211_CHAN_WIDTH_40:
15231 if (sme_config.csrConfig.channelBondingMode24GHz ==
15232 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15233 if (NL80211_CHAN_HT40MINUS ==
15234 cfg80211_get_chandef_type(chandef))
15235 sme_config.csrConfig.channelBondingMode24GHz =
15236 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
15237 else
15238 sme_config.csrConfig.channelBondingMode24GHz =
15239 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
15240 sme_update_config(pHddCtx->hHal, &sme_config);
15241 cbModeChange = true;
15242 }
15243 break;
15244
15245 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015246 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247 return -EINVAL;
15248 }
15249
15250 if (!cbModeChange)
15251 return 0;
15252
Krunal Sonib4326f22016-03-10 13:05:51 -080015253 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254 return 0;
15255
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015256 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015257 sme_config.csrConfig.channelBondingMode24GHz);
15258
15259 /* Change SAP ht2040 mode */
15260 status = hdd_set_sap_ht2040_mode(pAdapter,
15261 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015262 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015263 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 return -EINVAL;
15265 }
15266
15267 return 0;
15268}
15269
15270/**
15271 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15272 * @wiphy: Pointer to wiphy
15273 * @dev: Pointer to network device
15274 * @chandef: Pointer to channel definition parameter
15275 *
15276 * Return: 0 for success, non-zero for failure
15277 */
15278static int
15279wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15280 struct net_device *dev,
15281 struct cfg80211_chan_def *chandef)
15282{
15283 int ret;
15284
15285 cds_ssr_protect(__func__);
15286 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
15287 cds_ssr_unprotect(__func__);
15288
15289 return ret;
15290}
15291#endif
15292
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015293#ifdef CHANNEL_SWITCH_SUPPORTED
15294/**
15295 * __wlan_hdd_cfg80211_channel_switch()- function to switch
15296 * channel in SAP/GO
15297 * @wiphy: wiphy pointer
15298 * @dev: dev pointer.
15299 * @csa_params: Change channel params
15300 *
15301 * This function is called to switch channel in SAP/GO
15302 *
15303 * Return: 0 if success else return non zero
15304 */
15305static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15306 struct net_device *dev,
15307 struct cfg80211_csa_settings *csa_params)
15308{
15309 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15310 hdd_context_t *hdd_ctx;
15311 uint8_t channel;
15312 uint16_t freq;
15313 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080015314 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015315
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015316 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015317 csa_params->chandef.chan->center_freq);
15318
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015319 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
15320 hdd_err("invalid session id: %d", adapter->sessionId);
15321 return -EINVAL;
15322 }
15323
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015324 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15325 ret = wlan_hdd_validate_context(hdd_ctx);
15326
15327 if (0 != ret)
15328 return ret;
15329
Krunal Sonib4326f22016-03-10 13:05:51 -080015330 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
15331 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015332 return -ENOTSUPP;
15333
15334 freq = csa_params->chandef.chan->center_freq;
15335 channel = cds_freq_to_chan(freq);
15336
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053015337 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
15338
15339 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015340 return ret;
15341}
15342
15343/**
15344 * wlan_hdd_cfg80211_channel_switch()- function to switch
15345 * channel in SAP/GO
15346 * @wiphy: wiphy pointer
15347 * @dev: dev pointer.
15348 * @csa_params: Change channel params
15349 *
15350 * This function is called to switch channel in SAP/GO
15351 *
15352 * Return: 0 if success else return non zero
15353 */
15354static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15355 struct net_device *dev,
15356 struct cfg80211_csa_settings *csa_params)
15357{
15358 int ret;
15359
15360 cds_ssr_protect(__func__);
15361 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15362 cds_ssr_unprotect(__func__);
15363 return ret;
15364}
15365#endif
15366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015367/**
15368 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15369 * translation from NL to policy manager type
15370 * @type: Generic connection mode type defined in NL
15371 *
15372 *
15373 * This function provides the type translation
15374 *
15375 * Return: cds_con_mode enum
15376 */
15377enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15378 enum nl80211_iftype type)
15379{
15380 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15381 switch (type) {
15382 case NL80211_IFTYPE_STATION:
15383 mode = CDS_STA_MODE;
15384 break;
15385 case NL80211_IFTYPE_P2P_CLIENT:
15386 mode = CDS_P2P_CLIENT_MODE;
15387 break;
15388 case NL80211_IFTYPE_P2P_GO:
15389 mode = CDS_P2P_GO_MODE;
15390 break;
15391 case NL80211_IFTYPE_AP:
15392 mode = CDS_SAP_MODE;
15393 break;
15394 case NL80211_IFTYPE_ADHOC:
15395 mode = CDS_IBSS_MODE;
15396 break;
15397 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015398 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015399 type);
15400 }
15401 return mode;
15402}
15403
15404/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015405 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15406 * @wiphy: Handle to struct wiphy to get handle to module context.
15407 * @chandef: Contains information about the capture channel to be set.
15408 *
15409 * This interface is called if and only if monitor mode interface alone is
15410 * active.
15411 *
15412 * Return: 0 success or error code on failure.
15413 */
15414static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15415 struct cfg80211_chan_def *chandef)
15416{
15417 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15418 hdd_adapter_t *adapter;
15419 hdd_station_ctx_t *sta_ctx;
15420 struct hdd_mon_set_ch_info *ch_info;
15421 QDF_STATUS status;
15422 tHalHandle hal_hdl;
15423 struct qdf_mac_addr bssid;
15424 tCsrRoamProfile roam_profile;
15425 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015426 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015427 int ret;
15428 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15429
15430 ENTER();
15431
15432 ret = wlan_hdd_validate_context(hdd_ctx);
15433 if (ret)
15434 return ret;
15435
15436 hal_hdl = hdd_ctx->hHal;
15437
15438 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15439 if (!adapter)
15440 return -EIO;
15441
15442 hdd_info("%s: set monitor mode Channel %d and freq %d",
15443 adapter->dev->name, chan_num, chandef->chan->center_freq);
15444
15445 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15446 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015447 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15448 roam_profile.ChannelInfo.numOfChannels = 1;
15449 roam_profile.phyMode = ch_info->phy_mode;
15450 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015451 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015452
15453 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15454 QDF_MAC_ADDR_SIZE);
15455
15456 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015457 /*
15458 * CDS api expects secondary channel for calculating
15459 * the channel params
15460 */
15461 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15462 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15463 if (chan_num >= 1 && chan_num <= 5)
15464 sec_ch = chan_num + 4;
15465 else if (chan_num >= 6 && chan_num <= 13)
15466 sec_ch = chan_num - 4;
15467 }
15468 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015469 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15470 &roam_profile);
15471 if (status) {
15472 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15473 status);
15474 ret = qdf_status_to_os_return(status);
15475 return ret;
15476 }
15477 EXIT();
15478 return 0;
15479}
15480
15481/**
15482 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15483 * @wiphy: Handle to struct wiphy to get handle to module context.
15484 * @chandef: Contains information about the capture channel to be set.
15485 *
15486 * This interface is called if and only if monitor mode interface alone is
15487 * active.
15488 *
15489 * Return: 0 success or error code on failure.
15490 */
15491static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15492 struct cfg80211_chan_def *chandef)
15493{
15494 int ret;
15495
15496 cds_ssr_protect(__func__);
15497 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15498 cds_ssr_unprotect(__func__);
15499 return ret;
15500}
15501
15502/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015503 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15504 * @adapter: pointer to adapter
15505 *
15506 * Wrapper function to clear link layer stats.
15507 * return - void
15508 */
15509void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15510{
15511 tSirLLStatsClearReq link_layer_stats_clear_req;
15512 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15513
Mukul Sharma491021c2016-09-29 21:39:19 +053015514 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15515 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015516 link_layer_stats_clear_req.stopReq = 0;
15517 link_layer_stats_clear_req.reqId = 1;
15518 link_layer_stats_clear_req.staId = adapter->sessionId;
15519 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15520
15521 return;
15522}
15523
15524/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015525 * struct cfg80211_ops - cfg80211_ops
15526 *
15527 * @add_virtual_intf: Add virtual interface
15528 * @del_virtual_intf: Delete virtual interface
15529 * @change_virtual_intf: Change virtual interface
15530 * @change_station: Change station
15531 * @add_beacon: Add beacon in sap mode
15532 * @del_beacon: Delete beacon in sap mode
15533 * @set_beacon: Set beacon in sap mode
15534 * @start_ap: Start ap
15535 * @change_beacon: Change beacon
15536 * @stop_ap: Stop ap
15537 * @change_bss: Change bss
15538 * @add_key: Add key
15539 * @get_key: Get key
15540 * @del_key: Delete key
15541 * @set_default_key: Set default key
15542 * @set_channel: Set channel
15543 * @scan: Scan
15544 * @connect: Connect
15545 * @disconnect: Disconnect
15546 * @join_ibss = Join ibss
15547 * @leave_ibss = Leave ibss
15548 * @set_wiphy_params = Set wiphy params
15549 * @set_tx_power = Set tx power
15550 * @get_tx_power = get tx power
15551 * @remain_on_channel = Remain on channel
15552 * @cancel_remain_on_channel = Cancel remain on channel
15553 * @mgmt_tx = Tx management frame
15554 * @mgmt_tx_cancel_wait = Cancel management tx wait
15555 * @set_default_mgmt_key = Set default management key
15556 * @set_txq_params = Set tx queue parameters
15557 * @get_station = Get station
15558 * @set_power_mgmt = Set power management
15559 * @del_station = Delete station
15560 * @add_station = Add station
15561 * @set_pmksa = Set pmksa
15562 * @del_pmksa = Delete pmksa
15563 * @flush_pmksa = Flush pmksa
15564 * @update_ft_ies = Update FT IEs
15565 * @tdls_mgmt = Tdls management
15566 * @tdls_oper = Tdls operation
15567 * @set_rekey_data = Set rekey data
15568 * @sched_scan_start = Scheduled scan start
15569 * @sched_scan_stop = Scheduled scan stop
15570 * @resume = Resume wlan
15571 * @suspend = Suspend wlan
15572 * @set_mac_acl = Set mac acl
15573 * @testmode_cmd = Test mode command
15574 * @set_ap_chanwidth = Set AP channel bandwidth
15575 * @dump_survey = Dump survey
15576 * @key_mgmt_set_pmk = Set pmk key management
15577 */
15578static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15579 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15580 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15581 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15582 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015583 .start_ap = wlan_hdd_cfg80211_start_ap,
15584 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15585 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586 .change_bss = wlan_hdd_cfg80211_change_bss,
15587 .add_key = wlan_hdd_cfg80211_add_key,
15588 .get_key = wlan_hdd_cfg80211_get_key,
15589 .del_key = wlan_hdd_cfg80211_del_key,
15590 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15591 .scan = wlan_hdd_cfg80211_scan,
15592 .connect = wlan_hdd_cfg80211_connect,
15593 .disconnect = wlan_hdd_cfg80211_disconnect,
15594 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15595 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15596 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15597 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15598 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15599 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15600 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15601 .mgmt_tx = wlan_hdd_mgmt_tx,
15602 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15603 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15604 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015605 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606 .get_station = wlan_hdd_cfg80211_get_station,
15607 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15608 .del_station = wlan_hdd_cfg80211_del_station,
15609 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015610 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15611 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15612 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015613#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15615#endif
15616#ifdef FEATURE_WLAN_TDLS
15617 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15618 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15619#endif
15620#ifdef WLAN_FEATURE_GTK_OFFLOAD
15621 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15622#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15623#ifdef FEATURE_WLAN_SCAN_PNO
15624 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15625 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15626#endif /*FEATURE_WLAN_SCAN_PNO */
15627 .resume = wlan_hdd_cfg80211_resume_wlan,
15628 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15629 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15630#ifdef WLAN_NL80211_TESTMODE
15631 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15632#endif
15633#ifdef QCA_HT_2040_COEX
15634 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15635#endif
15636 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015637#ifdef CHANNEL_SWITCH_SUPPORTED
15638 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15639#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015640 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015641#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15642 defined(CFG80211_ABORT_SCAN)
15643 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15644#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015645};