blob: 417818a9b6d05118c224bf004129e54bb96cc4ec [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Paul Zhang3a210c52016-12-08 10:18:12 +080077#ifdef WLAN_UMAC_CONVERGENCE
78#include "wlan_cfg80211.h"
79#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080080#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080081#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082
83#ifdef FEATURE_WLAN_EXTSCAN
84#include "wlan_hdd_ext_scan.h"
85#endif
86
87#ifdef WLAN_FEATURE_LINK_LAYER_STATS
88#include "wlan_hdd_stats.h"
89#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080090#include "cds_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091#include "cds_concurrency.h"
92#include "qwlan_version.h"
93#include "wlan_hdd_memdump.h"
94
95#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070096#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097
Ravi Joshideb5a8d2015-11-09 19:11:43 -080098#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053099#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700100#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700101#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530102#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800103#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800104#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800105
Leo Changfdb45c32016-10-28 11:09:23 -0700106#include <cdp_txrx_cmn.h>
107#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800108#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530109#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800110#include "os_if_wifi_pos.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112#define g_mode_rates_size (12)
113#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
115 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
116
117/*
118 * Android CTS verifier needs atleast this much wait time (in msec)
119 */
120#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
121
122/*
123 * Refer @tCfgProtection structure for definition of the bit map.
124 * below value is obtained by setting the following bit-fields.
125 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
126 */
127#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
128
129#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700130 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700139 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140 .center_freq = (freq), \
141 .hw_value = (chan), \
142 .flags = (flag), \
143 .max_antenna_gain = 0, \
144 .max_power = 30, \
145}
146
147#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
148 { \
149 .bitrate = rate, \
150 .hw_value = rate_id, \
151 .flags = flag, \
152 }
153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
155#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
Agrawal Ashish65634612016-08-18 13:24:32 +0530159#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
160 mode <= DFS_MODE_DEPRIORITIZE))
161#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
162 || (channel >= 36 && channel <= 184))
163
Peng Xu4d67c8f2015-10-16 16:02:26 -0700164#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530165#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167static const u32 hdd_cipher_suites[] = {
168 WLAN_CIPHER_SUITE_WEP40,
169 WLAN_CIPHER_SUITE_WEP104,
170 WLAN_CIPHER_SUITE_TKIP,
171#ifdef FEATURE_WLAN_ESE
172#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
173#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
174 WLAN_CIPHER_SUITE_BTK,
175 WLAN_CIPHER_SUITE_KRK,
176 WLAN_CIPHER_SUITE_CCMP,
177#else
178 WLAN_CIPHER_SUITE_CCMP,
179#endif
180#ifdef FEATURE_WLAN_WAPI
181 WLAN_CIPHER_SUITE_SMS4,
182#endif
183#ifdef WLAN_FEATURE_11W
184 WLAN_CIPHER_SUITE_AES_CMAC,
185#endif
186};
187
Abhishek Singhf512bf32016-05-04 16:47:46 +0530188static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 HDD2GHZCHAN(2412, 1, 0),
190 HDD2GHZCHAN(2417, 2, 0),
191 HDD2GHZCHAN(2422, 3, 0),
192 HDD2GHZCHAN(2427, 4, 0),
193 HDD2GHZCHAN(2432, 5, 0),
194 HDD2GHZCHAN(2437, 6, 0),
195 HDD2GHZCHAN(2442, 7, 0),
196 HDD2GHZCHAN(2447, 8, 0),
197 HDD2GHZCHAN(2452, 9, 0),
198 HDD2GHZCHAN(2457, 10, 0),
199 HDD2GHZCHAN(2462, 11, 0),
200 HDD2GHZCHAN(2467, 12, 0),
201 HDD2GHZCHAN(2472, 13, 0),
202 HDD2GHZCHAN(2484, 14, 0),
203};
204
Abhishek Singhf512bf32016-05-04 16:47:46 +0530205static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206 HDD5GHZCHAN(5180, 36, 0),
207 HDD5GHZCHAN(5200, 40, 0),
208 HDD5GHZCHAN(5220, 44, 0),
209 HDD5GHZCHAN(5240, 48, 0),
210 HDD5GHZCHAN(5260, 52, 0),
211 HDD5GHZCHAN(5280, 56, 0),
212 HDD5GHZCHAN(5300, 60, 0),
213 HDD5GHZCHAN(5320, 64, 0),
214 HDD5GHZCHAN(5500, 100, 0),
215 HDD5GHZCHAN(5520, 104, 0),
216 HDD5GHZCHAN(5540, 108, 0),
217 HDD5GHZCHAN(5560, 112, 0),
218 HDD5GHZCHAN(5580, 116, 0),
219 HDD5GHZCHAN(5600, 120, 0),
220 HDD5GHZCHAN(5620, 124, 0),
221 HDD5GHZCHAN(5640, 128, 0),
222 HDD5GHZCHAN(5660, 132, 0),
223 HDD5GHZCHAN(5680, 136, 0),
224 HDD5GHZCHAN(5700, 140, 0),
225 HDD5GHZCHAN(5720, 144, 0),
226 HDD5GHZCHAN(5745, 149, 0),
227 HDD5GHZCHAN(5765, 153, 0),
228 HDD5GHZCHAN(5785, 157, 0),
229 HDD5GHZCHAN(5805, 161, 0),
230 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 HDD5GHZCHAN(5852, 170, 0),
232 HDD5GHZCHAN(5855, 171, 0),
233 HDD5GHZCHAN(5860, 172, 0),
234 HDD5GHZCHAN(5865, 173, 0),
235 HDD5GHZCHAN(5870, 174, 0),
236 HDD5GHZCHAN(5875, 175, 0),
237 HDD5GHZCHAN(5880, 176, 0),
238 HDD5GHZCHAN(5885, 177, 0),
239 HDD5GHZCHAN(5890, 178, 0),
240 HDD5GHZCHAN(5895, 179, 0),
241 HDD5GHZCHAN(5900, 180, 0),
242 HDD5GHZCHAN(5905, 181, 0),
243 HDD5GHZCHAN(5910, 182, 0),
244 HDD5GHZCHAN(5915, 183, 0),
245 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246};
247
248static struct ieee80211_rate g_mode_rates[] = {
249 HDD_G_MODE_RATETAB(10, 0x1, 0),
250 HDD_G_MODE_RATETAB(20, 0x2, 0),
251 HDD_G_MODE_RATETAB(55, 0x4, 0),
252 HDD_G_MODE_RATETAB(110, 0x8, 0),
253 HDD_G_MODE_RATETAB(60, 0x10, 0),
254 HDD_G_MODE_RATETAB(90, 0x20, 0),
255 HDD_G_MODE_RATETAB(120, 0x40, 0),
256 HDD_G_MODE_RATETAB(180, 0x80, 0),
257 HDD_G_MODE_RATETAB(240, 0x100, 0),
258 HDD_G_MODE_RATETAB(360, 0x200, 0),
259 HDD_G_MODE_RATETAB(480, 0x400, 0),
260 HDD_G_MODE_RATETAB(540, 0x800, 0),
261};
262
263static struct ieee80211_rate a_mode_rates[] = {
264 HDD_G_MODE_RATETAB(60, 0x10, 0),
265 HDD_G_MODE_RATETAB(90, 0x20, 0),
266 HDD_G_MODE_RATETAB(120, 0x40, 0),
267 HDD_G_MODE_RATETAB(180, 0x80, 0),
268 HDD_G_MODE_RATETAB(240, 0x100, 0),
269 HDD_G_MODE_RATETAB(360, 0x200, 0),
270 HDD_G_MODE_RATETAB(480, 0x400, 0),
271 HDD_G_MODE_RATETAB(540, 0x800, 0),
272};
273
274static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530275 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700277 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 .bitrates = g_mode_rates,
279 .n_bitrates = g_mode_rates_size,
280 .ht_cap.ht_supported = 1,
281 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
282 | IEEE80211_HT_CAP_GRN_FLD
283 | IEEE80211_HT_CAP_DSSSCCK40
284 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
285 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
286 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
287 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
288 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
289 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
290 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
291};
292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530294 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700296 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 .bitrates = a_mode_rates,
298 .n_bitrates = a_mode_rates_size,
299 .ht_cap.ht_supported = 1,
300 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
301 | IEEE80211_HT_CAP_GRN_FLD
302 | IEEE80211_HT_CAP_DSSSCCK40
303 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
304 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
305 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
306 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
307 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
308 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
309 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
310 .vht_cap.vht_supported = 1,
311};
312
313/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800314 * TX/RX direction for each kind of interface
315 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316static const struct ieee80211_txrx_stypes
317 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
318 [NL80211_IFTYPE_STATION] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ACTION) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ),
322 },
323 [NL80211_IFTYPE_AP] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_ADHOC] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
336 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_PROBE_REQ) |
338 BIT(SIR_MAC_MGMT_DISASSOC) |
339 BIT(SIR_MAC_MGMT_AUTH) |
340 BIT(SIR_MAC_MGMT_DEAUTH) |
341 BIT(SIR_MAC_MGMT_ACTION),
342 },
343 [NL80211_IFTYPE_P2P_CLIENT] = {
344 .tx = 0xffff,
345 .rx = BIT(SIR_MAC_MGMT_ACTION) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ),
347 },
348 [NL80211_IFTYPE_P2P_GO] = {
349 /* This is also same as for SoftAP */
350 .tx = 0xffff,
351 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
352 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_PROBE_REQ) |
354 BIT(SIR_MAC_MGMT_DISASSOC) |
355 BIT(SIR_MAC_MGMT_AUTH) |
356 BIT(SIR_MAC_MGMT_DEAUTH) |
357 BIT(SIR_MAC_MGMT_ACTION),
358 },
359};
360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361/* Interface limits and combinations registered by the driver */
362
363/* STA ( + STA ) combination */
364static const struct ieee80211_iface_limit
365 wlan_hdd_sta_iface_limit[] = {
366 {
367 .max = 3, /* p2p0 is a STA as well */
368 .types = BIT(NL80211_IFTYPE_STATION),
369 },
370};
371
372/* ADHOC (IBSS) limit */
373static const struct ieee80211_iface_limit
374 wlan_hdd_adhoc_iface_limit[] = {
375 {
376 .max = 1,
377 .types = BIT(NL80211_IFTYPE_STATION),
378 },
379 {
380 .max = 1,
381 .types = BIT(NL80211_IFTYPE_ADHOC),
382 },
383};
384
385/* AP ( + AP ) combination */
386static const struct ieee80211_iface_limit
387 wlan_hdd_ap_iface_limit[] = {
388 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530389 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 .types = BIT(NL80211_IFTYPE_AP),
391 },
392};
393
394/* P2P limit */
395static const struct ieee80211_iface_limit
396 wlan_hdd_p2p_iface_limit[] = {
397 {
398 .max = 1,
399 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
400 },
401 {
402 .max = 1,
403 .types = BIT(NL80211_IFTYPE_P2P_GO),
404 },
405};
406
407static const struct ieee80211_iface_limit
408 wlan_hdd_sta_ap_iface_limit[] = {
409 {
410 /* We need 1 extra STA interface for OBSS scan when SAP starts
411 * with HT40 in STA+SAP concurrency mode
412 */
413 .max = (1 + SAP_MAX_OBSS_STA_CNT),
414 .types = BIT(NL80211_IFTYPE_STATION),
415 },
416 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530417 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 .types = BIT(NL80211_IFTYPE_AP),
419 },
420};
421
422/* STA + P2P combination */
423static const struct ieee80211_iface_limit
424 wlan_hdd_sta_p2p_iface_limit[] = {
425 {
426 /* One reserved for dedicated P2PDEV usage */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_STATION)
429 },
430 {
431 /* Support for two identical (GO + GO or CLI + CLI)
432 * or dissimilar (GO + CLI) P2P interfaces
433 */
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
436 },
437};
438
439/* STA + AP + P2PGO combination */
440static const struct ieee80211_iface_limit
441wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
442 /* Support for AP+P2PGO interfaces */
443 {
444 .max = 2,
445 .types = BIT(NL80211_IFTYPE_STATION)
446 },
447 {
448 .max = 1,
449 .types = BIT(NL80211_IFTYPE_P2P_GO)
450 },
451 {
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_AP)
454 }
455};
456
457/* SAP + P2P combination */
458static const struct ieee80211_iface_limit
459wlan_hdd_sap_p2p_iface_limit[] = {
460 {
461 /* 1 dedicated for p2p0 which is a STA type */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_STATION)
464 },
465 {
466 /* The p2p interface in SAP+P2P can be GO/CLI.
467 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
468 */
469 .max = 1,
470 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
471 },
472 {
473 /* SAP+GO to support only one SAP interface */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_AP)
476 }
477};
478
479/* P2P + P2P combination */
480static const struct ieee80211_iface_limit
481wlan_hdd_p2p_p2p_iface_limit[] = {
482 {
483 /* 1 dedicated for p2p0 which is a STA type */
484 .max = 1,
485 .types = BIT(NL80211_IFTYPE_STATION)
486 },
487 {
488 /* The p2p interface in P2P+P2P can be GO/CLI.
489 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
490 */
491 .max = 2,
492 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
493 },
494};
495
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700496static const struct ieee80211_iface_limit
497 wlan_hdd_mon_iface_limit[] = {
498 {
499 .max = 3, /* Monitor interface */
500 .types = BIT(NL80211_IFTYPE_MONITOR),
501 },
502};
503
504static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 wlan_hdd_iface_combination[] = {
506 /* STA */
507 {
508 .limits = wlan_hdd_sta_iface_limit,
509 .num_different_channels = 2,
510 .max_interfaces = 3,
511 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
512 },
513 /* ADHOC */
514 {
515 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700516 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 .max_interfaces = 2,
518 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
519 },
520 /* AP */
521 {
522 .limits = wlan_hdd_ap_iface_limit,
523 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530524 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
526 },
527 /* P2P */
528 {
529 .limits = wlan_hdd_p2p_iface_limit,
530 .num_different_channels = 2,
531 .max_interfaces = 2,
532 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
533 },
534 /* STA + AP */
535 {
536 .limits = wlan_hdd_sta_ap_iface_limit,
537 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530538 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
540 .beacon_int_infra_match = true,
541 },
542 /* STA + P2P */
543 {
544 .limits = wlan_hdd_sta_p2p_iface_limit,
545 .num_different_channels = 2,
546 /* one interface reserved for P2PDEV dedicated usage */
547 .max_interfaces = 4,
548 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
549 .beacon_int_infra_match = true,
550 },
551 /* STA + P2P GO + SAP */
552 {
553 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
554 /* we can allow 3 channels for three different persona
555 * but due to firmware limitation, allow max 2 concrnt channels.
556 */
557 .num_different_channels = 2,
558 /* one interface reserved for P2PDEV dedicated usage */
559 .max_interfaces = 4,
560 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
561 .beacon_int_infra_match = true,
562 },
563 /* SAP + P2P */
564 {
565 .limits = wlan_hdd_sap_p2p_iface_limit,
566 .num_different_channels = 2,
567 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
568 .max_interfaces = 3,
569 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
570 .beacon_int_infra_match = true,
571 },
572 /* P2P + P2P */
573 {
574 .limits = wlan_hdd_p2p_p2p_iface_limit,
575 .num_different_channels = 2,
576 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
577 .max_interfaces = 3,
578 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
579 .beacon_int_infra_match = true,
580 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530581 /* Monitor */
582 {
583 .limits = wlan_hdd_mon_iface_limit,
584 .max_interfaces = 3,
585 .num_different_channels = 2,
586 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
587 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589
590static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591
592#ifdef WLAN_NL80211_TESTMODE
593enum wlan_hdd_tm_attr {
594 WLAN_HDD_TM_ATTR_INVALID = 0,
595 WLAN_HDD_TM_ATTR_CMD = 1,
596 WLAN_HDD_TM_ATTR_DATA = 2,
597 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
598 WLAN_HDD_TM_ATTR_TYPE = 4,
599 /* keep last */
600 WLAN_HDD_TM_ATTR_AFTER_LAST,
601 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
602};
603
604enum wlan_hdd_tm_cmd {
605 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
606 WLAN_HDD_TM_CMD_WLAN_HB = 1,
607};
608
609#define WLAN_HDD_TM_DATA_MAX_LEN 5000
610
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530611enum wlan_hdd_vendor_ie_access_policy {
612 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
613 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
614};
615
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
617 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
618 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
619 .len = WLAN_HDD_TM_DATA_MAX_LEN},
620};
621#endif /* WLAN_NL80211_TESTMODE */
622
623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
624static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
625 .flags = WIPHY_WOWLAN_MAGIC_PKT,
626 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
627 .pattern_min_len = 1,
628 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
629};
630#endif
631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530633 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
634 * @flags: Pointer to the flags to Add channel switch flag.
635 *
636 * This Function adds Channel Switch support flag, if channel switch is
637 * supported by kernel.
638 * Return: void.
639 */
640#ifdef CHANNEL_SWITCH_SUPPORTED
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800643 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530644 return;
645}
646#else
647static inline void hdd_add_channel_switch_support(uint32_t *flags)
648{
649 return;
650}
651#endif
652
Manikandan Mohan22b83722015-12-15 15:03:23 -0800653#ifdef FEATURE_WLAN_TDLS
654
655/* TDLS capabilities params */
656#define PARAM_MAX_TDLS_SESSION \
657 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
658#define PARAM_TDLS_FEATURE_SUPPORT \
659 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
660
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530661/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
663 * @wiphy: WIPHY structure pointer
664 * @wdev: Wireless device structure pointer
665 * @data: Pointer to the data received
666 * @data_len: Length of the data received
667 *
668 * This function provides TDLS capabilities
669 *
670 * Return: 0 on success and errno on failure
671 */
672static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
673 struct wireless_dev *wdev,
674 const void *data,
675 int data_len)
676{
677 int status;
678 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
679 struct sk_buff *skb;
680 uint32_t set = 0;
681
Jeff Johnson1f61b612016-02-12 16:28:33 -0800682 ENTER_DEV(wdev->netdev);
683
Anurag Chouhan6d760662016-02-20 16:05:43 +0530684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 hdd_err("Command not allowed in FTM mode");
686 return -EPERM;
687 }
688
689 status = wlan_hdd_validate_context(hdd_ctx);
690 if (status)
691 return status;
692
693 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
694 NLMSG_HDRLEN);
695 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700696 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 goto fail;
698 }
699
700 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700701 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
703 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 goto fail;
706 }
707 } else {
708 set = set | WIFI_TDLS_SUPPORT;
709 set = set | (hdd_ctx->config->fTDLSExternalControl ?
710 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
711 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
712 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700713 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
715 hdd_ctx->max_num_tdls_sta) ||
716 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
717 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700718 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 goto fail;
720 }
721 }
722 return cfg80211_vendor_cmd_reply(skb);
723fail:
724 if (skb)
725 kfree_skb(skb);
726 return -EINVAL;
727}
728
729/**
730 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
731 * @wiphy: WIPHY structure pointer
732 * @wdev: Wireless device structure pointer
733 * @data: Pointer to the data received
734 * @data_len: Length of the data received
735 *
736 * This function provides TDLS capabilities
737 *
738 * Return: 0 on success and errno on failure
739 */
740static int
741wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
742 struct wireless_dev *wdev,
743 const void *data,
744 int data_len)
745{
746 int ret;
747
748 cds_ssr_protect(__func__);
749 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
750 data, data_len);
751 cds_ssr_unprotect(__func__);
752
753 return ret;
754}
755#endif
756
757#ifdef QCA_HT_2040_COEX
758static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
759#endif
760
761#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
762/*
763 * FUNCTION: wlan_hdd_send_avoid_freq_event
764 * This is called when wlan driver needs to send vendor specific
765 * avoid frequency range event to userspace
766 */
767int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
768 tHddAvoidFreqList *pAvoidFreqList)
769{
770 struct sk_buff *vendor_event;
771
772 ENTER();
773
774 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700775 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 return -EINVAL;
777 }
778
779 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700780 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 return -EINVAL;
782 }
783
784 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
785 NULL,
786 sizeof(tHddAvoidFreqList),
787 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
788 GFP_KERNEL);
789 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700790 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 return -EINVAL;
792 }
793
794 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
795 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
796
797 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
798
799 EXIT();
800 return 0;
801}
802#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
803
804/* vendor specific events */
805static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
806#ifdef FEATURE_WLAN_CH_AVOID
807 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
812 },
813#endif /* FEATURE_WLAN_CH_AVOID */
814
815#ifdef WLAN_FEATURE_NAN
816 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_NAN
821 },
822#endif
823
824#ifdef WLAN_FEATURE_STATS_EXT
825 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
826 .vendor_id =
827 QCA_NL80211_VENDOR_ID,
828 .subcmd =
829 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
830 },
831#endif /* WLAN_FEATURE_STATS_EXT */
832#ifdef FEATURE_WLAN_EXTSCAN
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
840 .vendor_id =
841 QCA_NL80211_VENDOR_ID,
842 .subcmd =
843 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
844 },
845 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
846 .
847 vendor_id
848 =
849 QCA_NL80211_VENDOR_ID,
850 .subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd =
860 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
861 },
862 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
863 .
864 vendor_id
865 =
866 QCA_NL80211_VENDOR_ID,
867 .
868 subcmd
869 =
870 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
871 },
872 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
873 .
874 vendor_id
875 =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
881 .vendor_id =
882 QCA_NL80211_VENDOR_ID,
883 .subcmd =
884 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
885 },
886 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
887 .
888 vendor_id
889 =
890 QCA_NL80211_VENDOR_ID,
891 .subcmd =
892 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
893 },
894 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
895 .
896 vendor_id
897 =
898 QCA_NL80211_VENDOR_ID,
899 .subcmd =
900 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
901 },
902 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
903 .
904 vendor_id
905 =
906 QCA_NL80211_VENDOR_ID,
907 .
908 subcmd
909 =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd =
919 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
920 },
921 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
922 .
923 vendor_id
924 =
925 QCA_NL80211_VENDOR_ID,
926 .
927 subcmd
928 =
929 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
930 },
931 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
932 .
933 vendor_id
934 =
935 QCA_NL80211_VENDOR_ID,
936 .
937 subcmd
938 =
939 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
940 },
941 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
942 .vendor_id = QCA_NL80211_VENDOR_ID,
943 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
944 },
945 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
946 .vendor_id = QCA_NL80211_VENDOR_ID,
947 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
948 },
949#endif /* FEATURE_WLAN_EXTSCAN */
950
951#ifdef WLAN_FEATURE_LINK_LAYER_STATS
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
981 },
982 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
987 },
988#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
989 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
990 .vendor_id =
991 QCA_NL80211_VENDOR_ID,
992 .subcmd =
993 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
994 },
995 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
996 .vendor_id = QCA_NL80211_VENDOR_ID,
997 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
998 },
999#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1000 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1001 .vendor_id =
1002 QCA_NL80211_VENDOR_ID,
1003 .subcmd =
1004 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1005 },
1006#endif
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1030 },
1031 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1032 .vendor_id =
1033 QCA_NL80211_VENDOR_ID,
1034 .subcmd =
1035 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1036 },
1037#ifdef FEATURE_WLAN_EXTSCAN
1038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1041 },
1042 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1043 .vendor_id = QCA_NL80211_VENDOR_ID,
1044 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1045 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1049 },
1050 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1053 },
1054 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1057 },
1058#endif /* FEATURE_WLAN_EXTSCAN */
1059 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1062 },
1063#ifdef WLAN_FEATURE_MEMDUMP
1064 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1067 },
1068#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001069#ifdef WLAN_FEATURE_TSF
1070 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1073 },
1074#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1078 },
1079 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1080 .vendor_id = QCA_NL80211_VENDOR_ID,
1081 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1082 },
1083 /* OCB events */
1084 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1085 .vendor_id = QCA_NL80211_VENDOR_ID,
1086 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1087 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001088#ifdef FEATURE_LFR_SUBNET_DETECTION
1089 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1090 .vendor_id = QCA_NL80211_VENDOR_ID,
1091 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1092 },
1093#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001094
1095#ifdef WLAN_FEATURE_NAN_DATAPATH
1096 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1099 },
1100#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001101
1102 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1103 .vendor_id = QCA_NL80211_VENDOR_ID,
1104 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1105 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301106 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1107 .vendor_id = QCA_NL80211_VENDOR_ID,
1108 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1109 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301110 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1111 .vendor_id = QCA_NL80211_VENDOR_ID,
1112 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1113 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001114#ifdef WLAN_UMAC_CONVERGENCE
1115 COMMON_VENDOR_EVENTS
1116#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117};
1118
1119/**
1120 * __is_driver_dfs_capable() - get driver DFS capability
1121 * @wiphy: pointer to wireless wiphy structure.
1122 * @wdev: pointer to wireless_dev structure.
1123 * @data: Pointer to the data to be passed via vendor interface
1124 * @data_len:Length of the data to be passed
1125 *
1126 * This function is called by userspace to indicate whether or not
1127 * the driver supports DFS offload.
1128 *
1129 * Return: 0 on success, negative errno on failure
1130 */
1131static int __is_driver_dfs_capable(struct wiphy *wiphy,
1132 struct wireless_dev *wdev,
1133 const void *data,
1134 int data_len)
1135{
1136 u32 dfs_capability = 0;
1137 struct sk_buff *temp_skbuff;
1138 int ret_val;
1139 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1140
Jeff Johnson1f61b612016-02-12 16:28:33 -08001141 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142
1143 ret_val = wlan_hdd_validate_context(hdd_ctx);
1144 if (ret_val)
1145 return ret_val;
1146
Anurag Chouhan6d760662016-02-20 16:05:43 +05301147 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 hdd_err("Command not allowed in FTM mode");
1149 return -EPERM;
1150 }
1151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153
1154 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1155 NLMSG_HDRLEN);
1156
1157 if (temp_skbuff != NULL) {
1158 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1159 dfs_capability);
1160 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001161 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001162 kfree_skb(temp_skbuff);
1163
1164 return ret_val;
1165 }
1166
1167 return cfg80211_vendor_cmd_reply(temp_skbuff);
1168 }
1169
Jeff Johnson020db452016-06-29 14:37:26 -07001170 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171 return -ENOMEM;
1172}
1173
1174/**
1175 * is_driver_dfs_capable() - get driver DFS capability
1176 * @wiphy: pointer to wireless wiphy structure.
1177 * @wdev: pointer to wireless_dev structure.
1178 * @data: Pointer to the data to be passed via vendor interface
1179 * @data_len:Length of the data to be passed
1180 *
1181 * This function is called by userspace to indicate whether or not
1182 * the driver supports DFS offload. This is an SSR-protected
1183 * wrapper function.
1184 *
1185 * Return: 0 on success, negative errno on failure
1186 */
1187static int is_driver_dfs_capable(struct wiphy *wiphy,
1188 struct wireless_dev *wdev,
1189 const void *data,
1190 int data_len)
1191{
1192 int ret;
1193
1194 cds_ssr_protect(__func__);
1195 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1196 cds_ssr_unprotect(__func__);
1197
1198 return ret;
1199}
1200
1201/**
1202 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1203 *
1204 * @adapter: SAP adapter pointer
1205 *
1206 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1207 * radio. So in case of DFS MCC scenario override current SAP given config
1208 * to follow concurrent SAP DFS config
1209 *
1210 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1211 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1213{
1214 hdd_adapter_t *con_sap_adapter;
1215 tsap_Config_t *sap_config, *con_sap_config;
1216 int con_ch;
1217
1218 /*
1219 * Check if AP+AP case, once primary AP chooses a DFS
1220 * channel secondary AP should always follow primary APs channel
1221 */
1222 if (!cds_concurrent_beaconing_sessions_running())
1223 return 0;
1224
1225 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1226 if (!con_sap_adapter)
1227 return 0;
1228
1229 sap_config = &adapter->sessionCtx.ap.sapConfig;
1230 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1231 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1232
1233 if (!CDS_IS_DFS_CH(con_ch))
1234 return 0;
1235
Jeff Johnson020db452016-06-29 14:37:26 -07001236 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001238 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 sap_config->channel = con_ch;
1240
1241 if (con_sap_config->acs_cfg.acs_mode == true) {
1242 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1243 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001244 hdd_err("Primary AP channel config error");
1245 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 con_ch, con_sap_config->acs_cfg.pri_ch,
1247 con_sap_config->acs_cfg.ht_sec_ch);
1248 return -EINVAL;
1249 }
1250 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1251 * MCC restriction. So free ch list allocated in do_acs
1252 * func for Sec AP and realloc for Pri AP ch list size
1253 */
1254 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301255 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 &con_sap_config->acs_cfg,
1259 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301260 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 sizeof(uint8_t) *
1262 con_sap_config->acs_cfg.ch_list_count);
1263 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001264 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 return -ENOMEM;
1266 }
1267
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301268 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269 con_sap_config->acs_cfg.ch_list,
1270 con_sap_config->acs_cfg.ch_list_count);
1271
1272 } else {
1273 sap_config->acs_cfg.pri_ch = con_ch;
1274 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1275 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1276 }
1277
1278 return con_ch;
1279}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001280
1281/**
1282 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1283 * @sap_cfg: pointer to SAP config struct
1284 *
1285 * This function sets the default ACS start and end channel for the given band
1286 * and also parses the given ACS channel list.
1287 *
1288 * Return: None
1289 */
1290
1291static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1292 bool vht_enabled)
1293{
1294 int i;
1295 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001297 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1298 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001301 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1302 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001305 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1306 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001309 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1310 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001311 }
1312
1313 if (ht_enabled)
1314 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1315
1316 if (vht_enabled)
1317 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1318
1319
1320 /* Parse ACS Chan list from hostapd */
1321 if (!sap_cfg->acs_cfg.ch_list)
1322 return;
1323
1324 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1325 sap_cfg->acs_cfg.end_ch =
1326 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1327 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301328 /* avoid channel as start channel */
1329 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1330 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001331 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1332 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1333 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1334 }
1335}
1336
1337
1338static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1339
1340/**
1341 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1342 * @adapter: pointer to SAP adapter struct
1343 *
1344 * This function starts the ACS procedure if there are no
1345 * constraints like MBSSID DFS restrictions.
1346 *
1347 * Return: Status of ACS Start procedure
1348 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301349int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350{
1351
1352 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1353 tsap_Config_t *sap_config;
1354 tpWLAN_SAPEventCB acs_event_callback;
1355 int status;
1356
1357 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301358 if (hdd_ctx->acs_policy.acs_channel)
1359 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1360 else
1361 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362
1363 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001364 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001366
1367 if (status > 0) {
1368 /*notify hostapd about channel override */
1369 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1370 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1371 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 }
Jeff Johnson68755312017-02-10 11:46:55 -08001373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379
1380 acs_event_callback = hdd_hostapd_sap_event_cb;
1381
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301382 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301383 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301384 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 acs_event_callback, sap_config, adapter->dev);
1388
1389
1390 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001391 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 return -EINVAL;
1393 }
bings394afdd2017-01-09 11:22:38 +08001394 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1395 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1397
1398 return 0;
1399}
1400
1401/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301402 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1403 * @ap_adapter: AP adapter
1404 * @nol: Non-occupancy list
1405 * @nol_len: Length of NOL
1406 *
1407 * Get the NOL for SAP
1408 *
1409 * Return: Zero on success, non-zero on failure
1410 */
1411static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1412 uint32_t *nol_len)
1413{
1414 QDF_STATUS ret;
1415
1416 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1417 nol, nol_len);
1418 if (QDF_IS_STATUS_ERROR(ret))
1419 return -EINVAL;
1420
1421 return 0;
1422}
1423
1424/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301425 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1426 * @hdd_ctx: hdd context
1427 * @acs_chan_params: external acs channel params
1428 * @sap_config: SAP config
1429 *
1430 * This API provides unsorted pcl list.
1431 * this list is a subset of the valid channel list given by hostapd.
1432 * if channel is not present in pcl, weightage will be given as zero
1433 *
1434 * Return: Zero on success, non-zero on failure
1435 */
1436static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1437 struct hdd_vendor_acs_chan_params *acs_chan_params,
1438 tsap_Config_t *sap_config)
1439{
1440 int i, j;
1441
1442 for (i = 0; i < acs_chan_params->channel_count; i++) {
1443 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1444 if (acs_chan_params->channel_list[i] ==
1445 sap_config->acs_cfg.pcl_channels[j]) {
1446 acs_chan_params->vendor_pcl_list[i] =
1447 sap_config->acs_cfg.pcl_channels[j];
1448 acs_chan_params->vendor_weight_list[i] =
1449 sap_config->acs_cfg.
1450 pcl_channels_weight_list[j];
1451 break;
1452 } else {
1453 acs_chan_params->vendor_pcl_list[i] =
1454 acs_chan_params->channel_list[i];
1455 acs_chan_params->vendor_weight_list[i] = 0;
1456 }
1457 }
1458 }
1459 if (hdd_ctx->unsafe_channel_count == 0)
1460 return;
1461 /* Update unsafe channel weight as zero */
1462 for (i = 0; i < acs_chan_params->channel_count; i++) {
1463 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1464 if (acs_chan_params->channel_list[i] ==
1465 hdd_ctx->unsafe_channel_list[j]) {
1466 acs_chan_params->vendor_weight_list[i] = 0;
1467 }
1468 }
1469 }
1470}
1471
1472/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301473 * hdd_update_reg_chan_info : This API contructs channel info
1474 * for all the given channel
1475 * @adapter: pointer to SAP adapter struct
1476 * @channel_count: channel count
1477 * @channel_list: channel list
1478 *
1479 * Return: Status of of channel information updation
1480 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301481static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301482 uint32_t channel_count,
1483 uint8_t *channel_list)
1484{
1485 int i;
1486 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301487 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301488 uint8_t bw_offset = 0, chan = 0;
1489 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1490 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1491
1492 /* memory allocation */
1493 sap_config->channel_info = qdf_mem_malloc(
1494 sizeof(struct hdd_channel_info) *
1495 channel_count);
1496 if (!sap_config->channel_info) {
1497 hdd_err("memory allocation failed");
1498 return -ENOMEM;
1499
1500 }
1501 for (i = 0; i < channel_count; i++) {
1502 icv = &sap_config->channel_info[i];
1503 chan = channel_list[i];
1504
1505 if (chan == 0)
1506 continue;
1507
1508 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1509 bw_offset = 1 << BW_40_OFFSET_BIT;
1510 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1511 bw_offset = 1 << BW_20_OFFSET_BIT;
1512 icv->freq = cds_get_channel_freq(chan);
1513 icv->ieee_chan_number = chan;
1514 icv->max_reg_power = cds_get_channel_reg_power(chan);
1515
1516 /* filling demo values */
1517 icv->max_radio_power = HDD_MAX_TX_POWER;
1518 icv->min_radio_power = HDD_MIN_TX_POWER;
1519 /* not supported in current driver */
1520 icv->max_antenna_gain = 0;
1521
1522 icv->reg_class_id = wlan_hdd_find_opclass(
1523 WLAN_HDD_GET_HAL_CTX(adapter),
1524 chan, bw_offset);
1525
1526 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1527 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1528 cds_set_channel_params(chan, 0, &ch_params);
1529 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1530 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1531 }
1532 icv->flags = 0;
1533 icv->flags = cds_get_vendor_reg_flags(chan,
1534 sap_config->acs_cfg.ch_width,
1535 sap_config->acs_cfg.is_ht_enabled,
1536 sap_config->acs_cfg.is_vht_enabled,
1537 hdd_ctx->config->enable_sub_20_channel_width);
1538
1539 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1540 icv->freq, icv->flags,
1541 icv->flagext, icv->ieee_chan_number,
1542 icv->max_reg_power, icv->max_radio_power,
1543 icv->min_radio_power, icv->reg_class_id,
1544 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1545 icv->vht_center_freq_seg1);
1546 }
1547 return 0;
1548}
1549
1550/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1551#define CHAN_INFO_ATTR_FLAGS \
1552 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1553#define CHAN_INFO_ATTR_FLAG_EXT \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1555#define CHAN_INFO_ATTR_FREQ \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1557#define CHAN_INFO_ATTR_MAX_REG_POWER \
1558 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1559#define CHAN_INFO_ATTR_MAX_POWER \
1560 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1561#define CHAN_INFO_ATTR_MIN_POWER \
1562 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1563#define CHAN_INFO_ATTR_REG_CLASS_ID \
1564 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1565#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1566 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1567#define CHAN_INFO_ATTR_VHT_SEG_0 \
1568 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1569#define CHAN_INFO_ATTR_VHT_SEG_1 \
1570 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1571
1572/**
1573 * hdd_cfg80211_update_channel_info() - add channel info attributes
1574 * @skb: pointer to sk buff
1575 * @hdd_ctx: pointer to hdd station context
1576 * @idx: attribute index
1577 *
1578 * Return: Success(0) or reason code for failure
1579 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301580static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301581hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1582 tsap_Config_t *sap_config, int idx)
1583{
1584 struct nlattr *nla_attr, *channel;
1585 struct hdd_channel_info *icv;
1586 int i;
1587
1588 nla_attr = nla_nest_start(skb, idx);
1589 if (!nla_attr)
1590 goto fail;
1591
1592 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1593 channel = nla_nest_start(skb, i);
1594 if (!channel)
1595 goto fail;
1596
1597 icv = &sap_config->channel_info[i];
1598 if (!icv) {
1599 hdd_err("channel info not found");
1600 goto fail;
1601 }
1602 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1603 icv->freq) ||
1604 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1605 icv->flags) ||
1606 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1607 icv->flagext) ||
1608 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1609 icv->max_reg_power) ||
1610 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1611 icv->max_radio_power) ||
1612 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1613 icv->min_radio_power) ||
1614 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1615 icv->reg_class_id) ||
1616 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1617 icv->max_antenna_gain) ||
1618 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1619 icv->vht_center_freq_seg0) ||
1620 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1621 icv->vht_center_freq_seg1)) {
1622 hdd_err("put fail");
1623 goto fail;
1624 }
1625 nla_nest_end(skb, channel);
1626 }
1627 nla_nest_end(skb, nla_attr);
1628 return 0;
1629fail:
1630 hdd_err("nl channel update failed");
1631 return -EINVAL;
1632}
1633#undef CHAN_INFO_ATTR_FLAGS
1634#undef CHAN_INFO_ATTR_FLAG_EXT
1635#undef CHAN_INFO_ATTR_FREQ
1636#undef CHAN_INFO_ATTR_MAX_REG_POWER
1637#undef CHAN_INFO_ATTR_MAX_POWER
1638#undef CHAN_INFO_ATTR_MIN_POWER
1639#undef CHAN_INFO_ATTR_REG_CLASS_ID
1640#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1641#undef CHAN_INFO_ATTR_VHT_SEG_0
1642#undef CHAN_INFO_ATTR_VHT_SEG_1
1643
1644/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301645 * hdd_cfg80211_update_pcl() - add pcl info attributes
1646 * @skb: pointer to sk buff
1647 * @hdd_ctx: pointer to hdd station context
1648 * @idx: attribute index
1649 * @vendor_pcl_list: PCL list
1650 * @vendor_weight_list: PCL weights
1651 *
1652 * Return: Success(0) or reason code for failure
1653 */
1654static int32_t
1655hdd_cfg80211_update_pcl(struct sk_buff *skb,
1656 uint8_t ch_list_count, int idx,
1657 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1658{
1659 struct nlattr *nla_attr, *channel;
1660 int i;
1661
1662 nla_attr = nla_nest_start(skb, idx);
1663
1664 if (!nla_attr)
1665 goto fail;
1666
1667 for (i = 0; i < ch_list_count; i++) {
1668 channel = nla_nest_start(skb, i);
1669 if (!channel)
1670 goto fail;
1671 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1672 vendor_pcl_list[i]) ||
1673 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1674 vendor_weight_list[i])) {
1675 hdd_err("put fail");
1676 goto fail;
1677 }
1678 nla_nest_end(skb, channel);
1679 }
1680 nla_nest_end(skb, nla_attr);
1681
1682 return 0;
1683fail:
1684 hdd_err("updating pcl list failed");
1685 return -EINVAL;
1686}
1687
1688static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1689{
1690 /* Get scan band */
1691 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1692 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1693 *band = eCSR_BAND_24;
1694 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1695 *band = eCSR_BAND_5G;
1696 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1697 *band = eCSR_BAND_ALL;
1698 }
1699 /* Auto is not supported currently */
1700 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1701 hdd_err("invalid band");
1702 *band = eCSR_BAND_24;
1703 }
1704}
1705
1706void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1707 uint8_t reason)
1708{
1709 struct sk_buff *skb;
1710 tsap_Config_t *sap_config;
1711 uint32_t channel_count = 0, status;
1712 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1713 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1714 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1715 struct hdd_vendor_acs_chan_params acs_chan_params;
1716 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1717 eCsrBand band = eCSR_BAND_24;
1718 eCsrPhyMode phy_mode;
1719
1720 if (!hdd_ctx) {
1721 hdd_err("HDD context is NULL");
1722 return;
1723 }
1724
1725 ENTER();
1726 sap_config = &adapter->sessionCtx.ap.sapConfig;
1727
1728 /* Get valid channels for SAP */
1729 wlan_hdd_sap_get_valid_channellist(adapter,
1730 &channel_count, channel_list);
1731
1732 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1733 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1734 /* Get phymode */
1735 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1736
1737 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1738 &(adapter->wdev),
1739 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1740 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1741 GFP_KERNEL);
1742
1743 if (!skb) {
1744 hdd_err("cfg80211_vendor_event_alloc failed");
1745 return;
1746 }
1747 /*
1748 * Application expects pcl to be a subset of channel list
1749 * Remove all channels which are not in channel list from pcl
1750 * and add weight as zero
1751 */
1752 acs_chan_params.channel_count = channel_count;
1753 acs_chan_params.channel_list = channel_list;
1754 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1755 acs_chan_params.vendor_weight_list = vendor_weight_list;
1756
1757 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1758 sap_config);
1759 /* Update values in NL buffer */
1760 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1761 reason) ||
1762 nla_put_u8(skb,
1763 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1764 false) ||
1765 nla_put_u8(skb,
1766 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1767 true) ||
1768 nla_put_u8(skb,
1769 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1770 true) ||
1771 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1772 sap_config->acs_cfg.ch_width) ||
1773 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1774 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1775 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1776 band) ||
1777 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1778 phy_mode) ||
1779 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1780 channel_count, channel_list)) {
1781 hdd_err("nla put fail");
1782 goto fail;
1783 }
1784 status = hdd_cfg80211_update_pcl(skb, channel_count,
1785 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1786 vendor_pcl_list, vendor_weight_list);
1787
1788 if (status != 0)
1789 goto fail;
1790
1791 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1792 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1793
1794 if (status != 0)
1795 goto fail;
1796
1797 cfg80211_vendor_event(skb, GFP_KERNEL);
1798 return;
1799fail:
1800 if (skb)
1801 kfree_skb(skb);
1802}
1803
1804static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1805{
1806 struct hdd_external_acs_timer_context *timer_context;
1807
1808 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1809 return 0;
1810
1811 hdd_notice("Starting vendor app based ACS");
1812 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1813 timer_context->adapter = adapter;
1814
1815 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1816 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1817 QDF_TIMER_TYPE_SW,
1818 hdd_acs_response_timeout_handler, timer_context);
1819 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1820 return 0;
1821}
1822
1823/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1825 * @wiphy: Linux wiphy struct pointer
1826 * @wdev: Linux wireless device struct pointer
1827 * @data: ACS information from hostapd
1828 * @data_len: ACS information length
1829 *
1830 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1831 * and starts ACS procedure.
1832 *
1833 * Return: ACS procedure start status
1834 */
1835
1836static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1837 struct wireless_dev *wdev,
1838 const void *data, int data_len)
1839{
1840 struct net_device *ndev = wdev->netdev;
1841 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1842 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1843 tsap_Config_t *sap_config;
1844 struct sk_buff *temp_skbuff;
1845 int status = -EINVAL, i = 0;
1846 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1847 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301848 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001849
1850 /* ***Note*** Donot set SME config related to ACS operation here because
1851 * ACS operation is not synchronouse and ACS for Second AP may come when
1852 * ACS operation for first AP is going on. So only do_acs is split to
1853 * seperate start_acs routine. Also SME-PMAC struct that is used to
1854 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1855 * config shall be set only from start_acs.
1856 */
1857
1858 /* nla_policy Policy template. Policy not applied as some attributes are
1859 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1860 *
1861 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1862 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1864 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1865 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1866 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1867 */
1868
Jeff Johnson1f61b612016-02-12 16:28:33 -08001869 ENTER_DEV(ndev);
1870
Anurag Chouhan6d760662016-02-20 16:05:43 +05301871 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001872 hdd_err("Command not allowed in FTM mode");
1873 return -EPERM;
1874 }
1875
Kapil Gupta8878ad92017-02-13 11:56:04 +05301876 if (hdd_ctx->config->force_sap_acs &&
1877 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001878 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 return -EPERM;
1880 }
1881
1882 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301883 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301885
Naveen Rawat64e477e2016-05-20 10:34:56 -07001886 if (cds_is_sub_20_mhz_enabled()) {
1887 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1888 status = -EINVAL;
1889 goto out;
1890 }
1891
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301893 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894
1895 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1896 NULL);
1897 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001898 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 goto out;
1900 }
1901
1902 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001903 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001904 goto out;
1905 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301906 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1907 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908
1909 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1910 ht_enabled =
1911 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1912 else
1913 ht_enabled = 0;
1914
1915 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1916 ht40_enabled =
1917 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1918 else
1919 ht40_enabled = 0;
1920
1921 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1922 vht_enabled =
1923 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1924 else
1925 vht_enabled = 0;
1926
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301927 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1928 vht_enabled = 0;
1929 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1930 }
1931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1933 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1934 } else {
1935 if (ht_enabled && ht40_enabled)
1936 ch_width = 40;
1937 else
1938 ch_width = 20;
1939 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301940
1941 /* this may be possible, when sap_force_11n_for_11ac is set */
1942 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1943 if (ht_enabled && ht40_enabled)
1944 ch_width = 40;
1945 else
1946 ch_width = 20;
1947 }
1948
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949 if (ch_width == 80)
1950 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1951 else if (ch_width == 40)
1952 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1953 else
1954 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1955
1956 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1957 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1958 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1959 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1960 * since it contains the frequency values of the channels in
1961 * the channel list.
1962 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1963 * is present
1964 */
1965 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1966 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1967 sap_config->acs_cfg.ch_list_count = nla_len(
1968 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1969 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301970 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 sizeof(uint8_t) *
1972 sap_config->acs_cfg.ch_list_count);
1973 if (sap_config->acs_cfg.ch_list == NULL)
1974 goto out;
1975
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301976 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977 sap_config->acs_cfg.ch_list_count);
1978 }
1979 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1980 uint32_t *freq =
1981 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1982 sap_config->acs_cfg.ch_list_count = nla_len(
1983 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1984 sizeof(uint32_t);
1985 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301986 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 sap_config->acs_cfg.ch_list_count);
1988 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001989 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001990 status = -ENOMEM;
1991 goto out;
1992 }
1993
1994 /* convert frequency to channel */
1995 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1996 sap_config->acs_cfg.ch_list[i] =
1997 ieee80211_frequency_to_channel(freq[i]);
1998 }
1999 }
2000
2001 hdd_debug("get pcl for DO_ACS vendor command");
2002
2003 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002004 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302005 sap_config->acs_cfg.pcl_channels,
2006 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302007 sap_config->acs_cfg.pcl_channels_weight_list,
2008 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302009 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002010 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302013 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2014 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07002015 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 vht_enabled = 1;
2017 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2018 sap_config->acs_cfg.ch_width =
2019 hdd_ctx->config->vhtChannelWidth;
2020 /* No VHT80 in 2.4G so perform ACS accordingly */
2021 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302022 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302024 ch_width = 40;
2025 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026 }
2027
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302028 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2029
Jeff Johnson020db452016-06-29 14:37:26 -07002030 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 -08002031 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2032 ch_width, ht_enabled, vht_enabled,
2033 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2034
Kapil Gupta8878ad92017-02-13 11:56:04 +05302035 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2036 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07002039 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 sap_config->acs_cfg.ch_list_count);
2041 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07002042 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002043 }
2044 sap_config->acs_cfg.acs_mode = true;
2045 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002046 /* ***Note*** Completion variable usage is not allowed
2047 * here since ACS scan operation may take max 2.2 sec
2048 * for 5G band:
2049 * 9 Active channel X 40 ms active scan time +
2050 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2052 * for this long. So we split up the scanning part.
2053 */
2054 set_bit(ACS_PENDING, &adapter->event_flags);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302055 hdd_notice("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002056 status = 0;
2057 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302058 /* Check if vendor specific acs is enabled */
2059 if (hdd_ctx->config->vendor_acs_support) {
2060 sap_config->acs_cfg.hw_mode = hw_mode;
2061 hdd_create_acs_timer(adapter);
2062 hdd_update_acs_timer_reason(adapter,
2063 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2064 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2065 wlan_sap_set_vendor_acs(
2066 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2067 true);
2068 else
2069 wlan_sap_set_vendor_acs(
2070 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2071 false);
2072
2073 } else
2074 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 }
2076
2077out:
2078 if (0 == status) {
2079 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2080 NLMSG_HDRLEN);
2081 if (temp_skbuff != NULL)
2082 return cfg80211_vendor_cmd_reply(temp_skbuff);
2083 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002084 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2086
2087 return status;
2088}
2089
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002090/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002091 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2092 * @wiphy: Linux wiphy struct pointer
2093 * @wdev: Linux wireless device struct pointer
2094 * @data: ACS information from hostapd
2095 * @data_len: ACS information len
2096 *
2097 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2098 * and starts ACS procedure.
2099 *
2100 * Return: ACS procedure start status
2101 */
2102
2103static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2104 struct wireless_dev *wdev,
2105 const void *data, int data_len)
2106{
2107 int ret;
2108
2109 cds_ssr_protect(__func__);
2110 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2111 cds_ssr_unprotect(__func__);
2112
2113 return ret;
2114}
2115
2116/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002117 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2118 * @adapter: Pointer to adapter struct
2119 *
2120 * This function handle cleanup of what was done in DO_ACS, including free
2121 * memory.
2122 *
2123 * Return: void
2124 */
2125
2126void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2127{
2128 if (adapter == NULL)
2129 return;
2130 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2131 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2132 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2133 }
2134}
2135
2136/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002137 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2138 * @work: Linux workqueue struct pointer for ACS work
2139 *
2140 * This function starts the ACS procedure which was marked pending when an ACS
2141 * procedure was in progress for a concurrent SAP interface.
2142 *
2143 * Return: None
2144 */
2145
2146static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2147{
2148 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2149 acs_pending_work.work);
2150 wlan_hdd_cfg80211_start_acs(adapter);
2151}
2152
2153/**
2154 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2155 * @adapter: Pointer to SAP adapter struct
2156 * @pri_channel: SAP ACS procedure selected Primary channel
2157 * @sec_channel: SAP ACS procedure selected secondary channel
2158 *
2159 * This is a callback function from SAP module on ACS procedure is completed.
2160 * This function send the ACS selected channel information to hostapd
2161 *
2162 * Return: None
2163 */
2164
2165void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2166{
2167 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2168 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2169 struct sk_buff *vendor_event;
2170 int ret_val;
2171 hdd_adapter_t *con_sap_adapter;
2172 uint16_t ch_width;
2173
2174 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002175 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2177 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2178 GFP_KERNEL);
2179
2180 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002181 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182 return;
2183 }
2184
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 ret_val = nla_put_u8(vendor_event,
2186 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2187 sap_cfg->acs_cfg.pri_ch);
2188 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002189 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190 kfree_skb(vendor_event);
2191 return;
2192 }
2193
2194 ret_val = nla_put_u8(vendor_event,
2195 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2196 sap_cfg->acs_cfg.ht_sec_ch);
2197 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002198 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002199 kfree_skb(vendor_event);
2200 return;
2201 }
2202
2203 ret_val = nla_put_u8(vendor_event,
2204 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2205 sap_cfg->acs_cfg.vht_seg0_center_ch);
2206 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002207 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 kfree_skb(vendor_event);
2209 return;
2210 }
2211
2212 ret_val = nla_put_u8(vendor_event,
2213 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2214 sap_cfg->acs_cfg.vht_seg1_center_ch);
2215 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002216 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217 kfree_skb(vendor_event);
2218 return;
2219 }
2220
2221 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2222 ch_width = 80;
2223 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2224 ch_width = 40;
2225 else
2226 ch_width = 20;
2227
2228 ret_val = nla_put_u16(vendor_event,
2229 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2230 ch_width);
2231 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002232 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 kfree_skb(vendor_event);
2234 return;
2235 }
2236 if (sap_cfg->acs_cfg.pri_ch > 14)
2237 ret_val = nla_put_u8(vendor_event,
2238 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2239 QCA_ACS_MODE_IEEE80211A);
2240 else
2241 ret_val = nla_put_u8(vendor_event,
2242 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2243 QCA_ACS_MODE_IEEE80211G);
2244
2245 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002246 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 kfree_skb(vendor_event);
2248 return;
2249 }
2250
Jeff Johnson46b40792016-06-29 14:03:14 -07002251 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 -08002252 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2253 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2254 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2255
2256 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2257 /* ***Note*** As already mentioned Completion variable usage is not
2258 * allowed here since ACS scan operation may take max 2.2 sec.
2259 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2260 * operation.
2261 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2262 * when Primary AP ACS is complete and secondary AP ACS is started here
2263 * immediately, Primary AP start_bss may come inbetween ACS operation
2264 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2265 * delay. This path and below constraint will be removed on sessionizing
2266 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2267 * As per design constraint user space control application must take
2268 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2269 * this code path. Sec AP hostapd should be started after Primary AP
2270 * start beaconing which can be confirmed by getchannel iwpriv command
2271 */
2272
2273 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2274 if (con_sap_adapter &&
2275 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2277 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 /* Lets give 500ms for OBSS + START_BSS to complete */
2279 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2280 msecs_to_jiffies(500));
2281 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2282 }
2283
2284 return;
2285}
2286
2287static int
2288__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2289 struct wireless_dev *wdev,
2290 const void *data,
2291 int data_len)
2292{
2293 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2294 struct sk_buff *skb = NULL;
2295 uint32_t fset = 0;
2296 int ret;
2297
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002298 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302299
Anurag Chouhan6d760662016-02-20 16:05:43 +05302300 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 hdd_err("Command not allowed in FTM mode");
2302 return -EPERM;
2303 }
2304
2305 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302306 if (ret)
2307 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308
2309 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002310 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 fset |= WIFI_FEATURE_INFRA;
2312 }
2313 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002314 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 fset |= WIFI_FEATURE_INFRA_5G;
2316 }
2317#ifdef WLAN_FEATURE_P2P
2318 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2319 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002320 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 fset |= WIFI_FEATURE_P2P;
2322 }
2323#endif
2324 fset |= WIFI_FEATURE_SOFT_AP;
2325
2326 /* HOTSPOT is a supplicant feature, enable it by default */
2327 fset |= WIFI_FEATURE_HOTSPOT;
2328
2329#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302330 if (pHddCtx->config->extscan_enabled &&
2331 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002332 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2334 }
2335#endif
2336 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002337 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 fset |= WIFI_FEATURE_NAN;
2339 }
2340 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002341 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002342 fset |= WIFI_FEATURE_D2D_RTT;
2343 fset |= WIFI_FEATURE_D2AP_RTT;
2344 }
2345#ifdef FEATURE_WLAN_SCAN_PNO
2346 if (pHddCtx->config->configPNOScanSupport &&
2347 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002348 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 fset |= WIFI_FEATURE_PNO;
2350 }
2351#endif
2352 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2353#ifdef FEATURE_WLAN_TDLS
2354 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2355 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002356 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 fset |= WIFI_FEATURE_TDLS;
2358 }
2359 if (sme_is_feature_supported_by_fw(TDLS) &&
2360 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2361 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002362 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002363 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2364 }
2365#endif
2366#ifdef WLAN_AP_STA_CONCURRENCY
2367 fset |= WIFI_FEATURE_AP_STA;
2368#endif
2369 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002370 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371
2372 if (hdd_link_layer_stats_supported())
2373 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2374
2375 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2376 NLMSG_HDRLEN);
2377 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002378 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 return -EINVAL;
2380 }
Jeff Johnson020db452016-06-29 14:37:26 -07002381 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002383 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 goto nla_put_failure;
2385 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302386 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302387 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388nla_put_failure:
2389 kfree_skb(skb);
2390 return -EINVAL;
2391}
2392
2393/**
2394 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2395 * @wiphy: pointer to wireless wiphy structure.
2396 * @wdev: pointer to wireless_dev structure.
2397 * @data: Pointer to the data to be passed via vendor interface
2398 * @data_len:Length of the data to be passed
2399 *
2400 * Return: Return the Success or Failure code.
2401 */
2402static int
2403wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2404 struct wireless_dev *wdev,
2405 const void *data, int data_len)
2406{
2407 int ret = 0;
2408
2409 cds_ssr_protect(__func__);
2410 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2411 data, data_len);
2412 cds_ssr_unprotect(__func__);
2413
2414 return ret;
2415}
2416
2417/**
2418 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2419 * @wiphy: pointer to wireless wiphy structure.
2420 * @wdev: pointer to wireless_dev structure.
2421 * @data: Pointer to the data to be passed via vendor interface
2422 * @data_len:Length of the data to be passed
2423 *
2424 * Set the MAC address that is to be used for scanning.
2425 *
2426 * Return: Return the Success or Failure code.
2427 */
2428static int
2429__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2430 struct wireless_dev *wdev,
2431 const void *data,
2432 int data_len)
2433{
2434 tpSirScanMacOui pReqMsg = NULL;
2435 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2436 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302437 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 int ret;
2439
Jeff Johnson1f61b612016-02-12 16:28:33 -08002440 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441
Anurag Chouhan6d760662016-02-20 16:05:43 +05302442 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 hdd_err("Command not allowed in FTM mode");
2444 return -EPERM;
2445 }
2446
2447 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302448 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450
2451 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002452 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 return -ENOTSUPP;
2454 }
2455
2456 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2457 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002458 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 return -EINVAL;
2460 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302461 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 return -ENOMEM;
2465 }
2466 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002467 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 goto fail;
2469 }
2470 nla_memcpy(&pReqMsg->oui[0],
2471 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2472 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002473 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 pReqMsg->oui[1], pReqMsg->oui[2]);
2475 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302476 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002477 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 goto fail;
2479 }
2480 return 0;
2481fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302482 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483 return -EINVAL;
2484}
2485
2486/**
2487 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2488 * @wiphy: pointer to wireless wiphy structure.
2489 * @wdev: pointer to wireless_dev structure.
2490 * @data: Pointer to the data to be passed via vendor interface
2491 * @data_len:Length of the data to be passed
2492 *
2493 * Set the MAC address that is to be used for scanning. This is an
2494 * SSR-protecting wrapper function.
2495 *
2496 * Return: Return the Success or Failure code.
2497 */
2498static int
2499wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2500 struct wireless_dev *wdev,
2501 const void *data,
2502 int data_len)
2503{
2504 int ret;
2505
2506 cds_ssr_protect(__func__);
2507 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2508 data, data_len);
2509 cds_ssr_unprotect(__func__);
2510
2511 return ret;
2512}
2513
2514/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302515 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2516 * @wiphy: pointer phy adapter
2517 * @wdev: pointer to wireless device structure
2518 * @data: pointer to data buffer
2519 * @data_len: length of data
2520 *
2521 * This routine will give concurrency matrix
2522 *
2523 * Return: int status code
2524 */
2525static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2526 struct wireless_dev *wdev,
2527 const void *data,
2528 int data_len)
2529{
2530 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2531 uint8_t i, feature_sets, max_feature_sets;
2532 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2533 struct sk_buff *reply_skb;
2534 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2535 int ret;
2536
2537 ENTER_DEV(wdev->netdev);
2538
2539 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2540 hdd_err("Command not allowed in FTM mode");
2541 return -EPERM;
2542 }
2543
2544 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302545 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302546 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302547
2548 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2549 data, data_len, NULL)) {
2550 hdd_err("Invalid ATTR");
2551 return -EINVAL;
2552 }
2553
2554 /* Parse and fetch max feature set */
2555 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2556 hdd_err("Attr max feature set size failed");
2557 return -EINVAL;
2558 }
2559 max_feature_sets = nla_get_u32(tb[
2560 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2561 hdd_info("Max feature set size: %d", max_feature_sets);
2562
2563 /* Fill feature combination matrix */
2564 feature_sets = 0;
2565 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002566 WIFI_FEATURE_P2P;
2567 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2568 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302569 /* Add more feature combinations here */
2570
2571 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002572 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302573 hdd_info("Feature set matrix");
2574 for (i = 0; i < feature_sets; i++)
2575 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2576
2577 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2578 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2579 if (!reply_skb) {
2580 hdd_err("Feature set matrix: buffer alloc fail");
2581 return -ENOMEM;
2582 }
2583
2584 if (nla_put_u32(reply_skb,
2585 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2586 feature_sets) ||
2587 nla_put(reply_skb,
2588 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2589 sizeof(u32) * feature_sets,
2590 feature_set_matrix)) {
2591 hdd_err("nla put fail");
2592 kfree_skb(reply_skb);
2593 return -EINVAL;
2594 }
2595 return cfg80211_vendor_cmd_reply(reply_skb);
2596}
2597
2598/**
2599 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2600 * @wiphy: pointer to wireless wiphy structure.
2601 * @wdev: pointer to wireless_dev structure.
2602 * @data: Pointer to the data to be passed via vendor interface
2603 * @data_len:Length of the data to be passed
2604 *
2605 * Retrieves the concurrency feature set matrix
2606 *
2607 * Return: 0 on success, negative errno on failure
2608 */
2609static int
2610wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2611 struct wireless_dev *wdev,
2612 const void *data,
2613 int data_len)
2614{
2615 int ret;
2616
2617 cds_ssr_protect(__func__);
2618 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2619 data, data_len);
2620 cds_ssr_unprotect(__func__);
2621
2622 return ret;
2623}
2624
2625/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2627 * @feature_flags: pointer to the byte array of features.
2628 * @feature: Feature to be turned ON in the byte array.
2629 *
2630 * Return: None
2631 *
2632 * This is called to turn ON or SET the feature flag for the requested feature.
2633 **/
2634#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002635static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2636 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002637{
2638 uint32_t index;
2639 uint8_t bit_mask;
2640
2641 index = feature / NUM_BITS_IN_BYTE;
2642 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2643 feature_flags[index] |= bit_mask;
2644}
2645
2646/**
2647 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2648 * @wiphy: pointer to wireless wiphy structure.
2649 * @wdev: pointer to wireless_dev structure.
2650 * @data: Pointer to the data to be passed via vendor interface
2651 * @data_len:Length of the data to be passed
2652 *
2653 * This is called when wlan driver needs to send supported feature set to
2654 * supplicant upon a request/query from the supplicant.
2655 *
2656 * Return: Return the Success or Failure code.
2657 **/
2658#define MAX_CONCURRENT_CHAN_ON_24G 2
2659#define MAX_CONCURRENT_CHAN_ON_5G 2
2660static int
2661__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2662 struct wireless_dev *wdev,
2663 const void *data, int data_len)
2664{
2665 struct sk_buff *skb = NULL;
2666 uint32_t dbs_capability = 0;
2667 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302668 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 int ret_val;
2670
2671 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2672 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2673
Jeff Johnson1f61b612016-02-12 16:28:33 -08002674 ENTER_DEV(wdev->netdev);
2675
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2677 if (ret_val)
2678 return ret_val;
2679
Anurag Chouhan6d760662016-02-20 16:05:43 +05302680 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 hdd_err("Command not allowed in FTM mode");
2682 return -EPERM;
2683 }
2684
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002685 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002686 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687 wlan_hdd_cfg80211_set_feature(feature_flags,
2688 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2689 }
2690
2691 wlan_hdd_cfg80211_set_feature(feature_flags,
2692 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2693 if (wma_is_scan_simultaneous_capable())
2694 wlan_hdd_cfg80211_set_feature(feature_flags,
2695 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002696
2697 if (wma_is_p2p_lo_capable())
2698 wlan_hdd_cfg80211_set_feature(feature_flags,
2699 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2700
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002701 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2702 NLMSG_HDRLEN);
2703
2704 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002705 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 return -ENOMEM;
2707 }
2708
2709 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2710 sizeof(feature_flags), feature_flags))
2711 goto nla_put_failure;
2712
2713 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302714 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 if (one_by_one_dbs)
2716 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2717
2718 if (two_by_two_dbs)
2719 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2720
2721 if (!one_by_one_dbs && !two_by_two_dbs)
2722 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2723 } else {
2724 hdd_err("wma_get_dbs_hw_mode failed");
2725 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2726 }
2727
2728 hdd_info("dbs_capability is %d", dbs_capability);
2729
2730 if (nla_put_u32(skb,
2731 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2732 MAX_CONCURRENT_CHAN_ON_24G))
2733 goto nla_put_failure;
2734
2735 if (nla_put_u32(skb,
2736 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2737 MAX_CONCURRENT_CHAN_ON_5G))
2738 goto nla_put_failure;
2739
2740 return cfg80211_vendor_cmd_reply(skb);
2741
2742nla_put_failure:
2743 kfree_skb(skb);
2744 return -EINVAL;
2745}
2746
2747/**
2748 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2749 * @wiphy: pointer to wireless wiphy structure.
2750 * @wdev: pointer to wireless_dev structure.
2751 * @data: Pointer to the data to be passed via vendor interface
2752 * @data_len:Length of the data to be passed
2753 *
2754 * This is called when wlan driver needs to send supported feature set to
2755 * supplicant upon a request/query from the supplicant.
2756 *
2757 * Return: Return the Success or Failure code.
2758 */
2759static int
2760wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2761 struct wireless_dev *wdev,
2762 const void *data, int data_len)
2763{
2764 int ret;
2765
2766 cds_ssr_protect(__func__);
2767 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2768 data, data_len);
2769 cds_ssr_unprotect(__func__);
2770
2771 return ret;
2772}
2773
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302774#define PARAM_NUM_NW \
2775 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2776#define PARAM_SET_BSSID \
2777 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2778#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2779#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780
2781/**
2782 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2783 * @wiphy: The wiphy structure
2784 * @wdev: The wireless device
2785 * @data: Data passed by framework
2786 * @data_len: Parameters to be configured passed as data
2787 *
2788 * The roaming related parameters are configured by the framework
2789 * using this interface.
2790 *
2791 * Return: Return either success or failure code.
2792 */
2793static int
2794__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2795 struct wireless_dev *wdev, const void *data, int data_len)
2796{
2797 struct net_device *dev = wdev->netdev;
2798 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2799 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2800 uint8_t session_id;
2801 struct roam_ext_params roam_params;
2802 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302803 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002804 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2805 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2806 int rem, i;
2807 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002808 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 int ret;
2810
Jeff Johnson1f61b612016-02-12 16:28:33 -08002811 ENTER_DEV(dev);
2812
Anurag Chouhan6d760662016-02-20 16:05:43 +05302813 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 hdd_err("Command not allowed in FTM mode");
2815 return -EPERM;
2816 }
2817
2818 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302819 if (ret)
2820 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821
2822 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2823 data, data_len,
2824 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002825 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 return -EINVAL;
2827 }
2828 /* Parse and fetch Command Type*/
2829 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002830 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831 goto fail;
2832 }
2833 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302834 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2836 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002837 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002838 goto fail;
2839 }
2840 req_id = nla_get_u32(
2841 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002842 hdd_debug("Req Id (%d)", req_id);
2843 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002844 switch (cmd_type) {
2845 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2846 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302847 if (tb[PARAM_NUM_NW]) {
2848 count = nla_get_u32(
2849 tb[PARAM_NUM_NW]);
2850 } else {
2851 hdd_err("Number of networks is not provided");
2852 goto fail;
2853 }
2854
2855 if (count &&
2856 tb[PRAM_SSID_LIST]) {
2857 nla_for_each_nested(curr_attr,
2858 tb[PRAM_SSID_LIST], rem) {
2859 if (nla_parse(tb2,
2860 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2861 nla_data(curr_attr), nla_len(curr_attr),
2862 NULL)) {
2863 hdd_err("nla_parse failed");
2864 goto fail;
2865 }
2866 /* Parse and Fetch allowed SSID list*/
2867 if (!tb2[PARAM_LIST_SSID]) {
2868 hdd_err("attr allowed ssid failed");
2869 goto fail;
2870 }
2871 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2872 /*
2873 * Upper Layers include a null termination
2874 * character. Check for the actual permissible
2875 * length of SSID and also ensure not to copy
2876 * the NULL termination character to the driver
2877 * buffer.
2878 */
2879 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2880 ((buf_len - 1) <=
2881 SIR_MAC_MAX_SSID_LENGTH)) {
2882 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302884 tb2[PARAM_LIST_SSID], buf_len - 1);
2885 roam_params.ssid_allowed_list[i].length
2886 = buf_len - 1;
2887 hdd_debug("SSID[%d]: %.*s,length = %d",
2888 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 roam_params.ssid_allowed_list[i].length,
2890 roam_params.ssid_allowed_list[i].ssId,
2891 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302892 i++;
2893 } else {
2894 hdd_err("Invalid buffer length");
2895 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896 }
2897 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302898 if (i != count) {
2899 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2900 i, count);
2901 goto fail;
2902 }
2903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002905 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 roam_params.num_ssid_allowed_list);
2907 sme_update_roam_params(pHddCtx->hHal, session_id,
2908 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2909 break;
2910 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2911 /* Parse and fetch 5G Boost Threshold */
2912 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002913 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002914 goto fail;
2915 }
2916 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2917 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002918 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 roam_params.raise_rssi_thresh_5g);
2920 /* Parse and fetch 5G Penalty Threshold */
2921 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002922 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002923 goto fail;
2924 }
2925 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2926 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002927 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 roam_params.drop_rssi_thresh_5g);
2929 /* Parse and fetch 5G Boost Factor */
2930 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002931 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 goto fail;
2933 }
2934 roam_params.raise_factor_5g = nla_get_u32(
2935 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002936 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 roam_params.raise_factor_5g);
2938 /* Parse and fetch 5G Penalty factor */
2939 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002940 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 goto fail;
2942 }
2943 roam_params.drop_factor_5g = nla_get_u32(
2944 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002945 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 roam_params.drop_factor_5g);
2947 /* Parse and fetch 5G Max Boost */
2948 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002949 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 goto fail;
2951 }
2952 roam_params.max_raise_rssi_5g = nla_get_u32(
2953 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002954 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955 roam_params.max_raise_rssi_5g);
2956 /* Parse and fetch Rssi Diff */
2957 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002958 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002959 goto fail;
2960 }
2961 roam_params.rssi_diff = nla_get_s32(
2962 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002963 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002964 roam_params.rssi_diff);
2965 /* Parse and fetch Alert Rssi Threshold */
2966 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002967 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 goto fail;
2969 }
2970 roam_params.alert_rssi_threshold = nla_get_u32(
2971 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002972 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 roam_params.alert_rssi_threshold);
2974 sme_update_roam_params(pHddCtx->hHal, session_id,
2975 roam_params,
2976 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2977 break;
2978 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2979 /* Parse and fetch Activate Good Rssi Roam */
2980 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002981 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 goto fail;
2983 }
2984 roam_params.good_rssi_roam = nla_get_s32(
2985 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002986 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 roam_params.good_rssi_roam);
2988 sme_update_roam_params(pHddCtx->hHal, session_id,
2989 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2990 break;
2991 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2992 /* Parse and fetch number of preferred BSSID */
2993 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002994 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 goto fail;
2996 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002997 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002999 if (count > MAX_BSSID_FAVORED) {
3000 hdd_err("Preferred BSSID count %u exceeds max %u",
3001 count, MAX_BSSID_FAVORED);
3002 goto fail;
3003 }
3004 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 i = 0;
3006 nla_for_each_nested(curr_attr,
3007 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3008 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003009
3010 if (i == count) {
3011 hdd_warn("Ignoring excess Preferred BSSID");
3012 break;
3013 }
3014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 if (nla_parse(tb2,
3016 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3017 nla_data(curr_attr), nla_len(curr_attr),
3018 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003019 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020 goto fail;
3021 }
3022 /* Parse and fetch MAC address */
3023 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003024 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025 goto fail;
3026 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003027 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303029 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003030 hdd_debug(MAC_ADDRESS_STR,
3031 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003032 /* Parse and fetch preference factor*/
3033 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003034 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035 goto fail;
3036 }
3037 roam_params.bssid_favored_factor[i] = nla_get_u32(
3038 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003039 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 roam_params.bssid_favored_factor[i]);
3041 i++;
3042 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003043 if (i < count)
3044 hdd_warn("Num Preferred BSSID %u less than expected %u",
3045 i, count);
3046 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 sme_update_roam_params(pHddCtx->hHal, session_id,
3048 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3049 break;
3050 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3051 /* Parse and fetch number of blacklist BSSID */
3052 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003053 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 goto fail;
3055 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003056 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003058 if (count > MAX_BSSID_AVOID_LIST) {
3059 hdd_err("Blacklist BSSID count %u exceeds max %u",
3060 count, MAX_BSSID_AVOID_LIST);
3061 goto fail;
3062 }
3063 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003064 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303065
3066 if (count &&
3067 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3068 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003069 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3070 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003071
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303072 if (i == count) {
3073 hdd_warn("Ignoring excess Blacklist BSSID");
3074 break;
3075 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003076
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303077 if (nla_parse(tb2,
3078 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3079 nla_data(curr_attr), nla_len(curr_attr),
3080 NULL)) {
3081 hdd_err("nla_parse failed");
3082 goto fail;
3083 }
3084 /* Parse and fetch MAC address */
3085 if (!tb2[PARAM_SET_BSSID]) {
3086 hdd_err("attr blacklist addr failed");
3087 goto fail;
3088 }
3089 nla_memcpy(
3090 roam_params.bssid_avoid_list[i].bytes,
3091 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3092 hdd_debug(MAC_ADDRESS_STR,
3093 MAC_ADDR_ARRAY(
3094 roam_params.bssid_avoid_list[i].bytes));
3095 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003097 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003098 if (i < count)
3099 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3100 i, count);
3101 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102 sme_update_roam_params(pHddCtx->hHal, session_id,
3103 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3104 break;
3105 }
3106 return 0;
3107fail:
3108 return -EINVAL;
3109}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303110#undef PARAM_NUM_NW
3111#undef PARAM_SET_BSSID
3112#undef PRAM_SSID_LIST
3113#undef PARAM_LIST_SSID
3114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115
3116/**
3117 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3118 * @wiphy: pointer to wireless wiphy structure.
3119 * @wdev: pointer to wireless_dev structure.
3120 * @data: Pointer to the data to be passed via vendor interface
3121 * @data_len:Length of the data to be passed
3122 *
3123 * Return: Return the Success or Failure code.
3124 */
3125static int
3126wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3127 struct wireless_dev *wdev,
3128 const void *data,
3129 int data_len)
3130{
3131 int ret;
3132
3133 cds_ssr_protect(__func__);
3134 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3135 data, data_len);
3136 cds_ssr_unprotect(__func__);
3137
3138 return ret;
3139}
3140
3141static const struct nla_policy
3142wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3143 +1] = {
3144 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3145};
3146
3147/**
3148 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3149 * @hdd_ctx: HDD context
3150 * @device_mode: device mode
3151 * Return: bool
3152 */
3153static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003154 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155{
3156 hdd_adapter_t *adapter;
3157 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3158 hdd_ap_ctx_t *ap_ctx;
3159 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303160 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003161
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303162 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 &adapter_node);
3164
3165 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303166 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 adapter = adapter_node->pAdapter;
3168
3169 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003170 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 ap_ctx =
3172 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3173
3174 /*
3175 * if there is SAP already running on DFS channel,
3176 * do not disable scan on dfs channels. Note that
3177 * with SAP on DFS, there cannot be conurrency on
3178 * single radio. But then we can have multiple
3179 * radios !!
3180 */
3181 if (CHANNEL_STATE_DFS ==
3182 cds_get_channel_state(
3183 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003184 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 return true;
3186 }
3187 }
3188
3189 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003190 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 sta_ctx =
3192 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3193
3194 /*
3195 * if STA is already connected on DFS channel,
3196 * do not disable scan on dfs channels
3197 */
3198 if (hdd_conn_is_connected(sta_ctx) &&
3199 (CHANNEL_STATE_DFS ==
3200 cds_get_channel_state(
3201 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003202 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 return true;
3204 }
3205 }
3206
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303207 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 adapter_node,
3209 &next);
3210 adapter_node = next;
3211 }
3212
3213 return false;
3214}
3215
3216/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003217 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3218 * @hdd_ctx: HDD context within host driver
3219 * @adapter: Adapter pointer
3220 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3221 *
3222 * Loops through devices to see who is operating on DFS channels
3223 * and then disables/enables DFS channels by calling SME API.
3224 * Fails the disable request if any device is active on a DFS channel.
3225 *
3226 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003228
3229int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3230 hdd_adapter_t *adapter,
3231 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303234 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236
3237 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3238 if (no_dfs_flag) {
3239 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003240 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241
3242 if (true == status)
3243 return -EOPNOTSUPP;
3244
3245 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003246 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247
3248 if (true == status)
3249 return -EOPNOTSUPP;
3250 }
3251
3252 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3253
3254 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3255
3256 /*
3257 * call the SME API to tunnel down the new channel list
3258 * to the firmware
3259 */
3260 status = sme_handle_dfs_chan_scan(
3261 h_hal, hdd_ctx->config->enableDFSChnlScan);
3262
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303263 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264 ret_val = 0;
3265
3266 /*
3267 * Clear the SME scan cache also. Note that the
3268 * clearing of scan results is independent of session;
3269 * so no need to iterate over
3270 * all sessions
3271 */
3272 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303273 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 ret_val = -EPERM;
3275 }
3276
3277 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003278 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 ret_val = 0;
3280 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003281 return ret_val;
3282}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003283
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003284/**
3285 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3286 * @wiphy: corestack handler
3287 * @wdev: wireless device
3288 * @data: data
3289 * @data_len: data length
3290 * Return: success(0) or reason code for failure
3291 */
3292static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3293 struct wireless_dev *wdev,
3294 const void *data,
3295 int data_len)
3296{
3297 struct net_device *dev = wdev->netdev;
3298 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3299 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3300 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3301 int ret_val;
3302 uint32_t no_dfs_flag = 0;
3303
Jeff Johnson1f61b612016-02-12 16:28:33 -08003304 ENTER_DEV(dev);
3305
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003306 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303307 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003308 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003309
3310 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3311 data, data_len,
3312 wlan_hdd_set_no_dfs_flag_config_policy)) {
3313 hdd_err("invalid attr");
3314 return -EINVAL;
3315 }
3316
3317 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3318 hdd_err("attr dfs flag failed");
3319 return -EINVAL;
3320 }
3321
3322 no_dfs_flag = nla_get_u32(
3323 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3324
Jeff Johnson020db452016-06-29 14:37:26 -07003325 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003326
3327 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003328 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003329 return -EINVAL;
3330 }
3331
3332 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3333 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003334 return ret_val;
3335}
3336
3337/**
3338 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3339 *
3340 * @wiphy: wiphy device pointer
3341 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003342 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 * @data_len: Buffer length
3344 *
3345 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3346 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3347 *
3348 * Return: EOK or other error codes.
3349 */
3350
3351static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3352 struct wireless_dev *wdev,
3353 const void *data,
3354 int data_len)
3355{
3356 int ret;
3357
3358 cds_ssr_protect(__func__);
3359 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3360 data, data_len);
3361 cds_ssr_unprotect(__func__);
3362
3363 return ret;
3364}
3365
Manikandan Mohan80dea792016-04-28 16:36:48 -07003366static const struct nla_policy
3367wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3368 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3369};
3370
3371/**
3372 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3373 * @wiphy: wiphy device pointer
3374 * @wdev: wireless device pointer
3375 * @data: Vendor command data buffer
3376 * @data_len: Buffer length
3377 *
3378 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3379 * setup WISA Mode features.
3380 *
3381 * Return: Success(0) or reason code for failure
3382 */
3383static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3384 struct wireless_dev *wdev, const void *data, int data_len)
3385{
3386 struct net_device *dev = wdev->netdev;
3387 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3388 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3389 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3390 struct sir_wisa_params wisa;
3391 int ret_val;
3392 QDF_STATUS status;
3393 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003394 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3395 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003396
3397 ENTER_DEV(dev);
3398 ret_val = wlan_hdd_validate_context(hdd_ctx);
3399 if (ret_val)
3400 goto err;
3401
3402 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3403 hdd_err("Command not allowed in FTM mode");
3404 return -EPERM;
3405 }
3406
3407 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3408 wlan_hdd_wisa_cmd_policy)) {
3409 hdd_err("Invalid WISA cmd attributes");
3410 ret_val = -EINVAL;
3411 goto err;
3412 }
3413 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3414 hdd_err("Invalid WISA mode");
3415 ret_val = -EINVAL;
3416 goto err;
3417 }
3418
3419 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3420 hdd_info("WISA Mode: %d", wisa_mode);
3421 wisa.mode = wisa_mode;
3422 wisa.vdev_id = adapter->sessionId;
3423 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003424 if (!QDF_IS_STATUS_SUCCESS(status)) {
3425 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003426 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003427 }
3428 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003429 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003430 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3431 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003432 adapter->sessionId),
3433 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003434err:
3435 EXIT();
3436 return ret_val;
3437}
3438
3439/**
3440 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3441 * @wiphy: corestack handler
3442 * @wdev: wireless device
3443 * @data: data
3444 * @data_len: data length
3445 *
3446 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3447 * setup WISA mode features.
3448 *
3449 * Return: Success(0) or reason code for failure
3450 */
3451static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3452 struct wireless_dev *wdev,
3453 const void *data,
3454 int data_len)
3455{
3456 int ret;
3457
3458 cds_ssr_protect(__func__);
3459 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3460 cds_ssr_unprotect(__func__);
3461
3462 return ret;
3463}
3464
Anurag Chouhan96919482016-07-13 16:36:57 +05303465/*
3466 * define short names for the global vendor params
3467 * used by __wlan_hdd_cfg80211_get_station_cmd()
3468 */
3469#define STATION_INVALID \
3470 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3471#define STATION_INFO \
3472 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3473#define STATION_ASSOC_FAIL_REASON \
3474 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3475#define STATION_MAX \
3476 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3477
3478static const struct nla_policy
3479hdd_get_station_policy[STATION_MAX + 1] = {
3480 [STATION_INFO] = {.type = NLA_FLAG},
3481 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3482};
3483
3484/**
3485 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3486 * @hdd_ctx: HDD context within host driver
3487 * @wdev: wireless device
3488 *
3489 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3490 * Validate cmd attributes and send the station info to upper layers.
3491 *
3492 * Return: Success(0) or reason code for failure
3493 */
3494static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3495 hdd_adapter_t *adapter)
3496{
3497 struct sk_buff *skb = NULL;
3498 uint32_t nl_buf_len;
3499 hdd_station_ctx_t *hdd_sta_ctx;
3500
3501 nl_buf_len = NLMSG_HDRLEN;
3502 nl_buf_len += sizeof(uint32_t);
3503 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3504
3505 if (!skb) {
3506 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3507 return -ENOMEM;
3508 }
3509
3510 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3511
3512 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3513 hdd_sta_ctx->conn_info.assoc_status_code)) {
3514 hdd_err("put fail");
3515 goto fail;
3516 }
3517 return cfg80211_vendor_cmd_reply(skb);
3518fail:
3519 if (skb)
3520 kfree_skb(skb);
3521 return -EINVAL;
3522}
3523
3524/**
3525 * hdd_map_auth_type() - transform auth type specific to
3526 * vendor command
3527 * @auth_type: csr auth type
3528 *
3529 * Return: Success(0) or reason code for failure
3530 */
3531static int hdd_convert_auth_type(uint32_t auth_type)
3532{
3533 uint32_t ret_val;
3534
3535 switch (auth_type) {
3536 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3537 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3538 break;
3539 case eCSR_AUTH_TYPE_SHARED_KEY:
3540 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3541 break;
3542 case eCSR_AUTH_TYPE_WPA:
3543 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3544 break;
3545 case eCSR_AUTH_TYPE_WPA_PSK:
3546 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3547 break;
3548 case eCSR_AUTH_TYPE_AUTOSWITCH:
3549 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3550 break;
3551 case eCSR_AUTH_TYPE_WPA_NONE:
3552 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3553 break;
3554 case eCSR_AUTH_TYPE_RSN:
3555 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3556 break;
3557 case eCSR_AUTH_TYPE_RSN_PSK:
3558 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3559 break;
3560 case eCSR_AUTH_TYPE_FT_RSN:
3561 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3562 break;
3563 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3564 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3565 break;
3566 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3567 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3568 break;
3569 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3570 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3571 break;
3572 case eCSR_AUTH_TYPE_CCKM_WPA:
3573 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3574 break;
3575 case eCSR_AUTH_TYPE_CCKM_RSN:
3576 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3577 break;
3578 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3579 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3580 break;
3581 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3582 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3583 break;
3584 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3585 case eCSR_AUTH_TYPE_FAILED:
3586 case eCSR_AUTH_TYPE_NONE:
3587 default:
3588 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3589 break;
3590 }
3591 return ret_val;
3592}
3593
3594/**
3595 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3596 * vendor command
3597 * @dot11mode: dot11mode
3598 *
3599 * Return: Success(0) or reason code for failure
3600 */
3601static int hdd_convert_dot11mode(uint32_t dot11mode)
3602{
3603 uint32_t ret_val;
3604
3605 switch (dot11mode) {
3606 case eCSR_CFG_DOT11_MODE_11A:
3607 ret_val = QCA_WLAN_802_11_MODE_11A;
3608 break;
3609 case eCSR_CFG_DOT11_MODE_11B:
3610 ret_val = QCA_WLAN_802_11_MODE_11B;
3611 break;
3612 case eCSR_CFG_DOT11_MODE_11G:
3613 ret_val = QCA_WLAN_802_11_MODE_11G;
3614 break;
3615 case eCSR_CFG_DOT11_MODE_11N:
3616 ret_val = QCA_WLAN_802_11_MODE_11N;
3617 break;
3618 case eCSR_CFG_DOT11_MODE_11AC:
3619 ret_val = QCA_WLAN_802_11_MODE_11AC;
3620 break;
3621 case eCSR_CFG_DOT11_MODE_AUTO:
3622 case eCSR_CFG_DOT11_MODE_ABG:
3623 default:
3624 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3625 }
3626 return ret_val;
3627}
3628
3629/**
3630 * hdd_add_tx_bitrate() - add tx bitrate attribute
3631 * @skb: pointer to sk buff
3632 * @hdd_sta_ctx: pointer to hdd station context
3633 * @idx: attribute index
3634 *
3635 * Return: Success(0) or reason code for failure
3636 */
3637static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3638 hdd_station_ctx_t *hdd_sta_ctx,
3639 int idx)
3640{
3641 struct nlattr *nla_attr;
3642 uint32_t bitrate, bitrate_compat;
3643
3644 nla_attr = nla_nest_start(skb, idx);
3645 if (!nla_attr)
3646 goto fail;
3647 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3648 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3649
3650 /* report 16-bit bitrate only if we can */
3651 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3652 if (bitrate > 0 &&
3653 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3654 hdd_err("put fail");
3655 goto fail;
3656 }
3657 if (bitrate_compat > 0 &&
3658 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3659 hdd_err("put fail");
3660 goto fail;
3661 }
3662 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3663 hdd_sta_ctx->conn_info.txrate.nss)) {
3664 hdd_err("put fail");
3665 goto fail;
3666 }
3667 nla_nest_end(skb, nla_attr);
3668 return 0;
3669fail:
3670 return -EINVAL;
3671}
3672
3673/**
3674 * hdd_add_sta_info() - add station info attribute
3675 * @skb: pointer to sk buff
3676 * @hdd_sta_ctx: pointer to hdd station context
3677 * @idx: attribute index
3678 *
3679 * Return: Success(0) or reason code for failure
3680 */
3681static int32_t hdd_add_sta_info(struct sk_buff *skb,
3682 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3683{
3684 struct nlattr *nla_attr;
3685
3686 nla_attr = nla_nest_start(skb, idx);
3687 if (!nla_attr)
3688 goto fail;
3689 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3690 (hdd_sta_ctx->conn_info.signal + 100))) {
3691 hdd_err("put fail");
3692 goto fail;
3693 }
3694 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3695 goto fail;
3696 nla_nest_end(skb, nla_attr);
3697 return 0;
3698fail:
3699 return -EINVAL;
3700}
3701
3702/**
3703 * hdd_add_survey_info() - add survey info attribute
3704 * @skb: pointer to sk buff
3705 * @hdd_sta_ctx: pointer to hdd station context
3706 * @idx: attribute index
3707 *
3708 * Return: Success(0) or reason code for failure
3709 */
3710static int32_t hdd_add_survey_info(struct sk_buff *skb,
3711 hdd_station_ctx_t *hdd_sta_ctx,
3712 int idx)
3713{
3714 struct nlattr *nla_attr;
3715
3716 nla_attr = nla_nest_start(skb, idx);
3717 if (!nla_attr)
3718 goto fail;
3719 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3720 hdd_sta_ctx->conn_info.freq) ||
3721 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3722 (hdd_sta_ctx->conn_info.noise + 100))) {
3723 hdd_err("put fail");
3724 goto fail;
3725 }
3726 nla_nest_end(skb, nla_attr);
3727 return 0;
3728fail:
3729 return -EINVAL;
3730}
3731
3732/**
3733 * hdd_add_link_standard_info() - add link info attribute
3734 * @skb: pointer to sk buff
3735 * @hdd_sta_ctx: pointer to hdd station context
3736 * @idx: attribute index
3737 *
3738 * Return: Success(0) or reason code for failure
3739 */
3740static int32_t
3741hdd_add_link_standard_info(struct sk_buff *skb,
3742 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3743{
3744 struct nlattr *nla_attr;
3745
3746 nla_attr = nla_nest_start(skb, idx);
3747 if (!nla_attr)
3748 goto fail;
3749 if (nla_put(skb,
3750 NL80211_ATTR_SSID,
3751 hdd_sta_ctx->conn_info.SSID.SSID.length,
3752 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3753 hdd_err("put fail");
3754 goto fail;
3755 }
3756 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3757 goto fail;
3758 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3759 goto fail;
3760 nla_nest_end(skb, nla_attr);
3761 return 0;
3762fail:
3763 return -EINVAL;
3764}
3765
3766/**
3767 * hdd_add_ap_standard_info() - add ap info attribute
3768 * @skb: pointer to sk buff
3769 * @hdd_sta_ctx: pointer to hdd station context
3770 * @idx: attribute index
3771 *
3772 * Return: Success(0) or reason code for failure
3773 */
3774static int32_t
3775hdd_add_ap_standard_info(struct sk_buff *skb,
3776 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3777{
3778 struct nlattr *nla_attr;
3779
3780 nla_attr = nla_nest_start(skb, idx);
3781 if (!nla_attr)
3782 goto fail;
3783 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3784 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3785 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3786 &hdd_sta_ctx->conn_info.vht_caps)) {
3787 hdd_err("put fail");
3788 goto fail;
3789 }
3790 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3791 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3792 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3793 &hdd_sta_ctx->conn_info.ht_caps)) {
3794 hdd_err("put fail");
3795 goto fail;
3796 }
3797 nla_nest_end(skb, nla_attr);
3798 return 0;
3799fail:
3800 return -EINVAL;
3801}
3802
3803/**
3804 * hdd_get_station_info() - send BSS information to supplicant
3805 * @hdd_ctx: pointer to hdd context
3806 * @adapter: pointer to adapter
3807 *
3808 * Return: 0 if success else error status
3809 */
3810static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3811 hdd_adapter_t *adapter)
3812{
3813 struct sk_buff *skb = NULL;
3814 uint8_t *tmp_hs20 = NULL;
3815 uint32_t nl_buf_len;
3816 hdd_station_ctx_t *hdd_sta_ctx;
3817
3818 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3819
3820 nl_buf_len = NLMSG_HDRLEN;
3821 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3822 sizeof(hdd_sta_ctx->conn_info.freq) +
3823 sizeof(hdd_sta_ctx->conn_info.noise) +
3824 sizeof(hdd_sta_ctx->conn_info.signal) +
3825 (sizeof(uint32_t) * 2) +
3826 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3827 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3828 sizeof(hdd_sta_ctx->conn_info.authType) +
3829 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3830 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3831 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3832 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3833 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3834 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3835 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3836 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3837 1);
3838 }
3839 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3840 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3841 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3842 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3843
3844
3845 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3846 if (!skb) {
3847 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3848 return -ENOMEM;
3849 }
3850
3851 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3852 LINK_INFO_STANDARD_NL80211_ATTR)) {
3853 hdd_err("put fail");
3854 goto fail;
3855 }
3856 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3857 AP_INFO_STANDARD_NL80211_ATTR)) {
3858 hdd_err("put fail");
3859 goto fail;
3860 }
3861 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3862 hdd_sta_ctx->conn_info.roam_count) ||
3863 nla_put_u32(skb, INFO_AKM,
3864 hdd_convert_auth_type(
3865 hdd_sta_ctx->conn_info.authType)) ||
3866 nla_put_u32(skb, WLAN802_11_MODE,
3867 hdd_convert_dot11mode(
3868 hdd_sta_ctx->conn_info.dot11Mode))) {
3869 hdd_err("put fail");
3870 goto fail;
3871 }
3872 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3873 if (nla_put(skb, HT_OPERATION,
3874 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3875 &hdd_sta_ctx->conn_info.ht_operation)) {
3876 hdd_err("put fail");
3877 goto fail;
3878 }
3879 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3880 if (nla_put(skb, VHT_OPERATION,
3881 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3882 &hdd_sta_ctx->conn_info.vht_operation)) {
3883 hdd_err("put fail");
3884 goto fail;
3885 }
3886 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3887 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3888 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3889 tmp_hs20 + 1)) {
3890 hdd_err("put fail");
3891 goto fail;
3892 }
3893
3894 return cfg80211_vendor_cmd_reply(skb);
3895fail:
3896 if (skb)
3897 kfree_skb(skb);
3898 return -EINVAL;
3899}
3900
3901/**
3902 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3903 * @wiphy: corestack handler
3904 * @wdev: wireless device
3905 * @data: data
3906 * @data_len: data length
3907 *
3908 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3909 * Validate cmd attributes and send the station info to upper layers.
3910 *
3911 * Return: Success(0) or reason code for failure
3912 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303913static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303914__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3915 struct wireless_dev *wdev,
3916 const void *data,
3917 int data_len)
3918{
3919 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3920 struct net_device *dev = wdev->netdev;
3921 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3922 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3923 int32_t status;
3924
3925 ENTER_DEV(dev);
3926 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3927 hdd_err("Command not allowed in FTM mode");
3928 status = -EPERM;
3929 goto out;
3930 }
3931
3932 status = wlan_hdd_validate_context(hdd_ctx);
3933 if (0 != status)
3934 goto out;
3935
3936
3937 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3938 data, data_len, NULL);
3939 if (status) {
3940 hdd_err("Invalid ATTR");
3941 goto out;
3942 }
3943
3944 /* Parse and fetch Command Type*/
3945 if (tb[STATION_INFO]) {
3946 status = hdd_get_station_info(hdd_ctx, adapter);
3947 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3948 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3949 } else {
3950 hdd_err("get station info cmd type failed");
3951 status = -EINVAL;
3952 goto out;
3953 }
3954 EXIT();
3955out:
3956 return status;
3957}
3958
3959/**
3960 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3961 * @wiphy: corestack handler
3962 * @wdev: wireless device
3963 * @data: data
3964 * @data_len: data length
3965 *
3966 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3967 * Validate cmd attributes and send the station info to upper layers.
3968 *
3969 * Return: Success(0) or reason code for failure
3970 */
3971static int32_t
3972hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3973 struct wireless_dev *wdev,
3974 const void *data,
3975 int data_len)
3976{
3977 int ret;
3978
3979 cds_ssr_protect(__func__);
3980 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3981 cds_ssr_unprotect(__func__);
3982
3983 return ret;
3984}
3985
3986/*
3987 * undef short names defined for get station command
3988 * used by __wlan_hdd_cfg80211_get_station_cmd()
3989 */
3990#undef STATION_INVALID
3991#undef STATION_INFO
3992#undef STATION_ASSOC_FAIL_REASON
3993#undef STATION_MAX
3994
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3996/**
3997 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3998 * @wiphy: pointer to wireless wiphy structure.
3999 * @wdev: pointer to wireless_dev structure.
4000 * @data: Pointer to the Key data
4001 * @data_len:Length of the data passed
4002 *
4003 * This is called when wlan driver needs to save the keys received via
4004 * vendor specific command.
4005 *
4006 * Return: Return the Success or Failure code.
4007 */
4008static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4009 struct wireless_dev *wdev,
4010 const void *data, int data_len)
4011{
4012 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4013 struct net_device *dev = wdev->netdev;
4014 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4015 hdd_context_t *hdd_ctx_ptr;
4016 int status;
4017
Jeff Johnson1f61b612016-02-12 16:28:33 -08004018 ENTER_DEV(dev);
4019
Anurag Chouhan6d760662016-02-20 16:05:43 +05304020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 hdd_err("Command not allowed in FTM mode");
4022 return -EPERM;
4023 }
4024
4025 if ((data == NULL) || (data_len == 0) ||
4026 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004027 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028 return -EINVAL;
4029 }
4030
4031 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4032 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004033 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004034 return -EINVAL;
4035 }
4036
4037 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304038 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4041 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004042 true,
4043 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304044 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4045 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4047 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4048 return 0;
4049}
4050
4051/**
4052 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4053 * @wiphy: pointer to wireless wiphy structure.
4054 * @wdev: pointer to wireless_dev structure.
4055 * @data: Pointer to the Key data
4056 * @data_len:Length of the data passed
4057 *
4058 * This is called when wlan driver needs to save the keys received via
4059 * vendor specific command.
4060 *
4061 * Return: Return the Success or Failure code.
4062 */
4063static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4064 struct wireless_dev *wdev,
4065 const void *data, int data_len)
4066{
4067 int ret;
4068
4069 cds_ssr_protect(__func__);
4070 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4071 cds_ssr_unprotect(__func__);
4072
4073 return ret;
4074}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004075#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004076
4077static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4078 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4079 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4080 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004081 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082};
4083
4084/**
4085 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4086 * @wiphy: pointer to wireless wiphy structure.
4087 * @wdev: pointer to wireless_dev structure.
4088 * @data: Pointer to the data to be passed via vendor interface
4089 * @data_len:Length of the data to be passed
4090 *
4091 * This is called when wlan driver needs to send wifi driver related info
4092 * (driver/fw version) to the user space application upon request.
4093 *
4094 * Return: Return the Success or Failure code.
4095 */
4096static int
4097__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4098 struct wireless_dev *wdev,
4099 const void *data, int data_len)
4100{
4101 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4102 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004103 tSirVersionString driver_version;
4104 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004107 struct sk_buff *reply_skb;
4108 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109
Jeff Johnson1f61b612016-02-12 16:28:33 -08004110 ENTER_DEV(wdev->netdev);
4111
Anurag Chouhan6d760662016-02-20 16:05:43 +05304112 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113 hdd_err("Command not allowed in FTM mode");
4114 return -EPERM;
4115 }
4116
4117 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304118 if (status)
4119 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120
4121 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4122 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004123 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 return -EINVAL;
4125 }
4126
4127 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004128 hdd_err("Rcvd req for Driver version");
4129 strlcpy(driver_version, QWLAN_VERSIONSTR,
4130 sizeof(driver_version));
4131 skb_len += strlen(driver_version) + 1;
4132 count++;
4133 }
4134
4135 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4136 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4138 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004139 snprintf(firmware_version, sizeof(firmware_version),
4140 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4141 skb_len += strlen(firmware_version) + 1;
4142 count++;
4143 }
4144
4145 if (count == 0) {
4146 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 return -EINVAL;
4148 }
4149
Ryan Hsu7ac88852016-04-28 10:20:34 -07004150 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4151 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4152
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004154 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004155 return -ENOMEM;
4156 }
4157
Ryan Hsu7ac88852016-04-28 10:20:34 -07004158 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4159 if (nla_put_string(reply_skb,
4160 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4161 driver_version))
4162 goto error_nla_fail;
4163 }
4164
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304165 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004166 if (nla_put_string(reply_skb,
4167 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4168 firmware_version))
4169 goto error_nla_fail;
4170 }
4171
4172 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4173 if (nla_put_u32(reply_skb,
4174 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4175 hdd_ctx->radio_index))
4176 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004177 }
4178
4179 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004180
4181error_nla_fail:
4182 hdd_err("nla put fail");
4183 kfree_skb(reply_skb);
4184 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004185}
4186
4187/**
4188 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4189 * @wiphy: pointer to wireless wiphy structure.
4190 * @wdev: pointer to wireless_dev structure.
4191 * @data: Pointer to the data to be passed via vendor interface
4192 * @data_len:Length of the data to be passed
4193 *
4194 * This is called when wlan driver needs to send wifi driver related info
4195 * (driver/fw version) to the user space application upon request.
4196 *
4197 * Return: Return the Success or Failure code.
4198 */
4199static int
4200wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4201 struct wireless_dev *wdev,
4202 const void *data, int data_len)
4203{
4204 int ret;
4205
4206 cds_ssr_protect(__func__);
4207 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4208 cds_ssr_unprotect(__func__);
4209
4210 return ret;
4211}
4212
4213/**
4214 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4215 * @wiphy: pointer to wireless wiphy structure.
4216 * @wdev: pointer to wireless_dev structure.
4217 * @data: Pointer to the data to be passed via vendor interface
4218 * @data_len:Length of the data to be passed
4219 *
4220 * This is called by userspace to know the supported logger features
4221 *
4222 * Return: Return the Success or Failure code.
4223 */
4224static int
4225__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4226 struct wireless_dev *wdev,
4227 const void *data, int data_len)
4228{
4229 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4230 int status;
4231 uint32_t features;
4232 struct sk_buff *reply_skb = NULL;
4233
Jeff Johnson1f61b612016-02-12 16:28:33 -08004234 ENTER_DEV(wdev->netdev);
4235
Anurag Chouhan6d760662016-02-20 16:05:43 +05304236 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004237 hdd_err("Command not allowed in FTM mode");
4238 return -EPERM;
4239 }
4240
4241 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304242 if (status)
4243 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244
4245 features = 0;
4246
4247 if (hdd_is_memdump_supported())
4248 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4249 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4250 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4251 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4252
4253 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4254 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4255 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004256 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004257 return -ENOMEM;
4258 }
4259
Jeff Johnson020db452016-06-29 14:37:26 -07004260 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4262 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004263 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 kfree_skb(reply_skb);
4265 return -EINVAL;
4266 }
4267
4268 return cfg80211_vendor_cmd_reply(reply_skb);
4269}
4270
4271/**
4272 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4273 * @wiphy: pointer to wireless wiphy structure.
4274 * @wdev: pointer to wireless_dev structure.
4275 * @data: Pointer to the data to be passed via vendor interface
4276 * @data_len:Length of the data to be passed
4277 *
4278 * This is called by userspace to know the supported logger features
4279 *
4280 * Return: Return the Success or Failure code.
4281 */
4282static int
4283wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4284 struct wireless_dev *wdev,
4285 const void *data, int data_len)
4286{
4287 int ret;
4288
4289 cds_ssr_protect(__func__);
4290 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4291 data, data_len);
4292 cds_ssr_unprotect(__func__);
4293
4294 return ret;
4295}
4296
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004297#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298/**
4299 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304300 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 * @bssid: pointer to bssid of roamed AP.
4302 * @req_rsn_ie: Pointer to request RSN IE
4303 * @req_rsn_len: Length of the request RSN IE
4304 * @rsp_rsn_ie: Pointer to response RSN IE
4305 * @rsp_rsn_len: Length of the response RSN IE
4306 * @roam_info_ptr: Pointer to the roaming related information
4307 *
4308 * This is called when wlan driver needs to send the roaming and
4309 * authorization information after roaming.
4310 *
4311 * The information that would be sent is the request RSN IE, response
4312 * RSN IE and BSSID of the newly roamed AP.
4313 *
4314 * If the Authorized status is authenticated, then additional parameters
4315 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4316 * supplicant.
4317 *
4318 * The supplicant upon receiving this event would ignore the legacy
4319 * cfg80211_roamed call and use the entire information from this event.
4320 * The cfg80211_roamed should still co-exist since the kernel will
4321 * make use of the parameters even if the supplicant ignores it.
4322 *
4323 * Return: Return the Success or Failure code.
4324 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304325int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004326 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4327 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4328{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304329 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004330 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004331 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004332 ENTER();
4333
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304334 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004337 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004338 !roam_info_ptr->roamSynchInProgress)
4339 return 0;
4340
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004341 /*
4342 * The user space has issued a disconnect when roaming is in
4343 * progress. The disconnect should be honored gracefully.
4344 * If the roaming is complete and the roam event is sent
4345 * back to the user space, it will get confused as it is
4346 * expecting a disconnect event. So, do not send the event
4347 * and handle the disconnect later.
4348 */
4349 if (adapter->defer_disconnect) {
4350 hdd_notice("LFR3:Do not send roam auth event");
4351 return 0;
4352 }
4353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304355 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4357 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4358 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004359 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4361 GFP_KERNEL);
4362
4363 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004364 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 return -EINVAL;
4366 }
4367
4368 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4369 ETH_ALEN, bssid) ||
4370 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4371 req_rsn_len, req_rsn_ie) ||
4372 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4373 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004374 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 goto nla_put_failure;
4376 }
Jeff Johnson020db452016-06-29 14:37:26 -07004377 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 if (roam_info_ptr->synchAuthStatus ==
4379 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004380 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004381 if (nla_put_u8(skb,
4382 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4383 hdd_err("nla put fail");
4384 goto nla_put_failure;
4385 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004386 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4387 /* if FT or CCKM connection: dont send replay counter */
4388 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4389 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4390 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4391 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4392 nla_put(skb,
4393 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4394 SIR_REPLAY_CTR_LEN,
4395 roam_info_ptr->replay_ctr)) {
4396 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004397 hdd_err("failed to send replay counter.");
4398 goto nla_put_failure;
4399 }
4400 if (nla_put(skb,
4401 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4402 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4403 nla_put(skb,
4404 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4405 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4406 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407 goto nla_put_failure;
4408 }
4409 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004410 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004411 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4412 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004413 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414 goto nla_put_failure;
4415 }
4416 }
4417
Jeff Johnson020db452016-06-29 14:37:26 -07004418 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004419 roam_info_ptr->subnet_change_status);
4420
4421 /*
4422 * Add subnet change status if subnet has changed
4423 * 0 = unchanged
4424 * 1 = changed
4425 * 2 = unknown
4426 */
4427 if (roam_info_ptr->subnet_change_status) {
4428 if (nla_put_u8(skb,
4429 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4430 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004431 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004432 goto nla_put_failure;
4433 }
4434 }
4435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004436 cfg80211_vendor_event(skb, GFP_KERNEL);
4437 return 0;
4438
4439nla_put_failure:
4440 kfree_skb(skb);
4441 return -EINVAL;
4442}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004443#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444
4445static const struct nla_policy
4446wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4447
4448 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4449 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4450 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304451 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304452 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4453 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004454 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4455 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4456 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4457 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4458 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304459 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460};
4461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304463 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4464 *
4465 * @adapter: Pointer to HDD adapter
4466 * @ie_data: Pointer to Scan IEs buffer
4467 * @ie_len: Length of Scan IEs
4468 *
4469 * Return: 0 on success; error number otherwise
4470 */
4471static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4472 uint8_t *ie_data, uint8_t ie_len)
4473{
4474 hdd_scaninfo_t *scan_info = NULL;
4475 scan_info = &adapter->scan_info;
4476
4477 if (scan_info->default_scan_ies) {
4478 qdf_mem_free(scan_info->default_scan_ies);
4479 scan_info->default_scan_ies = NULL;
4480 }
4481
4482 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4483 if (!scan_info->default_scan_ies)
4484 return -ENOMEM;
4485
4486 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4487 scan_info->default_scan_ies_len = ie_len;
4488 return 0;
4489}
4490
4491/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4493 * vendor command
4494 *
4495 * @wiphy: wiphy device pointer
4496 * @wdev: wireless device pointer
4497 * @data: Vendor command data buffer
4498 * @data_len: Buffer length
4499 *
4500 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4501 *
4502 * Return: Error code.
4503 */
4504static int
4505__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4506 struct wireless_dev *wdev,
4507 const void *data,
4508 int data_len)
4509{
4510 struct net_device *dev = wdev->netdev;
4511 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4512 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4513 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4514 int ret_val = 0;
4515 u32 modulated_dtim;
4516 u16 stats_avg_factor;
4517 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304518 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004519 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004520 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304521 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304522 int attr_len;
4523 int access_policy = 0;
4524 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4525 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304526 uint16_t scan_ie_len = 0;
4527 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304528 struct sir_set_tx_rx_aggregation_size request;
4529 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004530 uint8_t retry, delay;
4531 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304532 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304533
Jeff Johnson1f61b612016-02-12 16:28:33 -08004534 ENTER_DEV(dev);
4535
Anurag Chouhan6d760662016-02-20 16:05:43 +05304536 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537 hdd_err("Command not allowed in FTM mode");
4538 return -EPERM;
4539 }
4540
4541 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304542 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004544
4545 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4546 data, data_len,
4547 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004548 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004549 return -EINVAL;
4550 }
4551
Krunal Sonie3531942016-04-12 17:43:53 -07004552 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4553 ftm_capab = nla_get_u32(tb[
4554 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4555 hdd_ctx->config->fine_time_meas_cap =
4556 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4557 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304558 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004559 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004560 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4561 hdd_ctx->config->fine_time_meas_cap);
Krunal Sonie3531942016-04-12 17:43:53 -07004562 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4563 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4564 hdd_ctx->config->fine_time_meas_cap);
4565 }
4566
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004567 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4568 modulated_dtim = nla_get_u32(
4569 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4570
4571 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4572 adapter->sessionId,
4573 modulated_dtim);
4574
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304575 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 ret_val = -EPERM;
4577 }
4578
Kapil Gupta6213c012016-09-02 19:39:09 +05304579 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4580 qpower = nla_get_u8(
4581 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4582 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4583 ret_val = -EINVAL;
4584 }
4585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4587 stats_avg_factor = nla_get_u16(
4588 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4589 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4590 adapter->sessionId,
4591 stats_avg_factor);
4592
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304593 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594 ret_val = -EPERM;
4595 }
4596
4597
4598 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4599 guard_time = nla_get_u32(
4600 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4601 status = sme_configure_guard_time(hdd_ctx->hHal,
4602 adapter->sessionId,
4603 guard_time);
4604
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304605 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004606 ret_val = -EPERM;
4607 }
4608
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304609 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4610 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4611 attr_len = nla_len(
4612 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4613 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4614 hdd_info("Invalid value. attr_len %d",
4615 attr_len);
4616 return -EINVAL;
4617 }
4618
4619 nla_memcpy(&vendor_ie,
4620 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4621 attr_len);
4622 vendor_ie_present = true;
4623 hdd_info("Access policy vendor ie present.attr_len %d",
4624 attr_len);
4625 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4626 &vendor_ie[0], attr_len);
4627 }
4628
4629 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4630 access_policy = (int) nla_get_u32(
4631 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4632 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4633 (access_policy >
4634 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4635 hdd_info("Invalid value. access_policy %d",
4636 access_policy);
4637 return -EINVAL;
4638 }
4639 access_policy_present = true;
4640 hdd_info("Access policy present. access_policy %d",
4641 access_policy);
4642 }
4643
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004644 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4645 retry = nla_get_u8(tb[
4646 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4647 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4648 CFG_NON_AGG_RETRY_MAX : retry;
4649 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4650 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4651 retry, PDEV_CMD);
4652 }
4653
4654 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4655 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4656 retry = retry > CFG_AGG_RETRY_MAX ?
4657 CFG_AGG_RETRY_MAX : retry;
4658
4659 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4660 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4661 CFG_AGG_RETRY_MIN : retry;
4662 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4663 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4664 retry, PDEV_CMD);
4665 }
4666
4667 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4668 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4669 retry = retry > CFG_MGMT_RETRY_MAX ?
4670 CFG_MGMT_RETRY_MAX : retry;
4671 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4672 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4673 retry, PDEV_CMD);
4674 }
4675
4676 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4677 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4678 retry = retry > CFG_CTRL_RETRY_MAX ?
4679 CFG_CTRL_RETRY_MAX : retry;
4680 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4681 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4682 retry, PDEV_CMD);
4683 }
4684
4685 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4686 delay = nla_get_u8(tb[
4687 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4688 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4689 CFG_PROPAGATION_DELAY_MAX : delay;
4690 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4691 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4692 delay, PDEV_CMD);
4693 }
4694
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304695 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4696 tx_fail_count = nla_get_u32(
4697 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4698 if (tx_fail_count) {
4699 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4700 adapter->sessionId, tx_fail_count);
4701 if (QDF_STATUS_SUCCESS != status) {
4702 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4703 status);
4704 return -EINVAL;
4705 }
4706 }
4707 }
4708
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304709 if (vendor_ie_present && access_policy_present) {
4710 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4711 access_policy =
4712 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304713 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304714 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304715 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304716
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304717 hdd_info("calling sme_update_access_policy_vendor_ie");
4718 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4719 adapter->sessionId, &vendor_ie[0],
4720 access_policy);
4721 if (QDF_STATUS_SUCCESS != status) {
4722 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304723 return -EINVAL;
4724 }
4725 }
4726
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304727 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4728 set_value = nla_get_u8(
4729 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4730 hdd_info("set_value: %d", set_value);
4731 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4732 }
4733
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304734 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4735 scan_ie_len = nla_len(
4736 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4737 hdd_info("Received default scan IE of len %d session %d device mode %d",
4738 scan_ie_len, adapter->sessionId,
4739 adapter->device_mode);
4740 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4741 scan_ie = (uint8_t *) nla_data(tb
4742 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304743
4744 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4745 scan_ie_len))
4746 hdd_err("Failed to save default scan IEs");
4747
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304748 if (adapter->device_mode == QDF_STA_MODE) {
4749 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4750 adapter->sessionId, scan_ie,
4751 scan_ie_len);
4752 if (QDF_STATUS_SUCCESS != status)
4753 ret_val = -EPERM;
4754 }
4755 } else
4756 ret_val = -EPERM;
4757 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304758
4759 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4760 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4761 /* if one is specified, both must be specified */
4762 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4763 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4764 hdd_err("Both TX and RX MPDU Aggregation required");
4765 return -EINVAL;
4766 }
4767
4768 request.tx_aggregation_size = nla_get_u8(
4769 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4770 request.rx_aggregation_size = nla_get_u8(
4771 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4772 request.vdev_id = adapter->sessionId;
4773
4774 if (request.tx_aggregation_size >=
4775 CFG_TX_AGGREGATION_SIZE_MIN &&
4776 request.tx_aggregation_size <=
4777 CFG_TX_AGGREGATION_SIZE_MAX &&
4778 request.rx_aggregation_size >=
4779 CFG_RX_AGGREGATION_SIZE_MIN &&
4780 request.rx_aggregation_size <=
4781 CFG_RX_AGGREGATION_SIZE_MAX) {
4782 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4783 if (qdf_status != QDF_STATUS_SUCCESS) {
4784 hdd_err("failed to set aggr sizes err %d",
4785 qdf_status);
4786 ret_val = -EPERM;
4787 }
4788 } else {
4789 hdd_err("TX %d RX %d MPDU aggr size not in range",
4790 request.tx_aggregation_size,
4791 request.rx_aggregation_size);
4792 ret_val = -EINVAL;
4793 }
4794 }
4795
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304796 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4797 uint8_t ignore_assoc_disallowed;
4798
4799 ignore_assoc_disallowed
4800 = nla_get_u8(tb[
4801 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4802 hdd_info("Set ignore_assoc_disallowed value - %d",
4803 ignore_assoc_disallowed);
4804 if ((ignore_assoc_disallowed <
4805 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4806 (ignore_assoc_disallowed >
4807 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4808 return -EPERM;
4809
4810 sme_update_session_param(hdd_ctx->hHal,
4811 adapter->sessionId,
4812 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4813 ignore_assoc_disallowed);
4814 }
4815
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816 return ret_val;
4817}
4818
4819/**
4820 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4821 * vendor command
4822 *
4823 * @wiphy: wiphy device pointer
4824 * @wdev: wireless device pointer
4825 * @data: Vendor command data buffer
4826 * @data_len: Buffer length
4827 *
4828 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4829 *
4830 * Return: EOK or other error codes.
4831 */
4832static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4833 struct wireless_dev *wdev,
4834 const void *data,
4835 int data_len)
4836{
4837 int ret;
4838
4839 cds_ssr_protect(__func__);
4840 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4841 data, data_len);
4842 cds_ssr_unprotect(__func__);
4843
4844 return ret;
4845}
4846
4847static const struct
4848nla_policy
4849qca_wlan_vendor_wifi_logger_start_policy
4850[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4851 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4852 = {.type = NLA_U32 },
4853 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4854 = {.type = NLA_U32 },
4855 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4856 = {.type = NLA_U32 },
4857};
4858
4859/**
4860 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4861 * or disable the collection of packet statistics from the firmware
4862 * @wiphy: WIPHY structure pointer
4863 * @wdev: Wireless device structure pointer
4864 * @data: Pointer to the data received
4865 * @data_len: Length of the data received
4866 *
4867 * This function enables or disables the collection of packet statistics from
4868 * the firmware
4869 *
4870 * Return: 0 on success and errno on failure
4871 */
4872static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4873 struct wireless_dev *wdev,
4874 const void *data,
4875 int data_len)
4876{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304877 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4879 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4880 struct sir_wifi_start_log start_log;
4881
Jeff Johnson1f61b612016-02-12 16:28:33 -08004882 ENTER_DEV(wdev->netdev);
4883
Anurag Chouhan6d760662016-02-20 16:05:43 +05304884 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004885 hdd_err("Command not allowed in FTM mode");
4886 return -EPERM;
4887 }
4888
4889 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304890 if (status)
4891 return status;
4892
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304893 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4894 hdd_err("Driver Modules are closed, can not start logger");
4895 return -EINVAL;
4896 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004897
4898 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4899 data, data_len,
4900 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004901 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004902 return -EINVAL;
4903 }
4904
4905 /* Parse and fetch ring id */
4906 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004907 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908 return -EINVAL;
4909 }
4910 start_log.ring_id = nla_get_u32(
4911 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004912 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913
4914 /* Parse and fetch verbose level */
4915 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004916 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 return -EINVAL;
4918 }
4919 start_log.verbose_level = nla_get_u32(
4920 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004921 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922
4923 /* Parse and fetch flag */
4924 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004925 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926 return -EINVAL;
4927 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304928 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304930 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304932 /* size is buff size which can be set using iwpriv command*/
4933 start_log.size = 0;
4934
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4936
4937 if (start_log.ring_id == RING_ID_WAKELOCK) {
4938 /* Start/stop wakelock events */
4939 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4940 cds_set_wakelock_logging(true);
4941 else
4942 cds_set_wakelock_logging(false);
4943 return 0;
4944 }
4945
4946 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304947 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004948 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 status);
4950 return -EINVAL;
4951 }
4952 return 0;
4953}
4954
4955/**
4956 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4957 * or disable the collection of packet statistics from the firmware
4958 * @wiphy: WIPHY structure pointer
4959 * @wdev: Wireless device structure pointer
4960 * @data: Pointer to the data received
4961 * @data_len: Length of the data received
4962 *
4963 * This function is used to enable or disable the collection of packet
4964 * statistics from the firmware
4965 *
4966 * Return: 0 on success and errno on failure
4967 */
4968static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4969 struct wireless_dev *wdev,
4970 const void *data,
4971 int data_len)
4972{
4973 int ret = 0;
4974
4975 cds_ssr_protect(__func__);
4976 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4977 wdev, data, data_len);
4978 cds_ssr_unprotect(__func__);
4979
4980 return ret;
4981}
4982
4983static const struct
4984nla_policy
4985qca_wlan_vendor_wifi_logger_get_ring_data_policy
4986[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4987 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4988 = {.type = NLA_U32 },
4989};
4990
4991/**
4992 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4993 * @wiphy: WIPHY structure pointer
4994 * @wdev: Wireless device structure pointer
4995 * @data: Pointer to the data received
4996 * @data_len: Length of the data received
4997 *
4998 * This function is used to flush or retrieve the per packet statistics from
4999 * the driver
5000 *
5001 * Return: 0 on success and errno on failure
5002 */
5003static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5004 struct wireless_dev *wdev,
5005 const void *data,
5006 int data_len)
5007{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305008 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 uint32_t ring_id;
5010 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5011 struct nlattr *tb
5012 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5013
Jeff Johnson1f61b612016-02-12 16:28:33 -08005014 ENTER_DEV(wdev->netdev);
5015
Anurag Chouhan6d760662016-02-20 16:05:43 +05305016 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017 hdd_err("Command not allowed in FTM mode");
5018 return -EPERM;
5019 }
5020
5021 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305022 if (status)
5023 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024
5025 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5026 data, data_len,
5027 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005028 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029 return -EINVAL;
5030 }
5031
5032 /* Parse and fetch ring id */
5033 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005034 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005035 return -EINVAL;
5036 }
5037
5038 ring_id = nla_get_u32(
5039 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5040
5041 if (ring_id == RING_ID_PER_PACKET_STATS) {
5042 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07005043 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305044 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5045 /*
5046 * As part of DRIVER ring ID, flush both driver and fw logs.
5047 * For other Ring ID's driver doesn't have any rings to flush
5048 */
5049 hdd_notice("Bug report triggered by framework");
5050
5051 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5052 WLAN_LOG_INDICATOR_FRAMEWORK,
5053 WLAN_LOG_REASON_CODE_UNUSED,
5054 true, false);
5055 if (QDF_STATUS_SUCCESS != status) {
5056 hdd_err("Failed to trigger bug report");
5057 return -EINVAL;
5058 }
5059 } else {
5060 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5061 WLAN_LOG_INDICATOR_FRAMEWORK,
5062 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005063 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 return 0;
5065}
5066
5067/**
5068 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5069 * @wiphy: WIPHY structure pointer
5070 * @wdev: Wireless device structure pointer
5071 * @data: Pointer to the data received
5072 * @data_len: Length of the data received
5073 *
5074 * This function is used to flush or retrieve the per packet statistics from
5075 * the driver
5076 *
5077 * Return: 0 on success and errno on failure
5078 */
5079static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5080 struct wireless_dev *wdev,
5081 const void *data,
5082 int data_len)
5083{
5084 int ret = 0;
5085
5086 cds_ssr_protect(__func__);
5087 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5088 wdev, data, data_len);
5089 cds_ssr_unprotect(__func__);
5090
5091 return ret;
5092}
5093
5094#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5095/**
5096 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5097 * @hdd_ctx: HDD context
5098 * @request_id: [input] request id
5099 * @pattern_id: [output] pattern id
5100 *
5101 * This function loops through request id to pattern id array
5102 * if the slot is available, store the request id and return pattern id
5103 * if entry exists, return the pattern id
5104 *
5105 * Return: 0 on success and errno on failure
5106 */
5107static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5108 uint32_t request_id,
5109 uint8_t *pattern_id)
5110{
5111 uint32_t i;
5112
5113 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5114 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5115 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5116 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5117 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5118 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5119 return 0;
5120 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5121 request_id) {
5122 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5123 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5124 return 0;
5125 }
5126 }
5127 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5128 return -EINVAL;
5129}
5130
5131/**
5132 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5133 * @hdd_ctx: HDD context
5134 * @request_id: [input] request id
5135 * @pattern_id: [output] pattern id
5136 *
5137 * This function loops through request id to pattern id array
5138 * reset request id to 0 (slot available again) and
5139 * return pattern id
5140 *
5141 * Return: 0 on success and errno on failure
5142 */
5143static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5144 uint32_t request_id,
5145 uint8_t *pattern_id)
5146{
5147 uint32_t i;
5148
5149 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5150 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5151 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5152 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5153 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5154 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5155 return 0;
5156 }
5157 }
5158 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5159 return -EINVAL;
5160}
5161
5162
5163/*
5164 * define short names for the global vendor params
5165 * used by __wlan_hdd_cfg80211_offloaded_packets()
5166 */
5167#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5168#define PARAM_REQUEST_ID \
5169 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5170#define PARAM_CONTROL \
5171 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5172#define PARAM_IP_PACKET \
5173 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5174#define PARAM_SRC_MAC_ADDR \
5175 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5176#define PARAM_DST_MAC_ADDR \
5177 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5178#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5179
5180/**
5181 * wlan_hdd_add_tx_ptrn() - add tx pattern
5182 * @adapter: adapter pointer
5183 * @hdd_ctx: hdd context
5184 * @tb: nl attributes
5185 *
5186 * This function reads the NL attributes and forms a AddTxPtrn message
5187 * posts it to SME.
5188 *
5189 */
5190static int
5191wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5192 struct nlattr **tb)
5193{
5194 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305195 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005196 uint32_t request_id, ret, len;
5197 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305198 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 uint16_t eth_type = htons(ETH_P_IP);
5200
5201 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005202 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 return -ENOTSUPP;
5204 }
5205
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305206 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005208 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209 return -ENOMEM;
5210 }
5211
5212 /* Parse and fetch request Id */
5213 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005214 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005215 goto fail;
5216 }
5217
5218 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5219 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005220 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005221 return -EINVAL;
5222 }
Jeff Johnson77848112016-06-29 14:52:06 -07005223 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224
5225 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005226 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227 goto fail;
5228 }
5229 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005230 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005232 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 goto fail;
5234 }
5235
5236 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005237 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238 goto fail;
5239 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005240 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305241 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005242 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005243 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005244
Anurag Chouhanc5548422016-02-24 18:33:27 +05305245 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005246 &adapter->macAddressCurrent)) {
5247 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248 goto fail;
5249 }
5250
5251 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005252 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253 goto fail;
5254 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305255 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005256 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 MAC_ADDR_ARRAY(dst_addr.bytes));
5258
5259 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005260 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005261 goto fail;
5262 }
5263 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005264 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265
5266 if (add_req->ucPtrnSize < 0 ||
5267 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5268 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005269 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005270 add_req->ucPtrnSize);
5271 goto fail;
5272 }
5273
5274 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305275 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305276 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305277 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305278 QDF_MAC_ADDR_SIZE);
5279 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305280 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 len += 2;
5282
5283 /*
5284 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5285 * ------------------------------------------------------------
5286 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5287 * ------------------------------------------------------------
5288 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305289 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005290 nla_data(tb[PARAM_IP_PACKET]),
5291 add_req->ucPtrnSize);
5292 add_req->ucPtrnSize += len;
5293
5294 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5295 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005296 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 goto fail;
5298 }
5299 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005300 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301
5302 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305303 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005304 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005305 goto fail;
5306 }
5307
5308 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305309 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005310 return 0;
5311
5312fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305313 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 return -EINVAL;
5315}
5316
5317/**
5318 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5319 * @adapter: adapter pointer
5320 * @hdd_ctx: hdd context
5321 * @tb: nl attributes
5322 *
5323 * This function reads the NL attributes and forms a DelTxPtrn message
5324 * posts it to SME.
5325 *
5326 */
5327static int
5328wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5329 struct nlattr **tb)
5330{
5331 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305332 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005333 uint32_t request_id, ret;
5334 uint8_t pattern_id = 0;
5335
5336 /* Parse and fetch request Id */
5337 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005338 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339 return -EINVAL;
5340 }
5341 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5342 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005343 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344 return -EINVAL;
5345 }
5346
5347 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5348 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005349 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005350 return -EINVAL;
5351 }
5352
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305353 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005355 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 return -ENOMEM;
5357 }
5358
Anurag Chouhanc5548422016-02-24 18:33:27 +05305359 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005360 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005362 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 request_id, del_req->ucPtrnId);
5364
5365 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305366 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005367 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368 goto fail;
5369 }
5370
5371 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305372 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 return 0;
5374
5375fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305376 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 return -EINVAL;
5378}
5379
5380
5381/**
5382 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5383 * @wiphy: Pointer to wireless phy
5384 * @wdev: Pointer to wireless device
5385 * @data: Pointer to data
5386 * @data_len: Data length
5387 *
5388 * Return: 0 on success, negative errno on failure
5389 */
5390static int
5391__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5392 struct wireless_dev *wdev,
5393 const void *data,
5394 int data_len)
5395{
5396 struct net_device *dev = wdev->netdev;
5397 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5398 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5399 struct nlattr *tb[PARAM_MAX + 1];
5400 uint8_t control;
5401 int ret;
5402 static const struct nla_policy policy[PARAM_MAX + 1] = {
5403 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5404 [PARAM_CONTROL] = { .type = NLA_U32 },
5405 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305406 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305408 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005409 [PARAM_PERIOD] = { .type = NLA_U32 },
5410 };
5411
Jeff Johnson1f61b612016-02-12 16:28:33 -08005412 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413
Anurag Chouhan6d760662016-02-20 16:05:43 +05305414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 hdd_err("Command not allowed in FTM mode");
5416 return -EPERM;
5417 }
5418
5419 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305420 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422
5423 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005424 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 return -ENOTSUPP;
5426 }
5427
5428 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005429 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 return -EINVAL;
5431 }
5432
5433 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005434 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435 return -EINVAL;
5436 }
5437 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005438 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439
5440 if (control == WLAN_START_OFFLOADED_PACKETS)
5441 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005442 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005444
5445 hdd_err("Invalid control: %d", control);
5446
5447 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005448}
5449
5450/*
5451 * done with short names for the global vendor params
5452 * used by __wlan_hdd_cfg80211_offloaded_packets()
5453 */
5454#undef PARAM_MAX
5455#undef PARAM_REQUEST_ID
5456#undef PARAM_CONTROL
5457#undef PARAM_IP_PACKET
5458#undef PARAM_SRC_MAC_ADDR
5459#undef PARAM_DST_MAC_ADDR
5460#undef PARAM_PERIOD
5461
5462/**
5463 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5464 * @wiphy: wiphy structure pointer
5465 * @wdev: Wireless device structure pointer
5466 * @data: Pointer to the data received
5467 * @data_len: Length of @data
5468 *
5469 * Return: 0 on success; errno on failure
5470 */
5471static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5472 struct wireless_dev *wdev,
5473 const void *data,
5474 int data_len)
5475{
5476 int ret = 0;
5477
5478 cds_ssr_protect(__func__);
5479 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5480 wdev, data, data_len);
5481 cds_ssr_unprotect(__func__);
5482
5483 return ret;
5484}
5485#endif
5486
5487/*
5488 * define short names for the global vendor params
5489 * used by __wlan_hdd_cfg80211_monitor_rssi()
5490 */
5491#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5492#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5493#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5494#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5495#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5496
5497/**
5498 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5499 * @wiphy: Pointer to wireless phy
5500 * @wdev: Pointer to wireless device
5501 * @data: Pointer to data
5502 * @data_len: Data length
5503 *
5504 * Return: 0 on success, negative errno on failure
5505 */
5506static int
5507__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5508 struct wireless_dev *wdev,
5509 const void *data,
5510 int data_len)
5511{
5512 struct net_device *dev = wdev->netdev;
5513 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5514 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5515 struct nlattr *tb[PARAM_MAX + 1];
5516 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305517 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 int ret;
5519 uint32_t control;
5520 static const struct nla_policy policy[PARAM_MAX + 1] = {
5521 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5522 [PARAM_CONTROL] = { .type = NLA_U32 },
5523 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5524 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5525 };
5526
Jeff Johnson1f61b612016-02-12 16:28:33 -08005527 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305529 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5530 hdd_err("invalid session id: %d", adapter->sessionId);
5531 return -EINVAL;
5532 }
5533
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005534 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305535 if (ret)
5536 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537
5538 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005539 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 return -ENOTSUPP;
5541 }
5542
5543 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005544 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005545 return -EINVAL;
5546 }
5547
5548 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005549 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 return -EINVAL;
5551 }
5552
5553 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005554 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555 return -EINVAL;
5556 }
5557
5558 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5559 req.session_id = adapter->sessionId;
5560 control = nla_get_u32(tb[PARAM_CONTROL]);
5561
5562 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5563 req.control = true;
5564 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005565 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 return -EINVAL;
5567 }
5568
5569 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005570 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 return -EINVAL;
5572 }
5573
5574 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5575 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5576
5577 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005578 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579 req.min_rssi, req.max_rssi);
5580 return -EINVAL;
5581 }
Jeff Johnson77848112016-06-29 14:52:06 -07005582 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583 req.min_rssi, req.max_rssi);
5584
5585 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5586 req.control = false;
5587 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005588 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 return -EINVAL;
5590 }
Jeff Johnson77848112016-06-29 14:52:06 -07005591 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592 req.request_id, req.session_id, req.control);
5593
5594 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305595 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005596 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005597 return -EINVAL;
5598 }
5599
5600 return 0;
5601}
5602
5603/*
5604 * done with short names for the global vendor params
5605 * used by __wlan_hdd_cfg80211_monitor_rssi()
5606 */
5607#undef PARAM_MAX
5608#undef PARAM_CONTROL
5609#undef PARAM_REQUEST_ID
5610#undef PARAM_MAX_RSSI
5611#undef PARAM_MIN_RSSI
5612
5613/**
5614 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5615 * @wiphy: wiphy structure pointer
5616 * @wdev: Wireless device structure pointer
5617 * @data: Pointer to the data received
5618 * @data_len: Length of @data
5619 *
5620 * Return: 0 on success; errno on failure
5621 */
5622static int
5623wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5624 const void *data, int data_len)
5625{
5626 int ret;
5627
5628 cds_ssr_protect(__func__);
5629 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5630 cds_ssr_unprotect(__func__);
5631
5632 return ret;
5633}
5634
5635/**
5636 * hdd_rssi_threshold_breached() - rssi breached NL event
5637 * @hddctx: HDD context
5638 * @data: rssi breached event data
5639 *
5640 * This function reads the rssi breached event %data and fill in the skb with
5641 * NL attributes and send up the NL event.
5642 *
5643 * Return: none
5644 */
5645void hdd_rssi_threshold_breached(void *hddctx,
5646 struct rssi_breach_event *data)
5647{
5648 hdd_context_t *hdd_ctx = hddctx;
5649 struct sk_buff *skb;
5650
5651 ENTER();
5652
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305653 if (wlan_hdd_validate_context(hdd_ctx))
5654 return;
5655 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005656 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005657 return;
5658 }
5659
5660 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5661 NULL,
5662 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5663 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5664 GFP_KERNEL);
5665
5666 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005667 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 return;
5669 }
5670
Jeff Johnson77848112016-06-29 14:52:06 -07005671 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005673 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005674 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5675
5676 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5677 data->request_id) ||
5678 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5679 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5680 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5681 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005682 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005683 goto fail;
5684 }
5685
5686 cfg80211_vendor_event(skb, GFP_KERNEL);
5687 return;
5688
5689fail:
5690 kfree_skb(skb);
5691 return;
5692}
5693
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305694static const struct nla_policy
5695ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5696 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5697};
5698
5699/**
5700 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5701 * @wiphy: Pointer to wireless phy
5702 * @wdev: Pointer to wireless device
5703 * @data: Pointer to data
5704 * @data_len: Length of @data
5705 *
5706 * Return: 0 on success, negative errno on failure
5707 */
5708static int
5709__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5710 struct wireless_dev *wdev,
5711 const void *data, int data_len)
5712{
5713 int status;
5714 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5715 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005716 struct net_device *dev = wdev->netdev;
5717 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305718
5719 ENTER_DEV(wdev->netdev);
5720
5721 status = wlan_hdd_validate_context(pHddCtx);
5722 if (0 != status)
5723 return status;
5724 if (!pHddCtx->config->fhostNSOffload) {
5725 hdd_err("ND Offload not supported");
5726 return -EINVAL;
5727 }
5728
5729 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5730 (struct nlattr *)data,
5731 data_len, ns_offload_set_policy)) {
5732 hdd_err("nla_parse failed");
5733 return -EINVAL;
5734 }
5735
5736 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5737 hdd_err("ND Offload flag attribute not present");
5738 return -EINVAL;
5739 }
5740
5741 pHddCtx->ns_offload_enable =
5742 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5743
Dustin Brownd8279d22016-09-07 14:52:57 -07005744 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305745 if (pHddCtx->ns_offload_enable)
5746 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5747 else
5748 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005749
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305750 return 0;
5751}
5752
5753/**
5754 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5755 * @wiphy: pointer to wireless wiphy structure.
5756 * @wdev: pointer to wireless_dev structure.
5757 * @data: Pointer to the data to be passed via vendor interface
5758 * @data_len:Length of the data to be passed
5759 *
5760 * Return: Return the Success or Failure code.
5761 */
5762static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5763 struct wireless_dev *wdev,
5764 const void *data, int data_len)
5765{
5766 int ret;
5767
5768 cds_ssr_protect(__func__);
5769 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5770 cds_ssr_unprotect(__func__);
5771
5772 return ret;
5773}
5774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005775/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5776 * @wiphy: Pointer to wireless phy
5777 * @wdev: Pointer to wireless device
5778 * @data: Pointer to data
5779 * @data_len: Data length
5780 *
5781 * This function return the preferred frequency list generated by the policy
5782 * manager.
5783 *
5784 * Return: success or failure code
5785 */
5786static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5787 struct wireless_dev
5788 *wdev, const void *data,
5789 int data_len)
5790{
5791 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5792 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305793 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305794 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305796 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797 enum cds_con_mode intf_mode;
5798 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5799 struct sk_buff *reply_skb;
5800
Jeff Johnson1f61b612016-02-12 16:28:33 -08005801 ENTER_DEV(wdev->netdev);
5802
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803 ret = wlan_hdd_validate_context(hdd_ctx);
5804 if (ret)
5805 return -EINVAL;
5806
5807 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5808 data, data_len, NULL)) {
5809 hdd_err("Invalid ATTR");
5810 return -EINVAL;
5811 }
5812
5813 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5814 hdd_err("attr interface type failed");
5815 return -EINVAL;
5816 }
5817
5818 intf_mode = nla_get_u32(tb
5819 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5820
5821 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5822 hdd_err("Invalid interface type");
5823 return -EINVAL;
5824 }
5825
5826 hdd_debug("Userspace requested pref freq list");
5827
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305828 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5829 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305830 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831 hdd_err("Get pcl failed");
5832 return -EINVAL;
5833 }
5834
5835 /* convert channel number to frequency */
5836 for (i = 0; i < pcl_len; i++) {
5837 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5838 freq_list[i] =
5839 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005840 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 else
5842 freq_list[i] =
5843 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005844 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845 }
5846
5847 /* send the freq_list back to supplicant */
5848 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5849 sizeof(u32) *
5850 pcl_len +
5851 NLMSG_HDRLEN);
5852
5853 if (!reply_skb) {
5854 hdd_err("Allocate reply_skb failed");
5855 return -EINVAL;
5856 }
5857
5858 if (nla_put_u32(reply_skb,
5859 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5860 intf_mode) ||
5861 nla_put(reply_skb,
5862 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5863 sizeof(uint32_t) * pcl_len,
5864 freq_list)) {
5865 hdd_err("nla put fail");
5866 kfree_skb(reply_skb);
5867 return -EINVAL;
5868 }
5869
5870 return cfg80211_vendor_cmd_reply(reply_skb);
5871}
5872
5873/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5874 * @wiphy: Pointer to wireless phy
5875 * @wdev: Pointer to wireless device
5876 * @data: Pointer to data
5877 * @data_len: Data length
5878 *
5879 * This function return the preferred frequency list generated by the policy
5880 * manager.
5881 *
5882 * Return: success or failure code
5883 */
5884static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5885 struct wireless_dev
5886 *wdev, const void *data,
5887 int data_len)
5888{
5889 int ret = 0;
5890
5891 cds_ssr_protect(__func__);
5892 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5893 data, data_len);
5894 cds_ssr_unprotect(__func__);
5895
5896 return ret;
5897}
5898
5899/**
5900 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5901 * @wiphy: Pointer to wireless phy
5902 * @wdev: Pointer to wireless device
5903 * @data: Pointer to data
5904 * @data_len: Data length
5905 *
5906 * Return: 0 on success, negative errno on failure
5907 */
5908static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5909 struct wireless_dev *wdev,
5910 const void *data,
5911 int data_len)
5912{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305913 struct net_device *ndev = wdev->netdev;
5914 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5916 int ret = 0;
5917 enum cds_con_mode intf_mode;
5918 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5919 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920
Jeff Johnson1f61b612016-02-12 16:28:33 -08005921 ENTER_DEV(ndev);
5922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005923 ret = wlan_hdd_validate_context(hdd_ctx);
5924 if (ret)
5925 return ret;
5926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5928 data, data_len, NULL)) {
5929 hdd_err("Invalid ATTR");
5930 return -EINVAL;
5931 }
5932
5933 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5934 hdd_err("attr interface type failed");
5935 return -EINVAL;
5936 }
5937
5938 intf_mode = nla_get_u32(tb
5939 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5940
5941 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5942 hdd_err("Invalid interface type");
5943 return -EINVAL;
5944 }
5945
5946 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5947 hdd_err("attr probable freq failed");
5948 return -EINVAL;
5949 }
5950
5951 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5952 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5953
5954 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005955 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005956 channel_hint, HW_MODE_20_MHZ)) {
5957 hdd_err("Set channel hint failed due to concurrency check");
5958 return -EINVAL;
5959 }
5960
Krunal Soni09e55032016-06-07 10:06:55 -07005961 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5962 hdd_warn("Remain On Channel Pending");
5963
Krunal Soni3091bcc2016-06-23 12:28:21 -07005964 ret = qdf_reset_connection_update();
5965 if (!QDF_IS_STATUS_SUCCESS(ret))
5966 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967
Krunal Soni3091bcc2016-06-23 12:28:21 -07005968 ret = cds_current_connections_update(adapter->sessionId,
5969 channel_hint,
5970 SIR_UPDATE_REASON_SET_OPER_CHAN);
5971 if (QDF_STATUS_E_FAILURE == ret) {
5972 /* return in the failure case */
5973 hdd_err("ERROR: connections update failed!!");
5974 return -EINVAL;
5975 }
5976
5977 if (QDF_STATUS_SUCCESS == ret) {
5978 /*
5979 * Success is the only case for which we expect hw mode
5980 * change to take place, hence we need to wait.
5981 * For any other return value it should be a pass
5982 * through
5983 */
5984 ret = qdf_wait_for_connection_update();
5985 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5986 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987 return -EINVAL;
5988 }
5989
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005990 }
5991
5992 return 0;
5993}
5994
5995/**
5996 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5997 * @wiphy: Pointer to wireless phy
5998 * @wdev: Pointer to wireless device
5999 * @data: Pointer to data
6000 * @data_len: Data length
6001 *
6002 * Return: 0 on success, negative errno on failure
6003 */
6004static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6005 struct wireless_dev *wdev,
6006 const void *data,
6007 int data_len)
6008{
6009 int ret = 0;
6010
6011 cds_ssr_protect(__func__);
6012 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6013 data, data_len);
6014 cds_ssr_unprotect(__func__);
6015
6016 return ret;
6017}
6018
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306019static const struct
6020nla_policy
6021qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6022 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6023};
6024
6025/**
6026 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6027 * @wiphy: WIPHY structure pointer
6028 * @wdev: Wireless device structure pointer
6029 * @data: Pointer to the data received
6030 * @data_len: Length of the data received
6031 *
6032 * This function is used to get link properties like nss, rate flags and
6033 * operating frequency for the active connection with the given peer.
6034 *
6035 * Return: 0 on success and errno on failure
6036 */
6037static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6038 struct wireless_dev *wdev,
6039 const void *data,
6040 int data_len)
6041{
6042 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6043 struct net_device *dev = wdev->netdev;
6044 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6045 hdd_station_ctx_t *hdd_sta_ctx;
6046 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306047 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306048 uint32_t sta_id;
6049 struct sk_buff *reply_skb;
6050 uint32_t rate_flags = 0;
6051 uint8_t nss;
6052 uint8_t final_rate_flags = 0;
6053 uint32_t freq;
6054
Jeff Johnson1f61b612016-02-12 16:28:33 -08006055 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306056
Anurag Chouhan6d760662016-02-20 16:05:43 +05306057 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306058 hdd_err("Command not allowed in FTM mode");
6059 return -EPERM;
6060 }
6061
6062 if (0 != wlan_hdd_validate_context(hdd_ctx))
6063 return -EINVAL;
6064
6065 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6066 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006067 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306068 return -EINVAL;
6069 }
6070
6071 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006072 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306073 adapter->device_mode);
6074 return -EINVAL;
6075 }
6076
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306077 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306078 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006079 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306080 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6081
Krunal Sonib4326f22016-03-10 13:05:51 -08006082 if (adapter->device_mode == QDF_STA_MODE ||
6083 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306084 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6085 if ((hdd_sta_ctx->conn_info.connState !=
6086 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306087 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306088 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006089 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306090 MAC_ADDR_ARRAY(peer_mac));
6091 return -EINVAL;
6092 }
6093
6094 nss = hdd_sta_ctx->conn_info.nss;
6095 freq = cds_chan_to_freq(
6096 hdd_sta_ctx->conn_info.operationChannel);
6097 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006098 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6099 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306100
6101 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6102 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306103 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306104 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306105 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306106 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306107 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306108 break;
6109 }
6110
6111 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006112 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306113 MAC_ADDR_ARRAY(peer_mac));
6114 return -EINVAL;
6115 }
6116
6117 nss = adapter->aStaInfo[sta_id].nss;
6118 freq = cds_chan_to_freq(
6119 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6120 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6121 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006122 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306123 MAC_ADDR_ARRAY(peer_mac));
6124 return -EINVAL;
6125 }
6126
6127 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6128 if (rate_flags & eHAL_TX_RATE_VHT80) {
6129 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006130#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306131 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006132#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306133 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6134 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006135#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306136 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006137#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306138 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6139 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6140 } else if (rate_flags &
6141 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6142 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006143#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306144 if (rate_flags & eHAL_TX_RATE_HT40)
6145 final_rate_flags |=
6146 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006147#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306148 }
6149
6150 if (rate_flags & eHAL_TX_RATE_SGI) {
6151 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6152 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6153 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6154 }
6155 }
6156
6157 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6158 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6159
6160 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006161 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306162 return -EINVAL;
6163 }
6164
6165 if (nla_put_u8(reply_skb,
6166 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6167 nss) ||
6168 nla_put_u8(reply_skb,
6169 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6170 final_rate_flags) ||
6171 nla_put_u32(reply_skb,
6172 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6173 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006174 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306175 kfree_skb(reply_skb);
6176 return -EINVAL;
6177 }
6178
6179 return cfg80211_vendor_cmd_reply(reply_skb);
6180}
6181
6182/**
6183 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6184 * properties.
6185 * @wiphy: WIPHY structure pointer
6186 * @wdev: Wireless device structure pointer
6187 * @data: Pointer to the data received
6188 * @data_len: Length of the data received
6189 *
6190 * This function is used to get link properties like nss, rate flags and
6191 * operating frequency for the active connection with the given peer.
6192 *
6193 * Return: 0 on success and errno on failure
6194 */
6195static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6196 struct wireless_dev *wdev,
6197 const void *data,
6198 int data_len)
6199{
6200 int ret = 0;
6201
6202 cds_ssr_protect(__func__);
6203 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6204 wdev, data, data_len);
6205 cds_ssr_unprotect(__func__);
6206
6207 return ret;
6208}
6209
Peng Xu278d0122015-09-24 16:34:17 -07006210static const struct
6211nla_policy
6212qca_wlan_vendor_ota_test_policy
6213[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6214 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6215};
6216
6217/**
6218 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6219 * @wiphy: Pointer to wireless phy
6220 * @wdev: Pointer to wireless device
6221 * @data: Pointer to data
6222 * @data_len: Data length
6223 *
6224 * Return: 0 on success, negative errno on failure
6225 */
6226static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6227 struct wireless_dev *wdev,
6228 const void *data,
6229 int data_len)
6230{
6231 struct net_device *dev = wdev->netdev;
6232 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6233 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6234 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6235 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6236 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306237 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006238 uint32_t current_roam_state;
6239
Jeff Johnson1f61b612016-02-12 16:28:33 -08006240 ENTER_DEV(dev);
6241
Anurag Chouhan6d760662016-02-20 16:05:43 +05306242 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006243 hdd_err("Command not allowed in FTM mode");
6244 return -EPERM;
6245 }
6246
6247 if (0 != wlan_hdd_validate_context(hdd_ctx))
6248 return -EINVAL;
6249
6250 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6251 data, data_len,
6252 qca_wlan_vendor_ota_test_policy)) {
6253 hdd_err("invalid attr");
6254 return -EINVAL;
6255 }
6256
6257 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6258 hdd_err("attr ota test failed");
6259 return -EINVAL;
6260 }
6261
6262 ota_enable = nla_get_u8(
6263 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6264
6265 hdd_info(" OTA test enable = %d", ota_enable);
6266 if (ota_enable != 1) {
6267 hdd_err("Invalid value, only enable test mode is supported!");
6268 return -EINVAL;
6269 }
6270
6271 current_roam_state =
6272 sme_get_current_roam_state(hal, adapter->sessionId);
6273 status = sme_stop_roaming(hal, adapter->sessionId,
6274 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306275 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006276 hdd_err("Enable/Disable roaming failed");
6277 return -EINVAL;
6278 }
6279
6280 status = sme_ps_enable_disable(hal, adapter->sessionId,
6281 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306282 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006283 hdd_err("Enable/Disable power save failed");
6284 /* restore previous roaming setting */
6285 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6286 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6287 status = sme_start_roaming(hal, adapter->sessionId,
6288 eCsrHddIssued);
6289 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6290 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6291 status = sme_stop_roaming(hal, adapter->sessionId,
6292 eCsrHddIssued);
6293
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306294 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006295 hdd_err("Restoring roaming state failed");
6296
6297 return -EINVAL;
6298 }
6299
6300
6301 return 0;
6302}
6303
6304/**
6305 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6306 * @wiphy: Pointer to wireless phy
6307 * @wdev: Pointer to wireless device
6308 * @data: Pointer to data
6309 * @data_len: Data length
6310 *
6311 * Return: 0 on success, negative errno on failure
6312 */
6313static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6314 struct wireless_dev *wdev,
6315 const void *data,
6316 int data_len)
6317{
6318 int ret = 0;
6319
6320 cds_ssr_protect(__func__);
6321 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6322 cds_ssr_unprotect(__func__);
6323
6324 return ret;
6325}
6326
Peng Xu4d67c8f2015-10-16 16:02:26 -07006327/**
6328 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6329 * @wiphy: Pointer to wireless phy
6330 * @wdev: Pointer to wireless device
6331 * @data: Pointer to data
6332 * @data_len: Data length
6333 *
6334 * Return: 0 on success, negative errno on failure
6335 */
6336static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6337 struct wireless_dev *wdev,
6338 const void *data,
6339 int data_len)
6340{
6341 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6342 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006343 hdd_adapter_t *adapter;
6344 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006345 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6346 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006347 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006348
Jeff Johnson1f61b612016-02-12 16:28:33 -08006349 ENTER_DEV(dev);
6350
Peng Xu4d67c8f2015-10-16 16:02:26 -07006351 ret = wlan_hdd_validate_context(hdd_ctx);
6352 if (ret)
6353 return ret;
6354
6355 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6356
6357 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6358 data, data_len, NULL)) {
6359 hdd_err("Invalid ATTR");
6360 return -EINVAL;
6361 }
6362
6363 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6364 hdd_err("attr tx power scale failed");
6365 return -EINVAL;
6366 }
6367
6368 scale_value = nla_get_u8(tb
6369 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6370
6371 if (scale_value > MAX_TXPOWER_SCALE) {
6372 hdd_err("Invalid tx power scale level");
6373 return -EINVAL;
6374 }
6375
Peng Xu62c8c432016-05-09 15:23:02 -07006376 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006377
Peng Xu62c8c432016-05-09 15:23:02 -07006378 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006379 hdd_err("Set tx power scale failed");
6380 return -EINVAL;
6381 }
6382
6383 return 0;
6384}
6385
6386/**
6387 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6388 * @wiphy: Pointer to wireless phy
6389 * @wdev: Pointer to wireless device
6390 * @data: Pointer to data
6391 * @data_len: Data length
6392 *
6393 * Return: 0 on success, negative errno on failure
6394 */
6395static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6396 struct wireless_dev *wdev,
6397 const void *data,
6398 int data_len)
6399{
Peng Xu62c8c432016-05-09 15:23:02 -07006400 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006401
6402 cds_ssr_protect(__func__);
6403 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6404 data, data_len);
6405 cds_ssr_unprotect(__func__);
6406
6407 return ret;
6408}
6409
6410/**
6411 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6412 * @wiphy: Pointer to wireless phy
6413 * @wdev: Pointer to wireless device
6414 * @data: Pointer to data
6415 * @data_len: Data length
6416 *
6417 * Return: 0 on success, negative errno on failure
6418 */
6419static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6420 struct wireless_dev *wdev,
6421 const void *data,
6422 int data_len)
6423{
6424 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6425 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006426 hdd_adapter_t *adapter;
6427 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006428 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6429 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006430 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006431
Jeff Johnson1f61b612016-02-12 16:28:33 -08006432 ENTER_DEV(dev);
6433
Peng Xu4d67c8f2015-10-16 16:02:26 -07006434 ret = wlan_hdd_validate_context(hdd_ctx);
6435 if (ret)
6436 return ret;
6437
6438 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6439
6440 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6441 data, data_len, NULL)) {
6442 hdd_err("Invalid ATTR");
6443 return -EINVAL;
6444 }
6445
6446 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6447 hdd_err("attr tx power decrease db value failed");
6448 return -EINVAL;
6449 }
6450
6451 scale_value = nla_get_u8(tb
6452 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6453
Peng Xu62c8c432016-05-09 15:23:02 -07006454 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6455 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006456
Peng Xu62c8c432016-05-09 15:23:02 -07006457 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006458 hdd_err("Set tx power decrease db failed");
6459 return -EINVAL;
6460 }
6461
6462 return 0;
6463}
6464
6465/**
6466 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6467 * @wiphy: Pointer to wireless phy
6468 * @wdev: Pointer to wireless device
6469 * @data: Pointer to data
6470 * @data_len: Data length
6471 *
6472 * Return: 0 on success, negative errno on failure
6473 */
6474static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6475 struct wireless_dev *wdev,
6476 const void *data,
6477 int data_len)
6478{
Peng Xu62c8c432016-05-09 15:23:02 -07006479 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006480
6481 cds_ssr_protect(__func__);
6482 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6483 data, data_len);
6484 cds_ssr_unprotect(__func__);
6485
6486 return ret;
6487}
Peng Xu8fdaa492016-06-22 10:20:47 -07006488
6489/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306490 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6491 * @wiphy: Pointer to wireless phy
6492 * @wdev: Pointer to wireless device
6493 * @data: Pointer to data
6494 * @data_len: Data length
6495 *
6496 * Processes the conditional channel switch request and invokes the helper
6497 * APIs to process the channel switch request.
6498 *
6499 * Return: 0 on success, negative errno on failure
6500 */
6501static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6502 struct wireless_dev *wdev,
6503 const void *data,
6504 int data_len)
6505{
6506 int ret;
6507 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6508 struct net_device *dev = wdev->netdev;
6509 hdd_adapter_t *adapter;
6510 struct nlattr
6511 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6512 uint32_t freq_len, i;
6513 uint32_t *freq;
6514 uint8_t chans[QDF_MAX_NUM_CHAN];
6515
6516 ENTER_DEV(dev);
6517
6518 ret = wlan_hdd_validate_context(hdd_ctx);
6519 if (ret)
6520 return ret;
6521
6522 if (!hdd_ctx->config->enableDFSMasterCap) {
6523 hdd_err("DFS master capability is not present in the driver");
6524 return -EINVAL;
6525 }
6526
6527 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6528 hdd_err("Command not allowed in FTM mode");
6529 return -EPERM;
6530 }
6531
6532 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6533 if (adapter->device_mode != QDF_SAP_MODE) {
6534 hdd_err("Invalid device mode %d", adapter->device_mode);
6535 return -EINVAL;
6536 }
6537
6538 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6539 data, data_len, NULL)) {
6540 hdd_err("Invalid ATTR");
6541 return -EINVAL;
6542 }
6543
6544 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6545 hdd_err("Frequency list is missing");
6546 return -EINVAL;
6547 }
6548
6549 freq_len = nla_len(
6550 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6551 sizeof(uint32_t);
6552
6553 if (freq_len > QDF_MAX_NUM_CHAN) {
6554 hdd_err("insufficient space to hold channels");
6555 return -ENOMEM;
6556 }
6557
6558 hdd_debug("freq_len=%d", freq_len);
6559
6560 freq = nla_data(
6561 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6562
6563
6564 for (i = 0; i < freq_len; i++) {
6565 if (freq[i] == 0)
6566 chans[i] = 0;
6567 else
6568 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6569
6570 hdd_debug("freq[%d]=%d", i, freq[i]);
6571 }
6572
6573 /*
6574 * The input frequency list from user space is designed to be a
6575 * priority based frequency list. This is only to accommodate any
6576 * future request. But, current requirement is only to perform CAC
6577 * on a single channel. So, the first entry from the list is picked.
6578 *
6579 * If channel is zero, any channel in the available outdoor regulatory
6580 * domain will be selected.
6581 */
6582 ret = wlan_hdd_request_pre_cac(chans[0]);
6583 if (ret) {
6584 hdd_err("pre cac request failed with reason:%d", ret);
6585 return ret;
6586 }
6587
6588 return 0;
6589}
6590
6591/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006592 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6593 * @wiphy: Pointer to wireless phy
6594 * @wdev: Pointer to wireless device
6595 * @data: Pointer to data
6596 * @data_len: Data length
6597 *
6598 * This function is to process the p2p listen offload start vendor
6599 * command. It parses the input parameters and invoke WMA API to
6600 * send the command to firmware.
6601 *
6602 * Return: 0 on success, negative errno on failure
6603 */
6604static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6605 struct wireless_dev *wdev,
6606 const void *data,
6607 int data_len)
6608{
6609 int ret;
6610 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6611 struct net_device *dev = wdev->netdev;
6612 hdd_adapter_t *adapter;
6613 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6614 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006615
6616 ENTER_DEV(dev);
6617
6618 ret = wlan_hdd_validate_context(hdd_ctx);
6619 if (ret)
6620 return ret;
6621
6622 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6623 hdd_err("Command not allowed in FTM mode");
6624 return -EPERM;
6625 }
6626
6627 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6628 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6629 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6630 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6631 hdd_err("Invalid device mode %d", adapter->device_mode);
6632 return -EINVAL;
6633 }
6634
6635 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6636 data, data_len, NULL)) {
6637 hdd_err("Invalid ATTR");
6638 return -EINVAL;
6639 }
6640
6641 memset(&params, 0, sizeof(params));
6642
6643 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6644 params.ctl_flags = 1; /* set to default value */
6645 else
6646 params.ctl_flags = nla_get_u32(tb
6647 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6648
6649 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6650 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6651 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6652 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6653 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6654 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6655 hdd_err("Attribute parsing failed");
6656 return -EINVAL;
6657 }
6658
6659 params.vdev_id = adapter->sessionId;
6660 params.freq = nla_get_u32(tb
6661 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6662 if ((params.freq != 2412) && (params.freq != 2437) &&
6663 (params.freq != 2462)) {
6664 hdd_err("Invalid listening channel: %d", params.freq);
6665 return -EINVAL;
6666 }
6667
6668 params.period = nla_get_u32(tb
6669 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6670 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6671 hdd_err("Invalid period: %d", params.period);
6672 return -EINVAL;
6673 }
6674
6675 params.interval = nla_get_u32(tb
6676 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6677 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6678 hdd_err("Invalid interval: %d", params.interval);
6679 return -EINVAL;
6680 }
6681
6682 params.count = nla_get_u32(tb
6683 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006684 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006685 hdd_err("Invalid count: %d", params.count);
6686 return -EINVAL;
6687 }
6688
6689 params.device_types = nla_data(tb
6690 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6691 if (params.device_types == NULL) {
6692 hdd_err("Invalid device types");
6693 return -EINVAL;
6694 }
6695
6696 params.dev_types_len = nla_len(tb
6697 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6698 if (params.dev_types_len < 8) {
6699 hdd_err("Invalid device type length: %d", params.dev_types_len);
6700 return -EINVAL;
6701 }
6702
6703 params.probe_resp_tmplt = nla_data(tb
6704 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6705 if (params.probe_resp_tmplt == NULL) {
6706 hdd_err("Invalid probe response template");
6707 return -EINVAL;
6708 }
6709
6710 params.probe_resp_len = nla_len(tb
6711 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6712 if (params.probe_resp_len == 0) {
6713 hdd_err("Invalid probe resp template length: %d",
6714 params.probe_resp_len);
6715 return -EINVAL;
6716 }
6717
6718 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6719 params.freq, params.period, params.interval, params.count);
6720
Wu Gao9a704f42017-03-10 18:42:11 +08006721 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006722}
6723
6724
6725/**
6726 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6727 * @wiphy: Pointer to wireless phy
6728 * @wdev: Pointer to wireless device
6729 * @data: Pointer to data
6730 * @data_len: Data length
6731 *
6732 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6733 * to process p2p listen offload start vendor command.
6734 *
6735 * Return: 0 on success, negative errno on failure
6736 */
6737static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6738 struct wireless_dev *wdev,
6739 const void *data,
6740 int data_len)
6741{
6742 int ret = 0;
6743
6744 cds_ssr_protect(__func__);
6745 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6746 data, data_len);
6747 cds_ssr_unprotect(__func__);
6748
6749 return ret;
6750}
6751
6752/**
6753 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6754 * @wiphy: Pointer to wireless phy
6755 * @wdev: Pointer to wireless device
6756 * @data: Pointer to data
6757 * @data_len: Data length
6758 *
6759 * This function is to process the p2p listen offload stop vendor
6760 * command. It invokes WMA API to send command to firmware.
6761 *
6762 * Return: 0 on success, negative errno on failure
6763 */
6764static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6765 struct wireless_dev *wdev,
6766 const void *data,
6767 int data_len)
6768{
Peng Xu8fdaa492016-06-22 10:20:47 -07006769 hdd_adapter_t *adapter;
6770 struct net_device *dev = wdev->netdev;
6771
6772 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6773 hdd_err("Command not allowed in FTM mode");
6774 return -EPERM;
6775 }
6776
6777 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6778 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6779 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6780 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6781 hdd_err("Invalid device mode");
6782 return -EINVAL;
6783 }
6784
Wu Gao9a704f42017-03-10 18:42:11 +08006785 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006786}
6787
6788/**
6789 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6790 * @wiphy: Pointer to wireless phy
6791 * @wdev: Pointer to wireless device
6792 * @data: Pointer to data
6793 * @data_len: Data length
6794 *
6795 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6796 * to process p2p listen offload stop vendor command.
6797 *
6798 * Return: 0 on success, negative errno on failure
6799 */
6800static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6801 struct wireless_dev *wdev,
6802 const void *data,
6803 int data_len)
6804{
6805 int ret = 0;
6806
6807 cds_ssr_protect(__func__);
6808 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6809 data, data_len);
6810 cds_ssr_unprotect(__func__);
6811
6812 return ret;
6813}
6814
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306815/**
6816 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6817 * @wiphy: Pointer to wireless phy
6818 * @wdev: Pointer to wireless device
6819 * @data: Pointer to data
6820 * @data_len: Data length
6821 *
6822 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6823 * to process the conditional channel switch request.
6824 *
6825 * Return: 0 on success, negative errno on failure
6826 */
6827static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6828 struct wireless_dev *wdev,
6829 const void *data,
6830 int data_len)
6831{
6832 int ret;
6833
6834 cds_ssr_protect(__func__);
6835 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6836 data, data_len);
6837 cds_ssr_unprotect(__func__);
6838
6839 return ret;
6840}
6841
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306842/*
6843 * define short names for the global vendor params
6844 * used by __wlan_hdd_cfg80211_bpf_offload()
6845 */
6846#define BPF_INVALID \
6847 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6848#define BPF_SET_RESET \
6849 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6850#define BPF_VERSION \
6851 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6852#define BPF_FILTER_ID \
6853 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6854#define BPF_PACKET_SIZE \
6855 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6856#define BPF_CURRENT_OFFSET \
6857 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6858#define BPF_PROGRAM \
6859 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6860#define BPF_MAX \
6861 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006862
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306863static const struct nla_policy
6864wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6865 [BPF_SET_RESET] = {.type = NLA_U32},
6866 [BPF_VERSION] = {.type = NLA_U32},
6867 [BPF_FILTER_ID] = {.type = NLA_U32},
6868 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6869 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6870 [BPF_PROGRAM] = {.type = NLA_U8},
6871};
6872
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006873struct bpf_offload_priv {
6874 struct sir_bpf_get_offload bpf_get_offload;
6875};
6876
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306877/**
6878 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006879 * @context: opaque context originally passed to SME. HDD always passes
6880 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306881 * @bpf_get_offload: struct for get offload
6882 *
6883 * This function receives the response/data from the lower layer and
6884 * checks to see if the thread is still waiting then post the results to
6885 * upper layer, if the request has timed out then ignore.
6886 *
6887 * Return: None
6888 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006889static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006890 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306891{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006892 struct hdd_request *request;
6893 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306894
6895 ENTER();
6896
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006897 request = hdd_request_get(context);
6898 if (!request) {
6899 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306900 return;
6901 }
6902
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006903 priv = hdd_request_priv(request);
6904 priv->bpf_get_offload = *data;
6905 hdd_request_complete(request);
6906 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306907}
6908
6909/**
6910 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6911 * @hdd_context: hdd_context
6912 * @bpf_get_offload: struct for get offload
6913 *
6914 * Return: 0 on success, error number otherwise.
6915 */
6916static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6917 struct sir_bpf_get_offload *bpf_get_offload)
6918{
6919 struct sk_buff *skb;
6920 uint32_t nl_buf_len;
6921
6922 ENTER();
6923
6924 nl_buf_len = NLMSG_HDRLEN;
6925 nl_buf_len +=
6926 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6927 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6928
6929 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6930 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006931 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306932 return -ENOMEM;
6933 }
6934
Jeff Johnson77848112016-06-29 14:52:06 -07006935 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306936 bpf_get_offload->bpf_version,
6937 bpf_get_offload->max_bytes_for_bpf_inst);
6938
6939 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6940 bpf_get_offload->max_bytes_for_bpf_inst) ||
6941 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006942 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306943 goto nla_put_failure;
6944 }
6945
6946 cfg80211_vendor_cmd_reply(skb);
6947 EXIT();
6948 return 0;
6949
6950nla_put_failure:
6951 kfree_skb(skb);
6952 return -EINVAL;
6953}
6954
6955/**
6956 * hdd_get_bpf_offload - Get BPF offload Capabilities
6957 * @hdd_ctx: Hdd context
6958 *
6959 * Return: 0 on success, errno on failure
6960 */
6961static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6962{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306963 QDF_STATUS status;
6964 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006965 void *cookie;
6966 struct hdd_request *request;
6967 struct bpf_offload_priv *priv;
6968 static const struct hdd_request_params params = {
6969 .priv_size = sizeof(*priv),
6970 .timeout_ms = WLAN_WAIT_TIME_BPF,
6971 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306972
6973 ENTER();
6974
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006975 request = hdd_request_alloc(&params);
6976 if (!request) {
6977 hdd_err("Unable to allocate request");
6978 return -EINVAL;
6979 }
6980 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306981
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006982 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6983 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006984 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306985 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006986 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006987 ret = qdf_status_to_os_return(status);
6988 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306989 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006990 ret = hdd_request_wait_for_response(request);
6991 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006992 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006993 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306994 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006995 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306996 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006997 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306998 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006999 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007001cleanup:
7002 /*
7003 * either we never sent a request to SME, we sent a request to
7004 * SME and timed out, or we sent a request to SME, received a
7005 * response from SME, and posted the response to userspace.
7006 * regardless we are done with the request.
7007 */
7008 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307009 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007010
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307011 return ret;
7012}
7013
7014/**
7015 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7016 * @hdd_ctx: Hdd context
7017 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307018 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307019 *
7020 * Return: 0 on success; errno on failure
7021 */
7022static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7023 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307024 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307025{
7026 struct sir_bpf_set_offload *bpf_set_offload;
7027 QDF_STATUS status;
7028 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307029 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307030
7031 ENTER();
7032
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307033 if (adapter->device_mode == QDF_STA_MODE ||
7034 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7035 if (!hdd_conn_is_connected(
7036 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7037 hdd_err("Not in Connected state!");
7038 return -ENOTSUPP;
7039 }
7040 }
7041
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307042 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7043 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007044 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307045 return -ENOMEM;
7046 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307047
7048 /* Parse and fetch bpf packet size */
7049 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007050 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307051 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307052 goto fail;
7053 }
7054 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7055
7056 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007057 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307058 goto post_sme;
7059 }
7060
7061 /* Parse and fetch bpf program */
7062 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007063 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307064 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307065 goto fail;
7066 }
7067
7068 prog_len = nla_len(tb[BPF_PROGRAM]);
7069 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307070
7071 if (bpf_set_offload->program == NULL) {
7072 hdd_err("qdf_mem_malloc failed for bpf offload program");
7073 ret = -ENOMEM;
7074 goto fail;
7075 }
7076
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307077 bpf_set_offload->current_length = prog_len;
7078 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307079 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307080
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307081 hdd_info("BPF set instructions");
7082 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7083 bpf_set_offload->program, prog_len);
7084
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307085 /* Parse and fetch filter Id */
7086 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007087 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307088 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307089 goto fail;
7090 }
7091 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7092
7093 /* Parse and fetch current offset */
7094 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007095 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307096 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307097 goto fail;
7098 }
7099 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7100
7101post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007102 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 +05307103 bpf_set_offload->session_id,
7104 bpf_set_offload->version,
7105 bpf_set_offload->filter_id,
7106 bpf_set_offload->total_length,
7107 bpf_set_offload->current_length,
7108 bpf_set_offload->current_offset);
7109
7110 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7111 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007112 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307113 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307114 goto fail;
7115 }
7116 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307117
7118fail:
7119 if (bpf_set_offload->current_length)
7120 qdf_mem_free(bpf_set_offload->program);
7121 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307122 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307123}
7124
7125/**
7126 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7127 * @wiphy: wiphy structure pointer
7128 * @wdev: Wireless device structure pointer
7129 * @data: Pointer to the data received
7130 * @data_len: Length of @data
7131 *
7132 * Return: 0 on success; errno on failure
7133 */
7134static int
7135__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7136 struct wireless_dev *wdev,
7137 const void *data, int data_len)
7138{
7139 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7140 struct net_device *dev = wdev->netdev;
7141 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7142 struct nlattr *tb[BPF_MAX + 1];
7143 int ret_val, packet_filter_subcmd;
7144
7145 ENTER();
7146
7147 ret_val = wlan_hdd_validate_context(hdd_ctx);
7148 if (ret_val)
7149 return ret_val;
7150
7151 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007152 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307153 return -EINVAL;
7154 }
7155
7156 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007157 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307158 return -ENOTSUPP;
7159 }
7160
7161 if (nla_parse(tb, BPF_MAX, data, data_len,
7162 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007163 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307164 return -EINVAL;
7165 }
7166
7167 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007168 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307169 return -EINVAL;
7170 }
7171
7172 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7173
7174 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7175 return hdd_get_bpf_offload(hdd_ctx);
7176 else
7177 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307178 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307179}
7180
7181/**
7182 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7183 * @wiphy: wiphy structure pointer
7184 * @wdev: Wireless device structure pointer
7185 * @data: Pointer to the data received
7186 * @data_len: Length of @data
7187 *
7188 * Return: 0 on success; errno on failure
7189 */
7190
7191static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7192 struct wireless_dev *wdev,
7193 const void *data, int data_len)
7194{
7195 int ret;
7196
7197 cds_ssr_protect(__func__);
7198 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7199 cds_ssr_unprotect(__func__);
7200
7201 return ret;
7202}
7203
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307204/**
7205 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7206 * @pre_cac_adapter: AP adapter used for pre cac
7207 * @status: Status (true or false)
7208 * @handle: Global handle
7209 *
7210 * Sets the status of pre cac i.e., whether the pre cac is active or not
7211 *
7212 * Return: Zero on success, non-zero on failure
7213 */
7214static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7215 bool status, tHalHandle handle)
7216{
7217 QDF_STATUS ret;
7218
7219 ret = wlan_sap_set_pre_cac_status(
7220 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7221 if (QDF_IS_STATUS_ERROR(ret))
7222 return -EINVAL;
7223
7224 return 0;
7225}
7226
7227/**
7228 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7229 * @ap_adapter: AP adapter
7230 * @chan_before_pre_cac: Channel
7231 *
7232 * Saves the channel which the AP was beaconing on before moving to the pre
7233 * cac channel. If radar is detected on the pre cac channel, this saved
7234 * channel will be used for AP operations.
7235 *
7236 * Return: Zero on success, non-zero on failure
7237 */
7238static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7239 uint8_t chan_before_pre_cac)
7240{
7241 QDF_STATUS ret;
7242
7243 ret = wlan_sap_set_chan_before_pre_cac(
7244 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7245 if (QDF_IS_STATUS_ERROR(ret))
7246 return -EINVAL;
7247
7248 return 0;
7249}
7250
7251/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307252 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7253 * are in nol list from provided channel list
7254 * @adapter: AP adapter
7255 * @channel_count: channel count
7256 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307257 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307258 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307259 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307260static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7261 uint32_t *channel_count,
7262 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307263{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307264 uint8_t i, j;
7265 uint32_t nol_len = 0;
7266 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7267 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7268 uint32_t chan_count;
7269 bool found;
7270 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307271
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307272 if (!hdd_ctx) {
7273 hdd_err("hdd ctx not found");
7274 *channel_count = 0;
7275 return;
7276 }
7277
7278 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7279 hdd_err("invalid channel count %d", *channel_count);
7280 return;
7281 }
7282
7283 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7284 if (nol_len == 0)
7285 return;
7286
7287 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7288 chan_count = *channel_count;
7289 qdf_mem_zero(channel_list, chan_count);
7290 *channel_count = 0;
7291
7292 for (i = 0 ; i < chan_count; i++) {
7293 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7294 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7295 continue;
7296 found = false;
7297 for (j = 0; j < nol_len; j++) {
7298 if (tmp_chan_list[i] == nol[j]) {
7299 found = true;
7300 hdd_notice("skipped channel %d due to nol",
7301 nol[j]);
7302 break;
7303 }
7304 }
7305 if (!found) {
7306 channel_list[*channel_count] = tmp_chan_list[i];
7307 *channel_count = *channel_count + 1;
7308 }
7309 }
7310}
7311
7312int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7313 uint32_t *channel_count,
7314 uint8_t *channel_list)
7315{
7316 tsap_Config_t *sap_config;
7317
7318 sap_config = &adapter->sessionCtx.ap.sapConfig;
7319
7320 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7321 sap_config->acs_cfg.ch_list_count);
7322 *channel_count = sap_config->acs_cfg.ch_list_count;
7323 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7324
7325 if (*channel_count == 0) {
7326 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307327 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307328 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307329
7330 return 0;
7331}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307332
7333/**
7334 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7335 * @hdd_ctx: HDD context
7336 * @ap_adapter: AP adapter
7337 * @channel: Channel requested by userspace
7338 * @pre_cac_chan: Pointer to the pre CAC channel
7339 *
7340 * Validates the channel provided by userspace. If user provided channel 0,
7341 * a valid outdoor channel must be selected from the regulatory channel.
7342 *
7343 * Return: Zero on success and non zero value on error
7344 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007345static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7346 hdd_adapter_t *ap_adapter,
7347 uint8_t channel,
7348 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307349{
7350 uint32_t i, j;
7351 QDF_STATUS status;
7352 int ret;
7353 uint8_t nol[QDF_MAX_NUM_CHAN];
7354 uint32_t nol_len = 0, weight_len = 0;
7355 bool found;
7356 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7357 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7358 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7359
7360 if (0 == channel) {
7361 /* Channel is not obtained from PCL because PCL may not have
7362 * the entire channel list. For example: if SAP is up on
7363 * channel 6 and PCL is queried for the next SAP interface,
7364 * if SCC is preferred, the PCL will contain only the channel
7365 * 6. But, we are in need of a DFS channel. So, going with the
7366 * first channel from the valid channel list.
7367 */
7368 status = cds_get_valid_chans(channel_list, &len);
7369 if (QDF_IS_STATUS_ERROR(status)) {
7370 hdd_err("Failed to get channel list");
7371 return -EINVAL;
7372 }
7373 cds_update_with_safe_channel_list(channel_list, &len,
7374 pcl_weights, weight_len);
7375 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7376 for (i = 0; i < len; i++) {
7377 found = false;
7378 for (j = 0; j < nol_len; j++) {
7379 if (channel_list[i] == nol[j]) {
7380 found = true;
7381 break;
7382 }
7383 }
7384 if (found)
7385 continue;
7386 if (CDS_IS_DFS_CH(channel_list[i])) {
7387 *pre_cac_chan = channel_list[i];
7388 break;
7389 }
7390 }
7391 if (*pre_cac_chan == 0) {
7392 hdd_err("unable to find outdoor channel");
7393 return -EINVAL;
7394 }
7395 } else {
7396 /* Only when driver selects a channel, check is done for
7397 * unnsafe and NOL channels. When user provides a fixed channel
7398 * the user is expected to take care of this.
7399 */
7400 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7401 !CDS_IS_DFS_CH(channel)) {
7402 hdd_err("Invalid channel for pre cac:%d", channel);
7403 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307404 }
Jeff Johnson68755312017-02-10 11:46:55 -08007405
7406 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307407 }
7408 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7409 return 0;
7410}
7411
7412/**
7413 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7414 * @channel: Channel option provided by userspace
7415 *
7416 * Sets the driver to the required hardware mode and start an adapater for
7417 * pre CAC which will mimic an AP.
7418 *
7419 * Return: Zero on success, non-zero value on error
7420 */
7421int wlan_hdd_request_pre_cac(uint8_t channel)
7422{
Krunal Sonib37bb352016-12-20 14:12:21 -08007423 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307424 hdd_context_t *hdd_ctx;
7425 int ret;
7426 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7427 hdd_ap_ctx_t *hdd_ap_ctx;
7428 QDF_STATUS status;
7429 struct wiphy *wiphy;
7430 struct net_device *dev;
7431 struct cfg80211_chan_def chandef;
7432 enum nl80211_channel_type channel_type;
7433 uint32_t freq;
7434 struct ieee80211_channel *chan;
7435 tHalHandle handle;
7436 bool val;
7437
7438 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7439 if (0 != wlan_hdd_validate_context(hdd_ctx))
7440 return -EINVAL;
7441
7442 if (cds_get_connection_count() > 1) {
7443 hdd_err("pre cac not allowed in concurrency");
7444 return -EINVAL;
7445 }
7446
7447 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7448 if (!ap_adapter) {
7449 hdd_err("unable to get SAP adapter");
7450 return -EINVAL;
7451 }
7452
7453 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7454 if (!handle) {
7455 hdd_err("Invalid handle");
7456 return -EINVAL;
7457 }
7458
7459 val = wlan_sap_is_pre_cac_active(handle);
7460 if (val) {
7461 hdd_err("pre cac is already in progress");
7462 return -EINVAL;
7463 }
7464
7465 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7466 if (!hdd_ap_ctx) {
7467 hdd_err("SAP context is NULL");
7468 return -EINVAL;
7469 }
7470
7471 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7472 hdd_err("SAP is already on DFS channel:%d",
7473 hdd_ap_ctx->operatingChannel);
7474 return -EINVAL;
7475 }
7476
7477 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7478 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7479 hdd_ap_ctx->operatingChannel);
7480 return -EINVAL;
7481 }
7482
Krunal Sonib37bb352016-12-20 14:12:21 -08007483 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7484 if (!mac_addr) {
7485 hdd_err("can't add virtual intf: Not getting valid mac addr");
7486 return -EINVAL;
7487 }
7488
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307489 hdd_info("channel:%d", channel);
7490
7491 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7492 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007493 if (ret != 0) {
7494 hdd_err("can't validate pre-cac channel");
7495 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307496 }
7497
7498 hdd_debug("starting pre cac SAP adapter");
7499
7500 /* Starting a SAP adapter:
7501 * Instead of opening an adapter, we could just do a SME open session
7502 * for AP type. But, start BSS would still need an adapter.
7503 * So, this option is not taken.
7504 *
7505 * hdd open adapter is going to register this precac interface with
7506 * user space. This interface though exposed to user space will be in
7507 * DOWN state. Consideration was done to avoid this registration to the
7508 * user space. But, as part of SAP operations multiple events are sent
7509 * to user space. Some of these events received from unregistered
7510 * interface was causing crashes. So, retaining the registration.
7511 *
7512 * So, this interface would remain registered and will remain in DOWN
7513 * state for the CAC duration. We will add notes in the feature
7514 * announcement to not use this temporary interface for any activity
7515 * from user space.
7516 */
7517 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007518 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307519 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307520 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007521 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307522 }
7523
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307524 /*
7525 * This interface is internally created by the driver. So, no interface
7526 * up comes for this interface from user space and hence starting
7527 * the adapter internally.
7528 */
7529 if (hdd_start_adapter(pre_cac_adapter)) {
7530 hdd_err("error starting the pre cac adapter");
7531 goto close_pre_cac_adapter;
7532 }
7533
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307534 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7535
7536 wiphy = hdd_ctx->wiphy;
7537 dev = pre_cac_adapter->dev;
7538
7539 /* Since this is only a dummy interface lets us use the IEs from the
7540 * other active SAP interface. In regular scenarios, these IEs would
7541 * come from the user space entity
7542 */
7543 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7544 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7545 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7546 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307547 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307548 }
7549 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7550 ap_adapter->sessionCtx.ap.beacon,
7551 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7552 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7553 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7554 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7555 ap_adapter->sessionCtx.ap.sapConfig.authType;
7556
7557 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7558 * to operate on the same bandwidth as that of the 2.4GHz operations.
7559 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7560 */
7561 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7562 case CH_WIDTH_20MHZ:
7563 channel_type = NL80211_CHAN_HT20;
7564 break;
7565 case CH_WIDTH_40MHZ:
7566 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7567 ap_adapter->sessionCtx.ap.sapConfig.channel)
7568 channel_type = NL80211_CHAN_HT40PLUS;
7569 else
7570 channel_type = NL80211_CHAN_HT40MINUS;
7571 break;
7572 default:
7573 channel_type = NL80211_CHAN_NO_HT;
7574 break;
7575 }
7576
7577 freq = cds_chan_to_freq(pre_cac_chan);
7578 chan = __ieee80211_get_channel(wiphy, freq);
7579 if (!chan) {
7580 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307581 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307582 }
7583
7584 cfg80211_chandef_create(&chandef, chan, channel_type);
7585
7586 hdd_debug("orig width:%d channel_type:%d freq:%d",
7587 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7588 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007589 /*
7590 * Doing update after opening and starting pre-cac adapter will make
7591 * sure that driver won't do hardware mode change if there are any
7592 * initial hick-ups or issues in pre-cac adapter's configuration.
7593 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7594 * connection update should result in DBS mode
7595 */
7596 status = cds_update_and_wait_for_connection_update(
7597 ap_adapter->sessionId,
7598 pre_cac_chan,
7599 SIR_UPDATE_REASON_PRE_CAC);
7600 if (QDF_IS_STATUS_ERROR(status)) {
7601 hdd_err("error in moving to DBS mode");
7602 goto stop_close_pre_cac_adapter;
7603 }
7604
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307605
7606 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7607 if (0 != ret) {
7608 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307609 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307610 }
7611
7612 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7613 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007614 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307615 if (QDF_IS_STATUS_ERROR(status)) {
7616 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307617 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307618 }
7619
7620 /*
7621 * The pre cac status is set here. But, it would not be reset explicitly
7622 * anywhere, since after the pre cac success/failure, the pre cac
7623 * adapter itself would be removed.
7624 */
7625 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7626 if (0 != ret) {
7627 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307628 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307629 }
7630
7631 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7632 hdd_ap_ctx->operatingChannel);
7633 if (0 != ret) {
7634 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307635 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307636 }
7637
7638 ap_adapter->pre_cac_chan = pre_cac_chan;
7639
7640 return 0;
7641
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307642stop_close_pre_cac_adapter:
7643 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307644 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7645 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307646close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307647 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007648release_intf_addr_and_return_failure:
7649 /*
7650 * Release the interface address as the adapter
7651 * failed to start, if you don't release then next
7652 * adapter which is trying to come wouldn't get valid
7653 * mac address. Remember we have limited pool of mac addresses
7654 */
7655 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307656 return -EINVAL;
7657}
7658
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307659static const struct nla_policy
7660wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7661 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7662};
7663
Agrawal Ashish65634612016-08-18 13:24:32 +05307664static const struct nla_policy
7665wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7666 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7667 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7668};
7669
7670/**
7671 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7672 * @wiphy: Pointer to wireless phy
7673 * @wdev: Pointer to wireless device
7674 * @data: Pointer to data
7675 * @data_len: Length of @data
7676 *
7677 * This function parses the incoming NL vendor command data attributes and
7678 * updates the SAP context about channel_hint and DFS mode.
7679 * If channel_hint is set, SAP will choose that channel
7680 * as operating channel.
7681 *
7682 * If DFS mode is enabled, driver will include DFS channels
7683 * in ACS else driver will skip DFS channels.
7684 *
7685 * Return: 0 on success, negative errno on failure
7686 */
7687static int
7688__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7689 struct wireless_dev *wdev,
7690 const void *data, int data_len)
7691{
7692 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7693 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7694 int ret;
7695 struct acs_dfs_policy *acs_policy;
7696 int mode = DFS_MODE_NONE;
7697 int channel_hint = 0;
7698
7699 ENTER_DEV(wdev->netdev);
7700
7701 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7702 hdd_err("Command not allowed in FTM mode");
7703 return -EINVAL;
7704 }
7705
7706 ret = wlan_hdd_validate_context(hdd_ctx);
7707 if (0 != ret)
7708 return ret;
7709
7710 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7711 data, data_len,
7712 wlan_hdd_set_acs_dfs_config_policy)) {
7713 hdd_err("invalid attr");
7714 return -EINVAL;
7715 }
7716
7717 acs_policy = &hdd_ctx->acs_policy;
7718 /*
7719 * SCM sends this attribute to restrict SAP from choosing
7720 * DFS channels from ACS.
7721 */
7722 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7723 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7724
7725 if (!IS_DFS_MODE_VALID(mode)) {
7726 hdd_err("attr acs dfs mode is not valid");
7727 return -EINVAL;
7728 }
7729 acs_policy->acs_dfs_mode = mode;
7730
7731 /*
7732 * SCM sends this attribute to provide an active channel,
7733 * to skip redundant ACS between drivers, and save driver start up time
7734 */
7735 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7736 channel_hint = nla_get_u8(
7737 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7738
7739 if (!IS_CHANNEL_VALID(channel_hint)) {
7740 hdd_err("acs channel is not valid");
7741 return -EINVAL;
7742 }
7743 acs_policy->acs_channel = channel_hint;
7744
7745 return 0;
7746}
7747
7748/**
7749 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7750 * @wiphy: wiphy structure pointer
7751 * @wdev: Wireless device structure pointer
7752 * @data: Pointer to the data received
7753 * @data_len: Length of @data
7754 *
7755 * This function parses the incoming NL vendor command data attributes and
7756 * updates the SAP context about channel_hint and DFS mode.
7757 *
7758 * Return: 0 on success; errno on failure
7759 */
7760static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7761 struct wireless_dev *wdev,
7762 const void *data, int data_len)
7763{
7764 int ret;
7765
7766 cds_ssr_protect(__func__);
7767 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7768 cds_ssr_unprotect(__func__);
7769
7770 return ret;
7771}
7772
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307773/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307774 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7775 * @mode : cfg80211 dfs mode
7776 *
7777 * Return: return csr sta roam dfs mode else return NONE
7778 */
7779static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7780 enum dfs_mode mode)
7781{
7782 switch (mode) {
7783 case DFS_MODE_ENABLE:
7784 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7785 break;
7786 case DFS_MODE_DISABLE:
7787 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7788 break;
7789 case DFS_MODE_DEPRIORITIZE:
7790 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7791 break;
7792 default:
7793 hdd_err("STA Roam policy dfs mode is NONE");
7794 return CSR_STA_ROAM_POLICY_NONE;
7795 }
7796}
7797
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307798/*
7799 * hdd_get_sap_operating_band: Get current operating channel
7800 * for sap.
7801 * @hdd_ctx: hdd context
7802 *
7803 * Return : Corresponding band for SAP operating channel
7804 */
7805uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7806{
7807 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7808 QDF_STATUS status;
7809 hdd_adapter_t *adapter;
7810 uint8_t operating_channel = 0;
7811 uint8_t sap_operating_band = 0;
7812 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7813 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7814 adapter = adapter_node->pAdapter;
7815
7816 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7817 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7818 &next);
7819 adapter_node = next;
7820 continue;
7821 }
7822 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7823 if (IS_24G_CH(operating_channel))
7824 sap_operating_band = eCSR_BAND_24;
7825 else if (IS_5G_CH(operating_channel))
7826 sap_operating_band = eCSR_BAND_5G;
7827 else
7828 sap_operating_band = eCSR_BAND_ALL;
7829 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7830 &next);
bings373b99b2017-01-23 10:35:08 +08007831 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307832 }
7833 return sap_operating_band;
7834}
7835
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307836static const struct nla_policy
7837wlan_hdd_set_sta_roam_config_policy[
7838QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7839 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7840 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7841};
7842
7843/**
7844 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7845 * for station connection or roaming.
7846 * @wiphy: Pointer to wireless phy
7847 * @wdev: Pointer to wireless device
7848 * @data: Pointer to data
7849 * @data_len: Length of @data
7850 *
7851 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7852 * channels needs to be skipped in scanning or not.
7853 * If dfs_mode is disabled, driver will not scan DFS channels.
7854 * If skip_unsafe_channels is set, driver will skip unsafe channels
7855 * in Scanning.
7856 *
7857 * Return: 0 on success, negative errno on failure
7858 */
7859static int
7860__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7861 struct wireless_dev *wdev,
7862 const void *data, int data_len)
7863{
7864 struct net_device *dev = wdev->netdev;
7865 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7866 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7867 struct nlattr *tb[
7868 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7869 int ret;
7870 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7871 enum dfs_mode mode = DFS_MODE_NONE;
7872 bool skip_unsafe_channels = false;
7873 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307874 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307875
7876 ENTER_DEV(dev);
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 ret = wlan_hdd_validate_context(hdd_ctx);
7884 if (0 != ret)
7885 return ret;
7886 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7887 data, data_len,
7888 wlan_hdd_set_sta_roam_config_policy)) {
7889 hdd_err("invalid attr");
7890 return -EINVAL;
7891 }
7892 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7893 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7894 if (!IS_DFS_MODE_VALID(mode)) {
7895 hdd_err("attr sta roam dfs mode policy is not valid");
7896 return -EINVAL;
7897 }
7898
7899 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7900
7901 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7902 skip_unsafe_channels = nla_get_u8(
7903 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307904 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307905 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307906 skip_unsafe_channels, adapter->sessionId,
7907 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307908
7909 if (!QDF_IS_STATUS_SUCCESS(status)) {
7910 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7911 return -EINVAL;
7912 }
7913 return 0;
7914}
7915
7916/**
7917 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7918 * connection and roaming for station.
7919 * @wiphy: wiphy structure pointer
7920 * @wdev: Wireless device structure pointer
7921 * @data: Pointer to the data received
7922 * @data_len: Length of @data
7923 *
7924 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7925 * channels needs to be skipped in scanning or not.
7926 * If dfs_mode is disabled, driver will not scan DFS channels.
7927 * If skip_unsafe_channels is set, driver will skip unsafe channels
7928 * in Scanning.
7929 * Return: 0 on success; errno on failure
7930 */
7931static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7932 struct wireless_dev *wdev,
7933 const void *data, int data_len)
7934{
7935 int ret;
7936
7937 cds_ssr_protect(__func__);
7938 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7939 cds_ssr_unprotect(__func__);
7940
7941 return ret;
7942}
7943
Agrawal Ashish467dde42016-09-08 18:44:22 +05307944#ifdef FEATURE_WLAN_CH_AVOID
7945/**
7946 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7947 * is on unsafe channel.
7948 * @wiphy: wiphy structure pointer
7949 * @wdev: Wireless device structure pointer
7950 * @data: Pointer to the data received
7951 * @data_len: Length of @data
7952 *
7953 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7954 * on any of unsafe channels.
7955 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7956 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7957 *
7958 * Return: 0 on success; errno on failure
7959 */
7960static int
7961__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7962 struct wireless_dev *wdev,
7963 const void *data, int data_len)
7964{
7965 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7966 int ret;
7967 uint16_t unsafe_channel_count;
7968 int unsafe_channel_index;
7969 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7970
7971 ENTER_DEV(wdev->netdev);
7972
7973 if (!qdf_ctx) {
7974 cds_err("qdf_ctx is NULL");
7975 return -EINVAL;
7976 }
7977
7978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7979 hdd_err("Command not allowed in FTM mode");
7980 return -EINVAL;
7981 }
7982
7983 ret = wlan_hdd_validate_context(hdd_ctx);
7984 if (0 != ret)
7985 return ret;
7986 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7987 &(hdd_ctx->unsafe_channel_count),
7988 sizeof(hdd_ctx->unsafe_channel_list));
7989
7990 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7991 (uint16_t)NUM_CHANNELS);
7992 for (unsafe_channel_index = 0;
7993 unsafe_channel_index < unsafe_channel_count;
7994 unsafe_channel_index++) {
7995 hdd_info("Channel %d is not safe",
7996 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7997 }
7998 hdd_unsafe_channel_restart_sap(hdd_ctx);
7999 return 0;
8000}
8001
8002/**
8003 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8004 * is on unsafe channel.
8005 * @wiphy: wiphy structure pointer
8006 * @wdev: Wireless device structure pointer
8007 * @data: Pointer to the data received
8008 * @data_len: Length of @data
8009 *
8010 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8011 * on any of unsafe channels.
8012 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8013 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8014 *
8015 * Return: 0 on success; errno on failure
8016 */
8017static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8018 struct wireless_dev *wdev,
8019 const void *data, int data_len)
8020{
8021 int ret;
8022
8023 cds_ssr_protect(__func__);
8024 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8025 cds_ssr_unprotect(__func__);
8026
8027 return ret;
8028}
8029
8030#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308031/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308032 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8033 * SAP is on unsafe channel.
8034 * @wiphy: wiphy structure pointer
8035 * @wdev: Wireless device structure pointer
8036 * @data: Pointer to the data received
8037 * @data_len: Length of @data
8038 *
8039 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8040 * driver.
8041 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8042 * will initiate restart of sap.
8043 *
8044 * Return: 0 on success; errno on failure
8045 */
8046static int
8047__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8048 struct wireless_dev *wdev,
8049 const void *data, int data_len)
8050{
8051 struct net_device *ndev = wdev->netdev;
8052 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8053 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8054 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8055 uint8_t config_channel = 0;
8056 hdd_ap_ctx_t *ap_ctx;
8057 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308058 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308059
8060 ENTER();
8061
8062 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008063 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308064 return -EINVAL;
8065 }
8066
8067 ret = wlan_hdd_validate_context(hdd_ctx);
8068 if (0 != ret)
8069 return -EINVAL;
8070
8071 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8072 data, data_len,
8073 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008074 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308075 return -EINVAL;
8076 }
8077
8078 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8079 if (!test_bit(SOFTAP_BSS_STARTED,
8080 &hostapd_adapter->event_flags)) {
8081 hdd_err("SAP is not started yet. Restart sap will be invalid");
8082 return -EINVAL;
8083 }
8084
8085 config_channel =
8086 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8087
8088 if (!((IS_24G_CH(config_channel)) ||
8089 (IS_5G_CH(config_channel)))) {
8090 hdd_err("Channel %d is not valid to restart SAP",
8091 config_channel);
8092 return -ENOTSUPP;
8093 }
8094
8095 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8096 ap_ctx->sapConfig.channel = config_channel;
8097 ap_ctx->sapConfig.ch_params.ch_width =
8098 ap_ctx->sapConfig.ch_width_orig;
8099
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008100 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308101 ap_ctx->sapConfig.sec_ch,
8102 &ap_ctx->sapConfig.ch_params);
8103
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008104 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308105 }
8106
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308107 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8108 uint32_t freq_len, i;
8109 uint32_t *freq;
8110 uint8_t chans[QDF_MAX_NUM_CHAN];
8111
8112 hdd_debug("setting mandatory freq/chan list");
8113
8114 freq_len = nla_len(
8115 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8116 sizeof(uint32_t);
8117
8118 if (freq_len > QDF_MAX_NUM_CHAN) {
8119 hdd_err("insufficient space to hold channels");
8120 return -ENOMEM;
8121 }
8122
8123 freq = nla_data(
8124 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8125
8126 hdd_debug("freq_len=%d", freq_len);
8127
8128 for (i = 0; i < freq_len; i++) {
8129 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8130 hdd_debug("freq[%d]=%d", i, freq[i]);
8131 }
8132
8133 status = cds_set_sap_mandatory_channels(chans, freq_len);
8134 if (QDF_IS_STATUS_ERROR(status))
8135 return -EINVAL;
8136 }
8137
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308138 return 0;
8139}
8140
8141/**
8142 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8143 * @wiphy: wiphy structure pointer
8144 * @wdev: Wireless device structure pointer
8145 * @data: Pointer to the data received
8146 * @data_len: Length of @data
8147 *
8148 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8149 * driver.
8150 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8151 * will initiate restart of sap.
8152 *
8153 * Return: 0 on success; errno on failure
8154 */
8155static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8156 struct wireless_dev *wdev,
8157 const void *data, int data_len)
8158{
8159 int ret;
8160
8161 cds_ssr_protect(__func__);
8162 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8163 wdev, data, data_len);
8164 cds_ssr_unprotect(__func__);
8165
8166 return ret;
8167}
8168
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308169#undef BPF_INVALID
8170#undef BPF_SET_RESET
8171#undef BPF_VERSION
8172#undef BPF_ID
8173#undef BPF_PACKET_SIZE
8174#undef BPF_CURRENT_OFFSET
8175#undef BPF_PROGRAM
8176#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308177
8178/**
8179 * define short names for the global vendor params
8180 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8181 */
8182#define PARAM_TOTAL_CMD_EVENT_WAKE \
8183 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8184#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8185 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8186#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8187 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8188#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8189 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8190#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8191 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8192#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8193 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8194#define PARAM_TOTAL_RX_DATA_WAKE \
8195 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8196#define PARAM_RX_UNICAST_CNT \
8197 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8198#define PARAM_RX_MULTICAST_CNT \
8199 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8200#define PARAM_RX_BROADCAST_CNT \
8201 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8202#define PARAM_ICMP_PKT \
8203 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8204#define PARAM_ICMP6_PKT \
8205 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8206#define PARAM_ICMP6_RA \
8207 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8208#define PARAM_ICMP6_NA \
8209 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8210#define PARAM_ICMP6_NS \
8211 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8212#define PARAM_ICMP4_RX_MULTICAST_CNT \
8213 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8214#define PARAM_ICMP6_RX_MULTICAST_CNT \
8215 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8216#define PARAM_OTHER_RX_MULTICAST_CNT \
8217 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308218#define PARAM_RSSI_BREACH_CNT \
8219 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8220#define PARAM_LOW_RSSI_CNT \
8221 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8222#define PARAM_GSCAN_CNT \
8223 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8224#define PARAM_PNO_COMPLETE_CNT \
8225 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8226#define PARAM_PNO_MATCH_CNT \
8227 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8228
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308229
8230
8231/**
8232 * hdd_send_wakelock_stats() - API to send wakelock stats
8233 * @ctx: context to be passed to callback
8234 * @data: data passed to callback
8235 *
8236 * This function is used to send wake lock stats to HAL layer
8237 *
8238 * Return: 0 on success, error number otherwise.
8239 */
8240static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8241 const struct sir_wake_lock_stats *data)
8242{
8243 struct sk_buff *skb;
8244 uint32_t nl_buf_len;
8245 uint32_t total_rx_data_wake, rx_multicast_cnt;
8246 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308247 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308248
8249 ENTER();
8250
8251 nl_buf_len = NLMSG_HDRLEN;
8252 nl_buf_len +=
8253 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8254 (NLMSG_HDRLEN + sizeof(uint32_t));
8255
8256 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8257
8258 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008259 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260 return -ENOMEM;
8261 }
8262
Jeff Johnson64943bd2016-08-23 13:14:06 -07008263 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308264 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008265 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308266 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008267 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308268 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008269 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308270 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008271 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308272 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008273 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308274 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008275 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308276 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008277 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8278 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308279 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308280 hdd_info("wow_rssi_breach_wake_up_count %d",
8281 data->wow_rssi_breach_wake_up_count);
8282 hdd_info("wow_low_rssi_wake_up_count %d",
8283 data->wow_low_rssi_wake_up_count);
8284 hdd_info("wow_gscan_wake_up_count %d",
8285 data->wow_gscan_wake_up_count);
8286 hdd_info("wow_pno_complete_wake_up_count %d",
8287 data->wow_pno_complete_wake_up_count);
8288 hdd_info("wow_pno_match_wake_up_count %d",
8289 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308290
8291 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308292 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308293
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308294 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308295 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308296
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308297 rx_multicast_cnt =
8298 data->wow_ipv4_mcast_wake_up_count +
8299 ipv6_rx_multicast_addr_cnt;
8300
8301 total_rx_data_wake =
8302 data->wow_ucast_wake_up_count +
8303 data->wow_bcast_wake_up_count +
8304 rx_multicast_cnt;
8305
8306 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8307 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8308 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8309 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8310 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8311 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8312 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8313 total_rx_data_wake) ||
8314 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8315 data->wow_ucast_wake_up_count) ||
8316 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8317 rx_multicast_cnt) ||
8318 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8319 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308320 nla_put_u32(skb, PARAM_ICMP_PKT,
8321 data->wow_icmpv4_count) ||
8322 nla_put_u32(skb, PARAM_ICMP6_PKT,
8323 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308324 nla_put_u32(skb, PARAM_ICMP6_RA,
8325 data->wow_ipv6_mcast_ra_stats) ||
8326 nla_put_u32(skb, PARAM_ICMP6_NA,
8327 data->wow_ipv6_mcast_na_stats) ||
8328 nla_put_u32(skb, PARAM_ICMP6_NS,
8329 data->wow_ipv6_mcast_ns_stats) ||
8330 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8331 data->wow_ipv4_mcast_wake_up_count) ||
8332 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8333 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308334 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8335 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8336 data->wow_rssi_breach_wake_up_count) ||
8337 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8338 data->wow_low_rssi_wake_up_count) ||
8339 nla_put_u32(skb, PARAM_GSCAN_CNT,
8340 data->wow_gscan_wake_up_count) ||
8341 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8342 data->wow_pno_complete_wake_up_count) ||
8343 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8344 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008345 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308346 goto nla_put_failure;
8347 }
8348
8349 cfg80211_vendor_cmd_reply(skb);
8350
8351 EXIT();
8352 return 0;
8353
8354nla_put_failure:
8355 kfree_skb(skb);
8356 return -EINVAL;
8357}
8358
8359/**
8360 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8361 * @wiphy: wiphy pointer
8362 * @wdev: pointer to struct wireless_dev
8363 * @data: pointer to incoming NL vendor data
8364 * @data_len: length of @data
8365 *
8366 * This function parses the incoming NL vendor command data attributes and
8367 * invokes the SME Api and blocks on a completion variable.
8368 * WMA copies required data and invokes callback
8369 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8370 *
8371 * Return: 0 on success; error number otherwise.
8372 */
8373static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8374 struct wireless_dev *wdev,
8375 const void *data,
8376 int data_len)
8377{
8378 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8379 int status, ret;
8380 struct sir_wake_lock_stats wake_lock_stats;
8381 QDF_STATUS qdf_status;
8382
8383 ENTER();
8384
8385 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008386 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308387 return -EINVAL;
8388 }
8389
8390 status = wlan_hdd_validate_context(hdd_ctx);
8391 if (0 != status)
8392 return -EINVAL;
8393
8394 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8395 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008396 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308397 return -EINVAL;
8398 }
8399
8400 ret = hdd_send_wakelock_stats(hdd_ctx,
8401 &wake_lock_stats);
8402 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008403 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308404
8405 EXIT();
8406 return ret;
8407}
8408
8409/**
8410 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8411 * @wiphy: wiphy pointer
8412 * @wdev: pointer to struct wireless_dev
8413 * @data: pointer to incoming NL vendor data
8414 * @data_len: length of @data
8415 *
8416 * This function parses the incoming NL vendor command data attributes and
8417 * invokes the SME Api and blocks on a completion variable.
8418 * WMA copies required data and invokes callback
8419 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8420 *
8421 * Return: 0 on success; error number otherwise.
8422 */
8423static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8424 struct wireless_dev *wdev,
8425 const void *data, int data_len)
8426{
8427 int ret;
8428
8429 cds_ssr_protect(__func__);
8430 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8431 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008432 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308433
8434 return ret;
8435}
8436
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308437/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308438 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8439 * @wiphy: wiphy structure pointer
8440 * @wdev: Wireless device structure pointer
8441 * @data: Pointer to the data received
8442 * @data_len: Length of @data
8443 *
8444 * This function reads wmi max bus size and fill in the skb with
8445 * NL attributes and send up the NL event.
8446 * Return: 0 on success; errno on failure
8447 */
8448static int
8449__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8450 struct wireless_dev *wdev,
8451 const void *data, int data_len)
8452{
8453 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8454 int ret_val;
8455 struct sk_buff *skb;
8456 uint32_t nl_buf_len;
8457
8458 ENTER();
8459
8460 ret_val = wlan_hdd_validate_context(hdd_ctx);
8461 if (ret_val)
8462 return ret_val;
8463
8464 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8465 hdd_err("Command not allowed in FTM mode");
8466 return -EINVAL;
8467 }
8468
8469 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8470
8471 nl_buf_len = NLMSG_HDRLEN;
8472 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8473
8474 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8475 if (!skb) {
8476 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8477 return -ENOMEM;
8478 }
8479
8480 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8481 hdd_ctx->wmi_max_len)) {
8482 hdd_err("nla put failure");
8483 goto nla_put_failure;
8484 }
8485
8486 cfg80211_vendor_cmd_reply(skb);
8487
8488 EXIT();
8489
8490 return 0;
8491
8492nla_put_failure:
8493 kfree_skb(skb);
8494 return -EINVAL;
8495}
8496
8497/**
8498 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8499 * @wiphy: wiphy structure pointer
8500 * @wdev: Wireless device structure pointer
8501 * @data: Pointer to the data received
8502 * @data_len: Length of @data
8503 *
8504 * Return: 0 on success; errno on failure
8505 */
8506static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8507 struct wireless_dev *wdev,
8508 const void *data, int data_len)
8509{
8510 int ret;
8511
8512 cds_ssr_protect(__func__);
8513 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8514 cds_ssr_unprotect(__func__);
8515
8516 return ret;
8517}
8518
8519/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308520 *__wlan_hdd_cfg80211_setband() - set band
8521 * @wiphy: Pointer to wireless phy
8522 * @wdev: Pointer to wireless device
8523 * @data: Pointer to data
8524 * @data_len: Length of @data
8525 *
8526 * Return: 0 on success, negative errno on failure
8527 */
8528static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8529 struct wireless_dev *wdev,
8530 const void *data, int data_len)
8531{
8532 struct net_device *dev = wdev->netdev;
8533 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8534 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8535 int ret;
8536 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8537 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8538
8539 ENTER();
8540
8541 ret = wlan_hdd_validate_context(hdd_ctx);
8542 if (ret)
8543 return ret;
8544
8545 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8546 hdd_err(FL("Invalid ATTR"));
8547 return -EINVAL;
8548 }
8549
8550 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8551 hdd_err(FL("attr SETBAND_VALUE failed"));
8552 return -EINVAL;
8553 }
8554
8555 ret = hdd_set_band(dev,
8556 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8557
8558 EXIT();
8559 return ret;
8560}
8561
8562/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308563 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8564 * @adapter: hdd adapter
8565 * @channel: channel number
8566 *
8567 * return: QDF status based on success or failure
8568 */
8569static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8570 int channel, int chan_bw)
8571{
8572 if (QDF_STATUS_SUCCESS !=
8573 wlan_hdd_validate_operation_channel(adapter, channel))
8574 return QDF_STATUS_E_FAILURE;
8575 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8576 channel,
8577 PHY_SINGLE_CHANNEL_CENTERED))) {
8578 hdd_notice("channel %d is in nol", channel);
8579 return -EINVAL;
8580 }
8581
8582 if ((wlansap_is_channel_leaking_in_nol(
8583 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8584 channel, chan_bw))) {
8585 hdd_notice("channel %d is leaking in nol", channel);
8586 return -EINVAL;
8587 }
8588
8589 return 0;
8590
8591}
8592
Kapil Gupta8878ad92017-02-13 11:56:04 +05308593static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8594 tsap_Config_t *sap_config,
8595 struct hdd_vendor_chan_info *channel_list)
8596{
8597 sap_config->channel = channel_list->pri_ch;
8598
8599 sap_config->ch_params.center_freq_seg0 =
8600 channel_list->vht_seg0_center_ch;
8601 sap_config->ch_params.center_freq_seg1 =
8602 channel_list->vht_seg1_center_ch;
8603
8604 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8605 sap_config->ch_params.ch_width = channel_list->chan_width;
8606 if (sap_config->channel >= 36)
8607 sap_config->ch_width_orig =
8608 hdd_ctx->config->vhtChannelWidth;
8609 else
8610 sap_config->ch_width_orig =
8611 hdd_ctx->config->nChannelBondingMode24GHz ?
8612 eHT_CHANNEL_WIDTH_40MHZ :
8613 eHT_CHANNEL_WIDTH_20MHZ;
8614
8615 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8616 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8617 sap_config->acs_cfg.vht_seg0_center_ch =
8618 channel_list->vht_seg0_center_ch;
8619 sap_config->acs_cfg.vht_seg1_center_ch =
8620 channel_list->vht_seg1_center_ch;
8621 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8622}
8623
8624static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8625 uint8_t channel_cnt,
8626 struct hdd_vendor_chan_info *channel_list)
8627{
8628 tsap_Config_t *sap_config;
8629 hdd_ap_ctx_t *hdd_ap_ctx;
8630 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8631 QDF_STATUS status = QDF_STATUS_SUCCESS;
8632
8633 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8634 sap_config = &adapter->sessionCtx.ap.sapConfig;
8635
8636 if (QDF_TIMER_STATE_RUNNING ==
8637 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8638 ap.vendor_acs_timer)) {
8639 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8640 }
8641
8642 if (channel_list && channel_list->pri_ch == 0) {
8643 /* Check mode, set default channel */
8644 channel_list->pri_ch = 6;
8645 /*
8646 * sap_select_default_oper_chan(hdd_ctx->hHal,
8647 * sap_config->acs_cfg.hw_mode);
8648 */
8649 }
8650
8651 switch (reason) {
8652 /* SAP init case */
8653 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8654 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8655 /* Update Hostapd */
8656 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8657 break;
8658
8659 /* DFS detected on current channel */
8660 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8661 wlan_sap_update_next_channel(
8662 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8663 channel_list->pri_ch,
8664 channel_list->chan_width);
8665 status = sme_update_new_channel_event(
8666 WLAN_HDD_GET_HAL_CTX(adapter),
8667 adapter->sessionId);
8668 break;
8669
8670 /* LTE coex event on current channel */
8671 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8672 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8673 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8674 hdd_ap_ctx->sapConfig.ch_width_orig =
8675 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008676 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308677 break;
8678
8679 default:
8680 hdd_info("invalid reason for timer invoke");
8681 }
8682 qdf_mem_free(channel_list);
8683 EXIT();
8684 return status;
8685}
8686
8687/**
8688 * Define short name for vendor channel set config
8689 */
8690#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8691#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8692#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8693#define SET_CHAN_PRIMARY_CHANNEL \
8694 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8695#define SET_CHAN_SECONDARY_CHANNEL \
8696 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8697#define SET_CHAN_SEG0_CENTER_CHANNEL \
8698 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8699#define SET_CHAN_SEG1_CENTER_CHANNEL \
8700 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8701#define SET_CHAN_CHANNEL_WIDTH \
8702 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8703#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8704
8705/**
8706 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8707 * @channel_list: pointer to hdd_vendor_chan_info
8708 * @reason: channel change reason
8709 * @channel_cnt: channel count
8710 * @data: data
8711 * @data_len: data len
8712 *
8713 * Return: 0 on success, negative errno on failure
8714 */
8715static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8716 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8717 const void *data, int data_len)
8718{
8719 int rem, i = 0;
8720 struct nlattr *tb[SET_CHAN_MAX + 1];
8721 struct nlattr *tb2[SET_CHAN_MAX + 1];
8722 struct nlattr *curr_attr;
8723 struct hdd_vendor_chan_info *channel_list;
8724
8725 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8726 hdd_err("Invalid ATTR");
8727 return -EINVAL;
8728 }
8729
8730 if (tb[SET_CHAN_REASON])
8731 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8732
8733 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8734 *channel_cnt = nla_get_u8(tb[
8735 SET_CHAN_CHANNEL_COUNT]);
8736 hdd_info("channel count %d", *channel_cnt);
8737 }
8738
8739 if (!(*channel_cnt)) {
8740 hdd_err("channel count is %d", *channel_cnt);
8741 return -EINVAL;
8742 }
8743
8744 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8745 (*channel_cnt));
8746
8747 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8748 if (nla_parse(tb2,
8749 SET_CHAN_MAX,
8750 nla_data(curr_attr), nla_len(curr_attr),
8751 NULL)) {
8752 hdd_err("nla_parse failed");
8753 return -EINVAL;
8754 }
8755 /* Parse and Fetch allowed SSID list*/
8756 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8757 channel_list[i].pri_ch =
8758 nla_get_u8(
8759 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8760 }
8761 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8762 channel_list[i].ht_sec_ch =
8763 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8764 }
8765 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8766 channel_list[i].vht_seg0_center_ch =
8767 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8768 }
8769 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8770 channel_list[i].vht_seg1_center_ch =
8771 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8772 }
8773 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8774 channel_list[i].chan_width =
8775 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8776 }
8777 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8778 i, channel_list[i].pri_ch,
8779 channel_list[i].ht_sec_ch,
8780 channel_list[i].vht_seg0_center_ch,
8781 channel_list[i].vht_seg1_center_ch,
8782 channel_list[i].chan_width);
8783 i++;
8784 if (i > *channel_cnt)
8785 break;
8786 }
8787 *chan_list_ptr = channel_list;
8788
8789 return 0;
8790}
8791
8792/**
8793 * Undef short names for vendor set channel configuration
8794 */
8795#undef SET_CHAN_REASON
8796#undef SET_CHAN_CHANNEL_COUNT
8797#undef SET_CHAN_CHAN_LIST
8798#undef SET_CHAN_PRIMARY_CHANNEL
8799#undef SET_CHAN_SECONDARY_CHANNEL
8800#undef SET_CHAN_SEG0_CENTER_CHANNEL
8801#undef SET_CHAN_SEG1_CENTER_CHANNEL
8802#undef SET_CHAN_CHANNEL_WIDTH
8803#undef SET_CHAN_MAX
8804
8805/**
8806 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8807 * @wiphy: Pointer to wireless phy
8808 * @wdev: Pointer to wireless device
8809 * @data: Pointer to data
8810 * @data_len: Length of @data
8811 *
8812 * Return: 0 on success, negative errno on failure
8813 */
8814static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8815 struct wireless_dev *wdev,
8816 const void *data, int data_len)
8817{
8818 int ret_val;
8819 QDF_STATUS qdf_status;
8820 uint8_t channel_cnt = 0, reason = -1;
8821 struct hdd_vendor_chan_info *channel_list = NULL;
8822 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8823 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8824
8825 ENTER();
8826
8827 ret_val = wlan_hdd_validate_context(hdd_ctx);
8828 if (ret_val)
8829 return ret_val;
8830
8831 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8832 hdd_err("Command not allowed in FTM mode");
8833 return -EINVAL;
8834 }
8835
8836 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8837 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8838 else {
8839 hdd_err("already timeout happened for acs");
8840 return -EINVAL;
8841 }
8842
8843 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8844 &channel_cnt, data, data_len);
8845 if (ret_val)
8846 return ret_val;
8847
8848 /* Validate channel to be set */
8849 while (channel_cnt && channel_list) {
8850 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8851 channel_list->pri_ch,
8852 channel_list->chan_width);
8853 if (qdf_status == QDF_STATUS_SUCCESS)
8854 break;
8855 channel_cnt--;
8856 channel_list++;
8857 }
8858 if ((channel_cnt <= 0) || !channel_list) {
8859 hdd_err("no available channel/chanlist %p", channel_list);
8860 return -EINVAL;
8861 }
8862
8863 qdf_status = hdd_update_acs_channel(adapter, reason,
8864 channel_cnt, channel_list);
8865 return qdf_status_to_os_return(qdf_status);
8866}
8867
8868/**
8869 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8870 * @wiphy: Pointer to wireless phy
8871 * @wdev: Pointer to wireless device
8872 * @data: Pointer to data
8873 * @data_len: Length of @data
8874 *
8875 * Return: 0 on success, negative errno on failure
8876 */
8877static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8878 struct wireless_dev *wdev,
8879 const void *data, int data_len)
8880{
8881 int ret;
8882
8883 cds_ssr_protect(__func__);
8884 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8885 data_len);
8886 cds_ssr_protect(__func__);
8887
8888 return ret;
8889}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308890
8891/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308892 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8893 * @wiphy: wiphy structure pointer
8894 * @wdev: Wireless device structure pointer
8895 * @data: Pointer to the data received
8896 * @data_len: Length of @data
8897 *
8898 * Return: 0 on success; errno on failure
8899 */
8900static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8901 struct wireless_dev *wdev,
8902 const void *data, int data_len)
8903{
8904 int ret;
8905
8906 cds_ssr_protect(__func__);
8907 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8908 cds_ssr_unprotect(__func__);
8909
8910 return ret;
8911}
8912
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008913/**
8914 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8915 * @nl80211_value: Vendor command attribute value
8916 * @wmi_value: Pointer to return converted WMI return value
8917 *
8918 * Convert NL80211 vendor command value for SAR limit set to WMI value
8919 * Return: 0 on success, -1 on invalid value
8920 */
8921static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8922 u32 *wmi_value)
8923{
8924 int ret = 0;
8925
8926 switch (nl80211_value) {
8927 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8928 *wmi_value = WMI_SAR_FEATURE_OFF;
8929 break;
8930 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8931 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8932 break;
8933 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8934 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8935 break;
8936 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8937 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8938 break;
8939 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8940 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8941 break;
8942 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8943 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8944 break;
8945 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8946 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8947 break;
8948 default:
8949 ret = -1;
8950 }
8951 return ret;
8952}
8953
8954/**
8955 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8956 * @nl80211_value: Vendor command attribute value
8957 * @wmi_value: Pointer to return converted WMI return value
8958 *
8959 * Convert NL80211 vendor command value for SAR BAND to WMI value
8960 * Return: 0 on success, -1 on invalid value
8961 */
8962static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8963{
8964 int ret = 0;
8965
8966 switch (nl80211_value) {
8967 case NL80211_BAND_2GHZ:
8968 *wmi_value = WMI_SAR_2G_ID;
8969 break;
8970 case NL80211_BAND_5GHZ:
8971 *wmi_value = WMI_SAR_5G_ID;
8972 break;
8973 default:
8974 ret = -1;
8975 }
8976 return ret;
8977}
8978
8979/**
8980 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8981 * @nl80211_value: Vendor command attribute value
8982 * @wmi_value: Pointer to return converted WMI return value
8983 *
8984 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8985 * Return: 0 on success, -1 on invalid value
8986 */
8987static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8988 u32 *wmi_value)
8989{
8990 int ret = 0;
8991
8992 switch (nl80211_value) {
8993 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8994 *wmi_value = WMI_SAR_MOD_CCK;
8995 break;
8996 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8997 *wmi_value = WMI_SAR_MOD_OFDM;
8998 break;
8999 default:
9000 ret = -1;
9001 }
9002 return ret;
9003}
9004
9005
9006/**
9007 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9008 * @wiphy: Pointer to wireless phy
9009 * @wdev: Pointer to wireless device
9010 * @data: Pointer to data
9011 * @data_len: Length of @data
9012 *
9013 * This function is used to setup Specific Absorption Rate limit specs.
9014 *
9015 * Return: 0 on success, negative errno on failure
9016 */
9017static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9018 struct wireless_dev *wdev,
9019 const void *data, int data_len)
9020{
9021 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9022 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9023 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9024 *sar_spec_list;
9025 struct sar_limit_cmd_params sar_limit_cmd = {0};
9026 int ret = -EINVAL, i = 0, rem = 0;
9027
9028 ENTER();
9029
9030 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9031 hdd_err("Command not allowed in FTM mode");
9032 return -EPERM;
9033 }
9034
9035 if (wlan_hdd_validate_context(hdd_ctx))
9036 return -EINVAL;
9037
9038 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9039 data, data_len, NULL)) {
9040 hdd_err("Invalid SAR attributes");
9041 return -EINVAL;
9042 }
9043
9044 /* Vendor command manadates all SAR Specs in single call */
9045 sar_limit_cmd.commit_limits = 1;
9046 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9047 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9048 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9049 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9050 &sar_limit_cmd.sar_enable) < 0) {
9051 hdd_err("Invalid SAR Enable attr");
9052 goto fail;
9053 }
9054 }
9055 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9056
9057 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9058 sar_limit_cmd.num_limit_rows = nla_get_u32(
9059 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9060 hdd_info("attr sar num_limit_rows %d",
9061 sar_limit_cmd.num_limit_rows);
9062 }
9063 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9064 hdd_err("SAR Spec list exceed supported size");
9065 goto fail;
9066 }
9067 if (sar_limit_cmd.num_limit_rows == 0)
9068 goto send_sar_limits;
9069 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9070 struct sar_limit_cmd_row) *
9071 sar_limit_cmd.num_limit_rows);
9072 if (!sar_limit_cmd.sar_limit_row_list) {
9073 ret = -ENOMEM;
9074 goto fail;
9075 }
9076 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9077 hdd_err("Invalid SAR SPECs list");
9078 goto fail;
9079 }
9080
9081 nla_for_each_nested(sar_spec_list,
9082 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9083 if (i == sar_limit_cmd.num_limit_rows) {
9084 hdd_warn("SAR Cmd has excess SPECs in list");
9085 break;
9086 }
9087
9088 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9089 nla_data(sar_spec_list), nla_len(sar_spec_list),
9090 NULL)) {
9091 hdd_err("nla_parse failed for SAR Spec list");
9092 goto fail;
9093 }
9094 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9095 if (sar_spec[
9096 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9097 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9098 nla_get_u32(sar_spec[
9099 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9100 } else {
9101 hdd_err("SAR Spec does not have power limit value");
9102 goto fail;
9103 }
9104
9105 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9106 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9107 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9108 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9109 < 0) {
9110 hdd_err("Invalid SAR Band attr");
9111 goto fail;
9112 }
9113 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9114 WMI_SAR_BAND_ID_VALID_MASK;
9115 }
9116 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9117 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9118 nla_get_u32(sar_spec[
9119 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9120 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9121 WMI_SAR_CHAIN_ID_VALID_MASK;
9122 }
9123 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9124 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9125 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9126 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9127 < 0) {
9128 hdd_err("Invalid SAR Modulation attr");
9129 goto fail;
9130 }
9131 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9132 WMI_SAR_MOD_ID_VALID_MASK;
9133 }
9134 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9135 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9136 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9137 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9138 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9139 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9140 i++;
9141 }
9142
9143 if (i < sar_limit_cmd.num_limit_rows) {
9144 hdd_warn("SAR Cmd has less SPECs in list");
9145 sar_limit_cmd.num_limit_rows = i;
9146 }
9147
9148send_sar_limits:
9149 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9150 QDF_STATUS_SUCCESS)
9151 ret = 0;
9152fail:
9153 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9154 return ret;
9155}
9156
9157/**
9158 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9159 * @wiphy: Pointer to wireless phy
9160 * @wdev: Pointer to wireless device
9161 * @data: Pointer to data
9162 * @data_len: Length of @data
9163 *
9164 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9165 *
9166 * Return: 0 on success, negative errno on failure
9167 */
9168static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9169 struct wireless_dev *wdev,
9170 const void *data,
9171 int data_len)
9172{
9173 int ret;
9174
9175 cds_ssr_protect(__func__);
9176 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9177 data_len);
9178 cds_ssr_unprotect(__func__);
9179
9180 return ret;
9181}
9182
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309183static const struct
9184nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9185 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9186 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9187 .len = QDF_MAC_ADDR_SIZE},
9188};
9189
9190/**
9191 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9192 * @wiphy: Pointer to wireless phy
9193 * @wdev: Pointer to wireless device
9194 * @data: Pointer to data
9195 * @data_len: Length of @data
9196 *
9197 * This function is used to enable/disable roaming using vendor commands
9198 *
9199 * Return: 0 on success, negative errno on failure
9200 */
9201static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9202 struct wireless_dev *wdev,
9203 const void *data, int data_len)
9204{
9205 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9206 struct net_device *dev = wdev->netdev;
9207 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9208 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9209 uint32_t is_fast_roam_enabled;
9210 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309211 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309212
9213 ENTER_DEV(dev);
9214
9215 ret = wlan_hdd_validate_context(hdd_ctx);
9216 if (0 != ret)
9217 return ret;
9218
9219 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9220 hdd_err("Command not allowed in FTM mode");
9221 return -EINVAL;
9222 }
9223
9224 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9225 qca_wlan_vendor_attr);
9226 if (ret) {
9227 hdd_err("Invalid ATTR");
9228 return -EINVAL;
9229 }
9230
9231 /* Parse and fetch Enable flag */
9232 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9233 hdd_err("attr enable failed");
9234 return -EINVAL;
9235 }
9236
9237 is_fast_roam_enabled = nla_get_u32(
9238 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009239 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9240 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309241
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009242 if (!adapter->fast_roaming_allowed) {
9243 hdd_err("fast roaming not allowed on %s interface",
9244 adapter->dev->name);
9245 return -EINVAL;
9246 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309247 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309248 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009249 (is_fast_roam_enabled &&
9250 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309251 if (qdf_status != QDF_STATUS_SUCCESS)
9252 hdd_err("sme_config_fast_roaming failed with status=%d",
9253 qdf_status);
9254 ret = qdf_status_to_os_return(qdf_status);
9255
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309256 EXIT();
9257 return ret;
9258}
9259
9260/**
9261 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9262 * @wiphy: Pointer to wireless phy
9263 * @wdev: Pointer to wireless device
9264 * @data: Pointer to data
9265 * @data_len: Length of @data
9266 *
9267 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9268 *
9269 * Return: 0 on success, negative errno on failure
9270 */
9271static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9272 struct wireless_dev *wdev,
9273 const void *data, int data_len)
9274{
9275 int ret;
9276
9277 cds_ssr_protect(__func__);
9278 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9279 cds_ssr_unprotect(__func__);
9280
9281 return ret;
9282}
9283
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309284static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9285 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9286 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9287 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9288 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9289};
9290
9291/**
9292 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9293 * @wiphy: Pointer to wireless phy
9294 * @wdev: Pointer to wireless device
9295 * @data: Pointer to data
9296 * @data_len: Length of @data
9297 *
9298 * Return: 0 on success, negative errno on failure
9299 */
9300static int
9301__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9302 struct wireless_dev *wdev,
9303 const void *data,
9304 int data_len)
9305{
9306 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9307 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9308 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9309 struct nlattr *apth;
9310 int rem;
9311 int ret = 1;
9312 int print_idx = -1;
9313 int module_id = -1;
9314 int bit_mask = -1;
9315 int status;
9316
9317 ENTER();
9318
9319 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9320 hdd_err("Command not allowed in FTM mode");
9321 return -EINVAL;
9322 }
9323
9324 ret = wlan_hdd_validate_context(hdd_ctx);
9325 if (ret != 0)
9326 return -EINVAL;
9327
9328 print_idx = qdf_get_pidx();
9329 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9330 hdd_err("Invalid print controle object index");
9331 return -EINVAL;
9332 }
9333
9334 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9335 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9336 hdd_err("Invalid attr");
9337 return -EINVAL;
9338 }
9339
9340 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9341 hdd_err("attr trace level param failed");
9342 return -EINVAL;
9343 }
9344
9345 nla_for_each_nested(apth,
9346 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9347 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9348 nla_data(apth), nla_len(apth), NULL)) {
9349 hdd_err("Invalid attr");
9350 return -EINVAL;
9351 }
9352
9353 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9354 hdd_err("attr Module ID failed");
9355 return -EINVAL;
9356 }
9357 module_id = nla_get_u32
9358 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9359
9360 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9361 hdd_err("attr Verbose mask failed");
9362 return -EINVAL;
9363 }
9364 bit_mask = nla_get_u32
9365 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9366
9367 status = hdd_qdf_trace_enable(module_id, bit_mask);
9368
9369 if (status != 0)
9370 hdd_err("can not set verbose mask %d for the category %d",
9371 bit_mask, module_id);
9372 }
9373
9374 EXIT();
9375 return ret;
9376}
9377
9378/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309379 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9380 * @wiphy: Pointer to wireless phy
9381 * @wdev: Pointer to wireless device
9382 * @data: Pointer to data
9383 * @data_len: Length of @data
9384 *
9385 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9386 *
9387 * Return: 0 on success, negative errno on failure
9388 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309389
9390static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9391 struct wireless_dev *wdev,
9392 const void *data,
9393 int data_len)
9394{
9395 int ret;
9396
9397 cds_ssr_protect(__func__);
9398 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9399 cds_ssr_unprotect(__func__);
9400
9401 return ret;
9402}
9403
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009404const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9405 {
9406 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9407 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9408 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309409 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009410 .doit = is_driver_dfs_capable
9411 },
9412
9413#ifdef WLAN_FEATURE_NAN
9414 {
9415 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9416 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9417 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9418 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9419 .doit = wlan_hdd_cfg80211_nan_request
9420 },
9421#endif
9422
9423#ifdef WLAN_FEATURE_STATS_EXT
9424 {
9425 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9426 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9427 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9428 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9429 .doit = wlan_hdd_cfg80211_stats_ext_request
9430 },
9431#endif
9432#ifdef FEATURE_WLAN_EXTSCAN
9433 {
9434 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9435 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9436 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9437 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9438 .doit = wlan_hdd_cfg80211_extscan_start
9439 },
9440 {
9441 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9442 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9443 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9444 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9445 .doit = wlan_hdd_cfg80211_extscan_stop
9446 },
9447 {
9448 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9449 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9450 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9451 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9452 },
9453 {
9454 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9455 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9456 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9457 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9458 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9459 },
9460 {
9461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9464 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9465 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9466 },
9467 {
9468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9471 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9472 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9473 },
9474 {
9475 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9476 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9477 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9478 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9479 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9480 },
9481 {
9482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9483 .info.subcmd =
9484 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9485 .flags =
9486 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9487 WIPHY_VENDOR_CMD_NEED_RUNNING,
9488 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9489 },
9490 {
9491 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9492 .info.subcmd =
9493 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9494 .flags =
9495 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9496 WIPHY_VENDOR_CMD_NEED_RUNNING,
9497 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9498 },
9499 {
9500 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9501 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9502 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9503 WIPHY_VENDOR_CMD_NEED_NETDEV |
9504 WIPHY_VENDOR_CMD_NEED_RUNNING,
9505 .doit = wlan_hdd_cfg80211_set_epno_list
9506 },
9507#endif /* FEATURE_WLAN_EXTSCAN */
9508
9509#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9510 {
9511 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9512 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9513 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9514 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9515 .doit = wlan_hdd_cfg80211_ll_stats_clear
9516 },
9517
9518 {
9519 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9520 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9521 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9522 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9523 .doit = wlan_hdd_cfg80211_ll_stats_set
9524 },
9525
9526 {
9527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9528 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9529 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9530 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9531 .doit = wlan_hdd_cfg80211_ll_stats_get
9532 },
9533#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9534#ifdef FEATURE_WLAN_TDLS
9535 {
9536 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9537 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9538 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9539 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9540 .doit = wlan_hdd_cfg80211_exttdls_enable
9541 },
9542 {
9543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9544 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9546 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9547 .doit = wlan_hdd_cfg80211_exttdls_disable
9548 },
9549 {
9550 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9551 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9552 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9553 .doit = wlan_hdd_cfg80211_exttdls_get_status
9554 },
9555#endif
9556 {
9557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9558 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9559 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9560 .doit = wlan_hdd_cfg80211_get_supported_features
9561 },
9562 {
9563 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9564 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9565 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9566 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9567 },
9568 {
9569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309572 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009573 },
9574 {
9575 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9576 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9577 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9578 WIPHY_VENDOR_CMD_NEED_NETDEV,
9579 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9580 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009581 {
9582 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9583 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9584 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9585 WIPHY_VENDOR_CMD_NEED_NETDEV,
9586 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9587 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009588 {
9589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9592 WIPHY_VENDOR_CMD_NEED_NETDEV |
9593 WIPHY_VENDOR_CMD_NEED_RUNNING,
9594 .doit = hdd_cfg80211_get_station_cmd
9595 },
9596 {
9597 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009598 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9599 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9600 WIPHY_VENDOR_CMD_NEED_NETDEV |
9601 WIPHY_VENDOR_CMD_NEED_RUNNING,
9602 .doit = wlan_hdd_cfg80211_do_acs
9603 },
9604
9605 {
9606 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9607 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9608 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9609 WIPHY_VENDOR_CMD_NEED_NETDEV,
9610 .doit = wlan_hdd_cfg80211_get_features
9611 },
9612#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9613 {
9614 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9615 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9616 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9617 WIPHY_VENDOR_CMD_NEED_NETDEV |
9618 WIPHY_VENDOR_CMD_NEED_RUNNING,
9619 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9620 },
9621#endif
9622#ifdef FEATURE_WLAN_EXTSCAN
9623 {
9624 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9625 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9626 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9627 WIPHY_VENDOR_CMD_NEED_NETDEV |
9628 WIPHY_VENDOR_CMD_NEED_RUNNING,
9629 .doit = wlan_hdd_cfg80211_set_passpoint_list
9630 },
9631 {
9632 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9633 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9634 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9635 WIPHY_VENDOR_CMD_NEED_NETDEV |
9636 WIPHY_VENDOR_CMD_NEED_RUNNING,
9637 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9638 },
9639 {
9640 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9641 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9642 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9643 WIPHY_VENDOR_CMD_NEED_NETDEV |
9644 WIPHY_VENDOR_CMD_NEED_RUNNING,
9645 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9646 },
9647 {
9648 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9649 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9650 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9651 WIPHY_VENDOR_CMD_NEED_NETDEV |
9652 WIPHY_VENDOR_CMD_NEED_RUNNING,
9653 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9654 },
9655#endif /* FEATURE_WLAN_EXTSCAN */
9656 {
9657 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9658 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9659 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9660 WIPHY_VENDOR_CMD_NEED_NETDEV,
9661 .doit = wlan_hdd_cfg80211_get_wifi_info
9662 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009663#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009664 {
9665 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9666 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9667 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9668 WIPHY_VENDOR_CMD_NEED_NETDEV |
9669 WIPHY_VENDOR_CMD_NEED_RUNNING,
9670 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9671 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009672#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009673 {
9674 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9675 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9676 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9677 WIPHY_VENDOR_CMD_NEED_NETDEV,
9678 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9679 },
9680 {
9681 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9682 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9683 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9684 WIPHY_VENDOR_CMD_NEED_NETDEV,
9685 .doit = wlan_hdd_cfg80211_wifi_logger_start
9686 },
9687 {
9688 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9689 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9690 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9691 WIPHY_VENDOR_CMD_NEED_NETDEV,
9692 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9693 },
9694 {
9695 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9696 .info.subcmd =
9697 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9698 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9699 WIPHY_VENDOR_CMD_NEED_NETDEV |
9700 WIPHY_VENDOR_CMD_NEED_RUNNING,
9701 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9702 },
9703 {
9704 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9705 .info.subcmd =
9706 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9707 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9708 WIPHY_VENDOR_CMD_NEED_NETDEV |
9709 WIPHY_VENDOR_CMD_NEED_RUNNING,
9710 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9711 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009712#ifdef WLAN_FEATURE_TSF
9713 {
9714 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9715 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9716 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9717 WIPHY_VENDOR_CMD_NEED_NETDEV |
9718 WIPHY_VENDOR_CMD_NEED_RUNNING,
9719 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9720 },
9721#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009722#ifdef FEATURE_WLAN_TDLS
9723 {
9724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9725 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9726 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9727 WIPHY_VENDOR_CMD_NEED_NETDEV |
9728 WIPHY_VENDOR_CMD_NEED_RUNNING,
9729 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9730 },
9731#endif
9732#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9733 {
9734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9737 WIPHY_VENDOR_CMD_NEED_NETDEV |
9738 WIPHY_VENDOR_CMD_NEED_RUNNING,
9739 .doit = wlan_hdd_cfg80211_offloaded_packets
9740 },
9741#endif
9742 {
9743 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9744 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9745 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9746 WIPHY_VENDOR_CMD_NEED_NETDEV |
9747 WIPHY_VENDOR_CMD_NEED_RUNNING,
9748 .doit = wlan_hdd_cfg80211_monitor_rssi
9749 },
9750 {
9751 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309752 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9753 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9754 WIPHY_VENDOR_CMD_NEED_NETDEV |
9755 WIPHY_VENDOR_CMD_NEED_RUNNING,
9756 .doit = wlan_hdd_cfg80211_set_ns_offload
9757 },
9758 {
9759 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9761 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9762 WIPHY_VENDOR_CMD_NEED_NETDEV |
9763 WIPHY_VENDOR_CMD_NEED_RUNNING,
9764 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9765 },
9766#ifdef WLAN_FEATURE_MEMDUMP
9767 {
9768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9769 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9770 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9771 WIPHY_VENDOR_CMD_NEED_NETDEV |
9772 WIPHY_VENDOR_CMD_NEED_RUNNING,
9773 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9774 },
9775#endif /* WLAN_FEATURE_MEMDUMP */
9776 {
9777 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9778 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9779 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9780 WIPHY_VENDOR_CMD_NEED_NETDEV |
9781 WIPHY_VENDOR_CMD_NEED_RUNNING,
9782 .doit = wlan_hdd_cfg80211_vendor_scan
9783 },
9784
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309785 /* Vendor abort scan */
9786 {
9787 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9788 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9789 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9790 WIPHY_VENDOR_CMD_NEED_NETDEV |
9791 WIPHY_VENDOR_CMD_NEED_RUNNING,
9792 .doit = wlan_hdd_vendor_abort_scan
9793 },
9794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009795 /* OCB commands */
9796 {
9797 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9798 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9799 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9800 WIPHY_VENDOR_CMD_NEED_NETDEV |
9801 WIPHY_VENDOR_CMD_NEED_RUNNING,
9802 .doit = wlan_hdd_cfg80211_ocb_set_config
9803 },
9804 {
9805 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9806 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9807 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9808 WIPHY_VENDOR_CMD_NEED_NETDEV |
9809 WIPHY_VENDOR_CMD_NEED_RUNNING,
9810 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9811 },
9812 {
9813 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9814 .info.subcmd =
9815 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9816 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9817 WIPHY_VENDOR_CMD_NEED_NETDEV |
9818 WIPHY_VENDOR_CMD_NEED_RUNNING,
9819 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9820 },
9821 {
9822 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9823 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9824 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9825 WIPHY_VENDOR_CMD_NEED_NETDEV |
9826 WIPHY_VENDOR_CMD_NEED_RUNNING,
9827 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9828 },
9829 {
9830 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9831 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9832 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9833 WIPHY_VENDOR_CMD_NEED_NETDEV |
9834 WIPHY_VENDOR_CMD_NEED_RUNNING,
9835 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9836 },
9837 {
9838 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9839 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9840 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9841 WIPHY_VENDOR_CMD_NEED_NETDEV |
9842 WIPHY_VENDOR_CMD_NEED_RUNNING,
9843 .doit = wlan_hdd_cfg80211_dcc_get_stats
9844 },
9845 {
9846 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9847 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9848 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9849 WIPHY_VENDOR_CMD_NEED_NETDEV |
9850 WIPHY_VENDOR_CMD_NEED_RUNNING,
9851 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9852 },
9853 {
9854 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9855 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9856 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9857 WIPHY_VENDOR_CMD_NEED_NETDEV |
9858 WIPHY_VENDOR_CMD_NEED_RUNNING,
9859 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9860 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309861 {
9862 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9863 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9864 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9865 WIPHY_VENDOR_CMD_NEED_NETDEV |
9866 WIPHY_VENDOR_CMD_NEED_RUNNING,
9867 .doit = wlan_hdd_cfg80211_get_link_properties
9868 },
Peng Xu278d0122015-09-24 16:34:17 -07009869 {
Peng Xud2220962016-07-11 17:59:17 -07009870 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009871 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9872 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9873 WIPHY_VENDOR_CMD_NEED_NETDEV |
9874 WIPHY_VENDOR_CMD_NEED_RUNNING,
9875 .doit = wlan_hdd_cfg80211_set_ota_test
9876 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009877#ifdef FEATURE_LFR_SUBNET_DETECTION
9878 {
9879 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9880 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9881 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9882 WIPHY_VENDOR_CMD_NEED_NETDEV |
9883 WIPHY_VENDOR_CMD_NEED_RUNNING,
9884 .doit = wlan_hdd_cfg80211_set_gateway_params
9885 },
9886#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009887 {
Peng Xud2220962016-07-11 17:59:17 -07009888 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009889 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9890 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9891 WIPHY_VENDOR_CMD_NEED_NETDEV |
9892 WIPHY_VENDOR_CMD_NEED_RUNNING,
9893 .doit = wlan_hdd_cfg80211_txpower_scale
9894 },
9895 {
9896 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9897 .info.subcmd =
9898 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9899 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9900 WIPHY_VENDOR_CMD_NEED_NETDEV |
9901 WIPHY_VENDOR_CMD_NEED_RUNNING,
9902 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9903 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309904 {
9905 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9906 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9907 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9908 WIPHY_VENDOR_CMD_NEED_NETDEV |
9909 WIPHY_VENDOR_CMD_NEED_RUNNING,
9910 .doit = wlan_hdd_cfg80211_bpf_offload
9911 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309912 {
9913 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309914 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9915 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9916 WIPHY_VENDOR_CMD_NEED_NETDEV |
9917 WIPHY_VENDOR_CMD_NEED_RUNNING,
9918 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9919 },
9920 {
9921 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309922 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9923 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9924 WIPHY_VENDOR_CMD_NEED_NETDEV |
9925 WIPHY_VENDOR_CMD_NEED_RUNNING,
9926 .doit = wlan_hdd_cfg80211_sta_roam_policy
9927 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309928#ifdef FEATURE_WLAN_CH_AVOID
9929 {
9930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9931 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9933 WIPHY_VENDOR_CMD_NEED_NETDEV |
9934 WIPHY_VENDOR_CMD_NEED_RUNNING,
9935 .doit = wlan_hdd_cfg80211_avoid_freq
9936 },
9937#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309938 {
9939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9942 WIPHY_VENDOR_CMD_NEED_NETDEV |
9943 WIPHY_VENDOR_CMD_NEED_RUNNING,
9944 .doit = wlan_hdd_cfg80211_sap_configuration_set
9945 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009946 {
Peng Xu4225c152016-07-14 21:18:14 -07009947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009948 .info.subcmd =
9949 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9951 WIPHY_VENDOR_CMD_NEED_NETDEV |
9952 WIPHY_VENDOR_CMD_NEED_RUNNING,
9953 .doit = wlan_hdd_cfg80211_p2p_lo_start
9954 },
9955 {
9956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9957 .info.subcmd =
9958 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9960 WIPHY_VENDOR_CMD_NEED_NETDEV |
9961 WIPHY_VENDOR_CMD_NEED_RUNNING,
9962 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9963 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309964 {
9965 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9966 .info.subcmd =
9967 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9969 WIPHY_VENDOR_CMD_NEED_NETDEV |
9970 WIPHY_VENDOR_CMD_NEED_RUNNING,
9971 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9972 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009973#ifdef WLAN_FEATURE_NAN_DATAPATH
9974 {
9975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9976 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9977 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9978 WIPHY_VENDOR_CMD_NEED_NETDEV |
9979 WIPHY_VENDOR_CMD_NEED_RUNNING,
9980 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9981 },
9982#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309983 {
9984 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9985 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9986 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9987 WIPHY_VENDOR_CMD_NEED_NETDEV |
9988 WIPHY_VENDOR_CMD_NEED_RUNNING,
9989 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9990 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309991 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309992 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9993 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9994 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9995 WIPHY_VENDOR_CMD_NEED_NETDEV |
9996 WIPHY_VENDOR_CMD_NEED_RUNNING,
9997 .doit = wlan_hdd_cfg80211_get_bus_size
9998 },
9999 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010000 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10001 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10003 WIPHY_VENDOR_CMD_NEED_NETDEV |
10004 WIPHY_VENDOR_CMD_NEED_RUNNING,
10005 .doit = wlan_hdd_cfg80211_update_vendor_channel
10006 },
10007 {
bingsd09dea32017-03-17 10:08:26 +080010008 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010009 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10011 WIPHY_VENDOR_CMD_NEED_NETDEV |
10012 WIPHY_VENDOR_CMD_NEED_RUNNING,
10013 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010014 },
10015 {
10016 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10017 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10019 WIPHY_VENDOR_CMD_NEED_NETDEV |
10020 WIPHY_VENDOR_CMD_NEED_RUNNING,
10021 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010022 },
10023#ifdef WLAN_FEATURE_DISA
10024 {
10025 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10026 .info.subcmd =
10027 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10029 WIPHY_VENDOR_CMD_NEED_NETDEV |
10030 WIPHY_VENDOR_CMD_NEED_RUNNING,
10031 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10032 },
10033#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010034#ifdef FEATURE_WLAN_TDLS
10035 {
10036 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10037 .info.subcmd =
10038 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10040 WIPHY_VENDOR_CMD_NEED_NETDEV |
10041 WIPHY_VENDOR_CMD_NEED_RUNNING,
10042 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010043 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010044#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010045 {
10046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10049 WIPHY_VENDOR_CMD_NEED_RUNNING,
10050 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10051 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010052 {
10053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10056 WIPHY_VENDOR_CMD_NEED_NETDEV |
10057 WIPHY_VENDOR_CMD_NEED_RUNNING,
10058 .doit = wlan_hdd_cfg80211_set_trace_level
10059 },
10060
Paul Zhang3a210c52016-12-08 10:18:12 +080010061#ifdef WLAN_UMAC_CONVERGENCE
10062 COMMON_VENDOR_COMMANDS
10063#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010064 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010065};
10066
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010067#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10068 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10069 defined(FEATURE_WLAN_SCAN_PNO)
10070/**
10071 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10072 * @wiphy: pointer to wiphy
10073 * @config: pointer to config
10074 *
10075 * Return: None
10076 */
10077static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10078 struct hdd_config *config)
10079{
10080 if (config->configPNOScanSupport) {
10081 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10082 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10083 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10084 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10085 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10086 if (config->max_sched_scan_plan_interval)
10087 wiphy->max_sched_scan_plan_interval =
10088 config->max_sched_scan_plan_interval;
10089 if (config->max_sched_scan_plan_iterations)
10090 wiphy->max_sched_scan_plan_iterations =
10091 config->max_sched_scan_plan_iterations;
10092 }
10093}
10094#else
10095static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10096 struct hdd_config *config)
10097{
10098}
10099#endif
10100
10101
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010102/**
10103 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10104 * @priv_size: Size of the hdd context.
10105 *
10106 * Allocate wiphy context and hdd context.
10107 *
10108 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010110hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010111{
10112 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010113 hdd_context_t *hdd_ctx;
10114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010115 ENTER();
10116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10118
10119 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010120 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010121 return NULL;
10122 }
10123
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010124 hdd_ctx = wiphy_priv(wiphy);
10125
10126 hdd_ctx->wiphy = wiphy;
10127
10128 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129}
10130
10131/*
10132 * FUNCTION: wlan_hdd_cfg80211_update_band
10133 * This function is called from the supplicant through a
10134 * private ioctl to change the band value
10135 */
10136int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10137{
10138 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010139 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140
10141 ENTER();
10142
Dustin Browna30892e2016-10-12 17:28:36 -070010143 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010144
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010145 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010146 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147
10148 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10149 struct ieee80211_supported_band *band = wiphy->bands[i];
10150
10151 channelEnabledState =
10152 cds_get_channel_state(band->channels[j].
10153 hw_value);
10154
Dustin Browna30892e2016-10-12 17:28:36 -070010155 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010156 /* 5G only */
10157#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10158 /* Enable Social channels for P2P */
10159 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10160 (band->channels[j].center_freq)
10161 && CHANNEL_STATE_ENABLE ==
10162 channelEnabledState)
10163 band->channels[j].flags &=
10164 ~IEEE80211_CHAN_DISABLED;
10165 else
10166#endif
10167 band->channels[j].flags |=
10168 IEEE80211_CHAN_DISABLED;
10169 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010170 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171 eCSR_BAND_24 == eBand) {
10172 /* 2G only */
10173 band->channels[j].flags |=
10174 IEEE80211_CHAN_DISABLED;
10175 continue;
10176 }
10177
Amar Singhal6842e8f2016-02-23 16:30:32 -080010178 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010179 band->channels[j].flags &=
10180 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010181 }
10182 }
10183 return 0;
10184}
10185
Peng Xuacfdda12017-02-06 16:15:38 -080010186#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187/*
10188 * FUNCTION: wlan_hdd_cfg80211_init
10189 * This function is called by hdd_wlan_startup()
10190 * during initialization.
10191 * This function is used to initialize and register wiphy structure.
10192 */
10193int wlan_hdd_cfg80211_init(struct device *dev,
10194 struct wiphy *wiphy, struct hdd_config *pCfg)
10195{
10196 int i, j;
10197 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10198
10199 ENTER();
10200
10201 /* Now bind the underlying wlan device with wiphy */
10202 set_wiphy_dev(wiphy, dev);
10203
10204 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10205
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010206#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10207 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010208 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010209#else
10210 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010211 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010212#endif
10213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10215 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10216 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10217#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10218 | WIPHY_FLAG_4ADDR_STATION
10219#endif
10220 | WIPHY_FLAG_OFFCHAN_TX;
10221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010222#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10223 wiphy->wowlan = &wowlan_support_cfg80211_init;
10224#else
10225 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10226 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10227 wiphy->wowlan.pattern_min_len = 1;
10228 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10229#endif
10230
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010231 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010232#ifdef FEATURE_WLAN_ESE
10233 || pCfg->isEseIniFeatureEnabled
10234#endif
10235 ) {
10236 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10237 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010238#ifdef FEATURE_WLAN_TDLS
10239 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10240 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10241#endif
10242
10243 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10244
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010245#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10246 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10247#endif
10248
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010249 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250
10251#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010252 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253#endif
10254
10255 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010256 * driver can still register regulatory callback and
10257 * it will get regulatory settings in wiphy->band[], but
10258 * driver need to determine what to do with both
10259 * regulatory settings
10260 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261
10262 wiphy->reg_notifier = hdd_reg_notifier;
10263
10264#if defined QCA_WIFI_FTM
10265}
10266#endif
10267
10268 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10269
10270 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10271
10272 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10273
Arun Khandavallifae92942016-08-01 13:31:08 +053010274 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10275 | BIT(NL80211_IFTYPE_ADHOC)
10276 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10277 | BIT(NL80211_IFTYPE_P2P_GO)
10278 | BIT(NL80211_IFTYPE_AP)
10279 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010280
Arun Khandavallifae92942016-08-01 13:31:08 +053010281 if (pCfg->advertiseConcurrentOperation) {
10282 if (pCfg->enableMCC) {
10283 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010284
Arun Khandavallifae92942016-08-01 13:31:08 +053010285 for (i = 0;
10286 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10287 i++) {
10288 if (!pCfg->allowMCCGODiffBI)
10289 wlan_hdd_iface_combination[i].
10290 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010291 }
10292 }
10293 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010294 ARRAY_SIZE(wlan_hdd_iface_combination);
10295 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010296 }
10297
10298 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010299 * on ini values
10300 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301 if (!pCfg->ShortGI20MhzEnable) {
10302 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10303 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010304 }
10305
10306 if (!pCfg->ShortGI40MhzEnable) {
10307 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10308 }
10309
10310 if (!pCfg->nChannelBondingMode5GHz) {
10311 wlan_hdd_band_5_ghz.ht_cap.cap &=
10312 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10313 }
10314
Abhishek Singhf512bf32016-05-04 16:47:46 +053010315 /*
10316 * In case of static linked driver at the time of driver unload,
10317 * module exit doesn't happens. Module cleanup helps in cleaning
10318 * of static memory.
10319 * If driver load happens statically, at the time of driver unload,
10320 * wiphy flags don't get reset because of static memory.
10321 * It's better not to store channel in static memory.
10322 */
Dustin Browna30892e2016-10-12 17:28:36 -070010323 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10324 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010325 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010326 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010327 hdd_err("Not enough memory to allocate channels");
10328 return -ENOMEM;
10329 }
Dustin Browna30892e2016-10-12 17:28:36 -070010330 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010331 &hdd_channels_2_4_ghz[0],
10332 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010333 if ((hdd_is_5g_supported(pHddCtx)) &&
10334 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10335 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10336 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10337 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010338 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10339 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010340 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010341 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010342 hdd_err("Not enough memory to allocate channels");
10343 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010344 bands[NL80211_BAND_2GHZ]->channels);
10345 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010346 return -ENOMEM;
10347 }
Dustin Browna30892e2016-10-12 17:28:36 -070010348 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010349 &hdd_channels_5_ghz[0],
10350 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010351 }
10352
Dustin Browna30892e2016-10-12 17:28:36 -070010353 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010355 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010357
10358 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10359 struct ieee80211_supported_band *band = wiphy->bands[i];
10360
Dustin Browna30892e2016-10-12 17:28:36 -070010361 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010362 eCSR_BAND_5G == pCfg->nBandCapability) {
10363 /* 5G only */
10364#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10365 /* Enable social channels for P2P */
10366 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10367 (band->channels[j].center_freq))
10368 band->channels[j].flags &=
10369 ~IEEE80211_CHAN_DISABLED;
10370 else
10371#endif
10372 band->channels[j].flags |=
10373 IEEE80211_CHAN_DISABLED;
10374 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010375 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 eCSR_BAND_24 == pCfg->nBandCapability) {
10377 /* 2G only */
10378 band->channels[j].flags |=
10379 IEEE80211_CHAN_DISABLED;
10380 continue;
10381 }
10382 }
10383 }
10384 /*Initialise the supported cipher suite details */
10385 wiphy->cipher_suites = hdd_cipher_suites;
10386 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10387
10388 /*signal strength in mBm (100*dBm) */
10389 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10390 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10391
Anurag Chouhan6d760662016-02-20 16:05:43 +053010392 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010393 wiphy->n_vendor_commands =
10394 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10395 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10396
10397 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10398 wiphy->n_vendor_events =
10399 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10400 }
10401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010402 if (pCfg->enableDFSMasterCap) {
10403 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10404 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010405
10406 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10407
10408#ifdef QCA_HT_2040_COEX
10409 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10410#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010411 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010412
10413#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10414 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10415 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10416 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10417 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10418#endif
10419
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010420 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010421 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010423 EXIT();
10424 return 0;
10425}
10426
Abhishek Singhf512bf32016-05-04 16:47:46 +053010427/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010428 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10429 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010430 *
10431 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010432 * memory allocated in wlan_hdd_cfg80211_init also
10433 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010434 *
10435 * Return: void
10436 */
10437void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10438{
10439 int i;
10440
Dustin Browna30892e2016-10-12 17:28:36 -070010441 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010442 if (NULL != wiphy->bands[i] &&
10443 (NULL != wiphy->bands[i]->channels)) {
10444 qdf_mem_free(wiphy->bands[i]->channels);
10445 wiphy->bands[i]->channels = NULL;
10446 }
10447 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010448 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010449}
10450
Yingying Tang80e15f32016-09-27 18:23:01 +080010451/**
10452 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10453 * @hdd_ctx: HDD context
10454 *
10455 * this function will update capabilities for supported bands
10456 *
10457 * Return: void
10458 */
10459static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10460{
10461 uint32_t val32;
10462 uint16_t val16;
10463 tSirMacHTCapabilityInfo *ht_cap_info;
10464 QDF_STATUS status;
10465
10466 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10467 if (QDF_STATUS_SUCCESS != status) {
10468 hdd_err("could not get HT capability info");
10469 val32 = 0;
10470 }
10471 val16 = (uint16_t)val32;
10472 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10473
10474 if (ht_cap_info->txSTBC == true) {
10475 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10476 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10477 IEEE80211_HT_CAP_TX_STBC;
10478 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10479 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10480 IEEE80211_HT_CAP_TX_STBC;
10481 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010482
10483 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10484 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10485 vht_cap.vht_supported = 0;
10486 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10487 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10488 vht_cap.vht_supported = 0;
10489 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10490 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010491}
10492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010493/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010494 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010495 * initialization. In wlan_hdd_cfg80211_init, only the
10496 * default values will be initialized. The final initialization
10497 * of all required members can be done here.
10498 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010499void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010500{
Yingying Tang80e15f32016-09-27 18:23:01 +080010501 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10502
10503 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010504}
10505
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010506/**
10507 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10508 * @cfg: hdd cfg
10509 *
10510 * this function update 11n mode in hdd cfg
10511 *
10512 * Return: void
10513 */
10514void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10515{
10516 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10517 hdd_notice("support 11ac");
10518 } else {
10519 hdd_notice("not support 11ac");
10520 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10521 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10522 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10523 cfg->sap_p2p_11ac_override = 0;
10524 }
10525 }
10526}
10527
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010528/* In this function we are registering wiphy. */
10529int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10530{
10531 ENTER();
10532 /* Register our wiphy dev with cfg80211 */
10533 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010534 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010535 return -EIO;
10536 }
10537
10538 EXIT();
10539 return 0;
10540}
10541
10542/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010543 * HDD function to update wiphy capability based on target offload status.
10544 *
10545 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10546 * capability even before downloading firmware to the target. In discrete
10547 * case, host will get know certain offload capability (say sched_scan
10548 * caps) only after downloading firmware to the target and target boots up.
10549 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10550 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010551 */
10552void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10553{
10554#ifdef FEATURE_WLAN_SCAN_PNO
10555 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10556 struct hdd_config *pCfg = pHddCtx->config;
10557
10558 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10559 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010560 * have PNO support.
10561 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562 if (!pCfg->PnoOffload) {
10563 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10564 wiphy->max_sched_scan_ssids = 0;
10565 wiphy->max_match_sets = 0;
10566 wiphy->max_sched_scan_ie_len = 0;
10567 }
10568#endif
10569}
10570
10571/* This function registers for all frame which supplicant is interested in */
Wu Gao84d120c2017-03-24 18:46:00 +080010572#ifdef CONVERGED_P2P_ENABLE
10573void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10574{
10575 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10576 /* Register for all P2P action, public action etc frames */
10577 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10578
10579 ENTER();
10580
10581 /* Register frame indication call back */
10582 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10583
10584 /* Register for p2p ack indication */
10585 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10586
10587 /* Right now we are registering these frame when driver is getting
10588 * initialized. Once we will move to 2.6.37 kernel, in which we have
10589 * frame register ops, we will move this code as a part of that
10590 */
10591
10592 /* GAS Initial Request */
10593 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10594 (uint8_t *) GAS_INITIAL_REQ,
10595 GAS_INITIAL_REQ_SIZE);
10596
10597 /* GAS Initial Response */
10598 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10599 (uint8_t *) GAS_INITIAL_RSP,
10600 GAS_INITIAL_RSP_SIZE);
10601
10602 /* GAS Comeback Request */
10603 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10604 (uint8_t *) GAS_COMEBACK_REQ,
10605 GAS_COMEBACK_REQ_SIZE);
10606
10607 /* GAS Comeback Response */
10608 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10609 (uint8_t *) GAS_COMEBACK_RSP,
10610 GAS_COMEBACK_RSP_SIZE);
10611
10612 /* WNM BSS Transition Request frame */
10613 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10614 (uint8_t *) WNM_BSS_ACTION_FRAME,
10615 WNM_BSS_ACTION_FRAME_SIZE);
10616
10617 /* WNM-Notification */
10618 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10619 (uint8_t *) WNM_NOTIFICATION_FRAME,
10620 WNM_NOTIFICATION_FRAME_SIZE);
10621}
10622#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010623void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10624{
10625 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10626 /* Register for all P2P action, public action etc frames */
10627 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10628
10629 ENTER();
10630
Abhishek Singh7996eb72015-12-30 17:24:02 +053010631 /* Register frame indication call back */
10632 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10633
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010634 /* Register for p2p ack indication */
10635 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10636
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010637 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010638 * initialized. Once we will move to 2.6.37 kernel, in which we have
10639 * frame register ops, we will move this code as a part of that
10640 */
10641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010642 /* GAS Initial Request */
10643 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10644 (uint8_t *) GAS_INITIAL_REQ,
10645 GAS_INITIAL_REQ_SIZE);
10646
10647 /* GAS Initial Response */
10648 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10649 (uint8_t *) GAS_INITIAL_RSP,
10650 GAS_INITIAL_RSP_SIZE);
10651
10652 /* GAS Comeback Request */
10653 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10654 (uint8_t *) GAS_COMEBACK_REQ,
10655 GAS_COMEBACK_REQ_SIZE);
10656
10657 /* GAS Comeback Response */
10658 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10659 (uint8_t *) GAS_COMEBACK_RSP,
10660 GAS_COMEBACK_RSP_SIZE);
10661
10662 /* P2P Public Action */
10663 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10664 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10665 P2P_PUBLIC_ACTION_FRAME_SIZE);
10666
10667 /* P2P Action */
10668 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10669 (uint8_t *) P2P_ACTION_FRAME,
10670 P2P_ACTION_FRAME_SIZE);
10671
10672 /* WNM BSS Transition Request frame */
10673 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10674 (uint8_t *) WNM_BSS_ACTION_FRAME,
10675 WNM_BSS_ACTION_FRAME_SIZE);
10676
10677 /* WNM-Notification */
10678 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10679 (uint8_t *) WNM_NOTIFICATION_FRAME,
10680 WNM_NOTIFICATION_FRAME_SIZE);
10681}
Wu Gao84d120c2017-03-24 18:46:00 +080010682#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010683
10684void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10685{
10686 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10687 /* Register for all P2P action, public action etc frames */
10688 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10689
10690 ENTER();
10691
10692 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010693 * initialized. Once we will move to 2.6.37 kernel, in which we have
10694 * frame register ops, we will move this code as a part of that
10695 */
10696
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 /* GAS Initial Request */
10698
10699 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10700 (uint8_t *) GAS_INITIAL_REQ,
10701 GAS_INITIAL_REQ_SIZE);
10702
10703 /* GAS Initial Response */
10704 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10705 (uint8_t *) GAS_INITIAL_RSP,
10706 GAS_INITIAL_RSP_SIZE);
10707
10708 /* GAS Comeback Request */
10709 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10710 (uint8_t *) GAS_COMEBACK_REQ,
10711 GAS_COMEBACK_REQ_SIZE);
10712
10713 /* GAS Comeback Response */
10714 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10715 (uint8_t *) GAS_COMEBACK_RSP,
10716 GAS_COMEBACK_RSP_SIZE);
10717
10718 /* P2P Public Action */
10719 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10720 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10721 P2P_PUBLIC_ACTION_FRAME_SIZE);
10722
10723 /* P2P Action */
10724 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10725 (uint8_t *) P2P_ACTION_FRAME,
10726 P2P_ACTION_FRAME_SIZE);
10727
10728 /* WNM-Notification */
10729 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10730 (uint8_t *) WNM_NOTIFICATION_FRAME,
10731 WNM_NOTIFICATION_FRAME_SIZE);
10732}
10733
10734#ifdef FEATURE_WLAN_WAPI
10735void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10736 const uint8_t *mac_addr, const uint8_t *key,
10737 int key_Len)
10738{
10739 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10740 tCsrRoamSetKey setKey;
10741 bool isConnected = true;
10742 int status = 0;
10743 uint32_t roamId = 0xFF;
10744 uint8_t *pKeyPtr = NULL;
10745 int n = 0;
10746
Jeff Johnson46b40792016-06-29 14:03:14 -070010747 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010748 hdd_device_mode_to_string(pAdapter->device_mode),
10749 pAdapter->device_mode);
10750
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010751 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010752 setKey.keyId = key_index; /* Store Key ID */
10753 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10754 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10755 setKey.paeRole = 0; /* the PAE role */
10756 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010757 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010758 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010759 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760 }
10761 setKey.keyLength = key_Len;
10762 pKeyPtr = setKey.Key;
10763 memcpy(pKeyPtr, key, key_Len);
10764
Jeff Johnson46b40792016-06-29 14:03:14 -070010765 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010766 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010767 hdd_notice("WAPI KEY Data[%d]:%02x ",
10768 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010769
10770 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10771 if (isConnected) {
10772 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10773 pAdapter->sessionId, &setKey, &roamId);
10774 }
10775 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010776 hdd_err("sme_roam_set_key returned ERROR status= %d",
10777 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010778 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10779 }
10780}
10781#endif /* FEATURE_WLAN_WAPI */
10782
10783uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10784 uint8_t eid)
10785{
10786 int left = length;
10787 uint8_t *ptr = (uint8_t *)ies_ptr;
10788 uint8_t elem_id, elem_len;
10789
10790 while (left >= 2) {
10791 elem_id = ptr[0];
10792 elem_len = ptr[1];
10793 left -= 2;
10794 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010795 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010796 eid, elem_len, left);
10797 return NULL;
10798 }
10799 if (elem_id == eid) {
10800 return ptr;
10801 }
10802
10803 left -= elem_len;
10804 ptr += (elem_len + 2);
10805 }
10806 return NULL;
10807}
10808
10809/*
10810 * FUNCTION: wlan_hdd_validate_operation_channel
10811 * called by wlan_hdd_cfg80211_start_bss() and
10812 * wlan_hdd_set_channel()
10813 * This function validates whether given channel is part of valid
10814 * channel list.
10815 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010816QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010817 int channel)
10818{
10819
10820 uint32_t num_ch = 0;
10821 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10822 u32 indx = 0;
10823 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10824 uint8_t fValidChannel = false, count = 0;
10825 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10826
10827 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10828
10829 if (hdd_pConfig_ini->sapAllowAllChannel) {
10830 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010831 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010832 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010833 fValidChannel = true;
10834 break;
10835 }
10836 }
10837 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010838 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010839 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 }
10841 } else {
10842 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10843 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010844 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010845 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846 }
10847 for (indx = 0; indx < num_ch; indx++) {
10848 if (channel == valid_ch[indx]) {
10849 break;
10850 }
10851 }
10852
10853 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010854 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010855 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 }
10857 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010858 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859
10860}
10861
10862#ifdef DHCP_SERVER_OFFLOAD
10863static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10864{
10865 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10866 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10867 uint8_t numEntries = 0;
10868 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10869 uint8_t num;
10870 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010871 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010872 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010873 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010874 return;
10875 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010876 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10877 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10878 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10879 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10880 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10881 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010882 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010883 goto end;
10884 }
10885 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010886 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 goto end;
10888 }
10889 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010890 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010891 goto end;
10892 }
10893 for (num = 0; num < numEntries; num++) {
10894 temp = srv_ip[num];
10895 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10896 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010897 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010898 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010899 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900 goto end;
10901 }
Jeff Johnson77848112016-06-29 14:52:06 -070010902 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010903end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010904 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010905 return;
10906}
10907#endif /* DHCP_SERVER_OFFLOAD */
10908
10909static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10910 struct net_device *dev,
10911 struct bss_parameters *params)
10912{
10913 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10914 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10915 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010916 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917
10918 ENTER();
10919
Anurag Chouhan6d760662016-02-20 16:05:43 +053010920 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010921 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010922 return -EINVAL;
10923 }
10924
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010925 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10926 hdd_err("invalid session id: %d", pAdapter->sessionId);
10927 return -EINVAL;
10928 }
10929
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010930 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10932 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010933 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010934 hdd_device_mode_to_string(pAdapter->device_mode),
10935 pAdapter->device_mode, params->ap_isolate);
10936
10937 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10938 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010939 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010940 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941
Krunal Sonib4326f22016-03-10 13:05:51 -080010942 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10943 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010944 return -EOPNOTSUPP;
10945 }
10946
10947 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010948 * want to update this parameter
10949 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 if (-1 != params->ap_isolate) {
10951 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10952 !!params->ap_isolate;
10953
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010954 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010955 pAdapter->sessionId,
10956 pAdapter->sessionCtx.
10957 ap.
10958 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010959 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 ret = -EINVAL;
10961 }
10962 }
10963
10964 EXIT();
10965 return ret;
10966}
10967
Krunal Soni8c37e322016-02-03 16:08:37 -080010968/**
10969 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10970 * @ndev: pointer to net device provided by supplicant
10971 * @type: type of the interface, upper layer wanted to change
10972 *
10973 * Upper layer provides the new interface mode that needs to be changed
10974 * for given net device
10975 *
10976 * Return: success or failure in terms of integer value
10977 */
10978static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010979 enum nl80211_iftype type)
10980{
Krunal Soni8c37e322016-02-03 16:08:37 -080010981 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10982 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10983 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010984 hdd_wext_state_t *wext;
10985 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010986 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987
10988 ENTER();
10989
Krunal Soni8c37e322016-02-03 16:08:37 -080010990 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010991 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010992 return 0;
10993 }
10994
10995 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010996 hdd_stop_adapter(hdd_ctx, adapter, true);
10997 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010998 wdev->iftype = type;
10999 /*Check for sub-string p2p to confirm its a p2p interface */
11000 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011001 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011003 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011004 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011005 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011007 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011009 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011010 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011011 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11012 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011013 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11014 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011016 adapter->scan_info.scanAddIE.length;
11017 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011018 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011019 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11020 wext->roamProfile.phyMode =
11021 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11022 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011023 EXIT();
11024 return status;
11025}
11026
11027static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11028 struct net_device *dev,
11029 struct bss_parameters *params)
11030{
11031 int ret;
11032
11033 cds_ssr_protect(__func__);
11034 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11035 cds_ssr_unprotect(__func__);
11036
11037 return ret;
11038}
11039
11040/* FUNCTION: wlan_hdd_change_country_code_cd
11041 * to wait for contry code completion
11042 */
11043void *wlan_hdd_change_country_code_cb(void *pAdapter)
11044{
11045 hdd_adapter_t *call_back_pAdapter = pAdapter;
11046 complete(&call_back_pAdapter->change_country_code);
11047 return NULL;
11048}
11049
Rajeev Kumar98edb772016-01-19 12:42:19 -080011050/**
11051 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11052 * @wiphy: Pointer to the wiphy structure
11053 * @ndev: Pointer to the net device
11054 * @type: Interface type
11055 * @flags: Flags for change interface
11056 * @params: Pointer to change interface parameters
11057 *
11058 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059 */
11060static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11061 struct net_device *ndev,
11062 enum nl80211_iftype type,
11063 u32 *flags,
11064 struct vif_params *params)
11065{
11066 struct wireless_dev *wdev;
11067 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11068 hdd_context_t *pHddCtx;
11069 tCsrRoamProfile *pRoamProfile = NULL;
11070 eCsrRoamBssType LastBSSType;
11071 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011072 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073 int status;
11074
11075 ENTER();
11076
Anurag Chouhan6d760662016-02-20 16:05:43 +053011077 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011078 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 return -EINVAL;
11080 }
11081
11082 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11083 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011084 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011085 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011086
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011087 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011088 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11089 pAdapter->sessionId, type));
11090
Jeff Johnson77848112016-06-29 14:52:06 -070011091 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011092 pAdapter->device_mode, type);
11093
Arun Khandavallifae92942016-08-01 13:31:08 +053011094 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11095 if (status) {
11096 hdd_err("Failed to start modules");
11097 return -EINVAL;
11098 }
11099
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011100 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011101 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11102 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011103 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011104 return -EINVAL;
11105 }
11106
11107 pConfig = pHddCtx->config;
11108 wdev = ndev->ieee80211_ptr;
11109
11110 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011111 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011112
Nitesh Shahe6359752017-02-23 19:57:50 +053011113 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011114 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11115 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11116 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11117 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118 hdd_wext_state_t *pWextState =
11119 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11120
11121 pRoamProfile = &pWextState->roamProfile;
11122 LastBSSType = pRoamProfile->BSSType;
11123
11124 switch (type) {
11125 case NL80211_IFTYPE_STATION:
11126 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011127 case NL80211_IFTYPE_ADHOC:
11128 if (type == NL80211_IFTYPE_ADHOC) {
11129 wlan_hdd_tdls_exit(pAdapter);
11130 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011131 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011132 }
11133 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11134 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011135 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011136 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011137 if (hdd_start_adapter(pAdapter)) {
11138 hdd_err("Failed to start adapter :%d",
11139 pAdapter->device_mode);
11140 return -EINVAL;
11141 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 case NL80211_IFTYPE_AP:
11144 case NL80211_IFTYPE_P2P_GO:
11145 {
Jeff Johnson77848112016-06-29 14:52:06 -070011146 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147 (type ==
11148 NL80211_IFTYPE_AP) ? "SoftAP" :
11149 "P2pGo");
11150
11151 /* Cancel any remain on channel for GO mode */
11152 if (NL80211_IFTYPE_P2P_GO == type) {
11153 wlan_hdd_cancel_existing_remain_on_channel
11154 (pAdapter);
11155 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156
Arun Khandavallifae92942016-08-01 13:31:08 +053011157 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 /* De-init the adapter */
11159 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11160 memset(&pAdapter->sessionCtx, 0,
11161 sizeof(pAdapter->sessionCtx));
11162 pAdapter->device_mode =
11163 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011164 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11165 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166
11167 /*
11168 * Fw will take care incase of concurrency
11169 */
11170
Krunal Sonib4326f22016-03-10 13:05:51 -080011171 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011173 /* To meet Android requirements create
11174 * a randomized MAC address of the
11175 * form 02:1A:11:Fx:xx:xx
11176 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 get_random_bytes(&ndev->dev_addr[3], 3);
11178 ndev->dev_addr[0] = 0x02;
11179 ndev->dev_addr[1] = 0x1A;
11180 ndev->dev_addr[2] = 0x11;
11181 ndev->dev_addr[3] |= 0xF0;
11182 memcpy(pAdapter->macAddressCurrent.
11183 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011184 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 pr_info("wlan: Generated HotSpot BSSID "
11186 MAC_ADDRESS_STR "\n",
11187 MAC_ADDR_ARRAY(ndev->dev_addr));
11188 }
11189
11190 hdd_set_ap_ops(pAdapter->dev);
11191
Arun Khandavallifae92942016-08-01 13:31:08 +053011192 if (hdd_start_adapter(pAdapter)) {
11193 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011194 return -EINVAL;
11195 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 /* Interface type changed update in wiphy structure */
11197 if (wdev) {
11198 wdev->iftype = type;
11199 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011200 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201 return -EINVAL;
11202 }
11203 goto done;
11204 }
11205
11206 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011207 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011208 type);
11209 return -EOPNOTSUPP;
11210 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011211 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11212 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011213 switch (type) {
11214 case NL80211_IFTYPE_STATION:
11215 case NL80211_IFTYPE_P2P_CLIENT:
11216 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011217 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11218 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011219 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011220 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011221 if (hdd_start_adapter(pAdapter)) {
11222 hdd_err("Failed to start adapter :%d",
11223 pAdapter->device_mode);
11224 return -EINVAL;
11225 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226 goto done;
11227
11228 case NL80211_IFTYPE_AP:
11229 case NL80211_IFTYPE_P2P_GO:
11230 wdev->iftype = type;
11231 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011232 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233 goto done;
11234
11235 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011236 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011237 type);
11238 return -EOPNOTSUPP;
11239 }
11240 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011241 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 pAdapter->device_mode);
11243 return -EOPNOTSUPP;
11244 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011245done:
11246 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011247 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011248
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011249 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250
11251 EXIT();
11252 return 0;
11253}
11254
Rajeev Kumar98edb772016-01-19 12:42:19 -080011255/**
11256 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11257 * @wiphy: Pointer to the wiphy structure
11258 * @ndev: Pointer to the net device
11259 * @type: Interface type
11260 * @flags: Flags for change interface
11261 * @params: Pointer to change interface parameters
11262 *
11263 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264 */
11265static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11266 struct net_device *ndev,
11267 enum nl80211_iftype type,
11268 u32 *flags,
11269 struct vif_params *params)
11270{
11271 int ret;
11272
11273 cds_ssr_protect(__func__);
11274 ret =
11275 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11276 cds_ssr_unprotect(__func__);
11277
11278 return ret;
11279}
11280
11281#ifdef FEATURE_WLAN_TDLS
11282static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11283 int index, uint8_t match)
11284{
11285 int i;
11286 for (i = 0; i < index; i++) {
11287 if (arr[i] == match)
11288 return true;
11289 }
11290 return false;
11291}
11292#endif
11293
11294/**
11295 * __wlan_hdd_change_station() - change station
11296 * @wiphy: Pointer to the wiphy structure
11297 * @dev: Pointer to the net device.
11298 * @mac: bssid
11299 * @params: Pointer to station parameters
11300 *
11301 * Return: 0 for success, error number on failure.
11302 */
11303#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11304static int __wlan_hdd_change_station(struct wiphy *wiphy,
11305 struct net_device *dev,
11306 const uint8_t *mac,
11307 struct station_parameters *params)
11308#else
11309static int __wlan_hdd_change_station(struct wiphy *wiphy,
11310 struct net_device *dev,
11311 uint8_t *mac,
11312 struct station_parameters *params)
11313#endif
11314{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011315 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011316 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11317 hdd_context_t *pHddCtx;
11318 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011319 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011320#ifdef FEATURE_WLAN_TDLS
11321 tCsrStaParams StaParams = { 0 };
11322 uint8_t isBufSta = 0;
11323 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011324 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325#endif
11326 int ret;
11327
11328 ENTER();
11329
Anurag Chouhan6d760662016-02-20 16:05:43 +053011330 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011331 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011332 return -EINVAL;
11333 }
11334
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011335 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011336 TRACE_CODE_HDD_CHANGE_STATION,
11337 pAdapter->sessionId, params->listen_interval));
11338
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011339 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11340 hdd_err("invalid session id: %d", pAdapter->sessionId);
11341 return -EINVAL;
11342 }
11343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11345 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011346 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011347 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348
11349 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11350
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011351 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011352
Krunal Sonib4326f22016-03-10 13:05:51 -080011353 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11354 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011355 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11356 status =
11357 hdd_softap_change_sta_state(pAdapter,
11358 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011359 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011360
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011361 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011362 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011363 return -EINVAL;
11364 }
11365 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011366 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11367 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011368#ifdef FEATURE_WLAN_TDLS
11369 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011370
11371 if (cds_is_sub_20_mhz_enabled()) {
11372 hdd_err("TDLS not allowed with sub 20 MHz");
11373 return -EINVAL;
11374 }
11375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376 StaParams.capability = params->capability;
11377 StaParams.uapsd_queues = params->uapsd_queues;
11378 StaParams.max_sp = params->max_sp;
11379
11380 /* Convert (first channel , number of channels) tuple to
11381 * the total list of channels. This goes with the assumption
11382 * that if the first channel is < 14, then the next channels
11383 * are an incremental of 1 else an incremental of 4 till the number
11384 * of channels.
11385 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011386 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011387 if (0 != params->supported_channels_len) {
11388 int i = 0, j = 0, k = 0, no_of_channels = 0;
11389 int num_unique_channels;
11390 int next;
11391 for (i = 0;
11392 i < params->supported_channels_len
11393 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11394 int wifi_chan_index;
11395 if (!wlan_hdd_is_duplicate_channel
11396 (StaParams.supported_channels, j,
11397 params->supported_channels[i])) {
11398 StaParams.
11399 supported_channels[j] =
11400 params->
11401 supported_channels[i];
11402 } else {
11403 continue;
11404 }
11405 wifi_chan_index =
11406 ((StaParams.supported_channels[j] <=
11407 HDD_CHANNEL_14) ? 1 : 4);
11408 no_of_channels =
11409 params->supported_channels[i + 1];
11410
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011411 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 -080011412 StaParams.
11413 supported_channels[j],
11414 wifi_chan_index,
11415 no_of_channels);
11416 for (k = 1; k <= no_of_channels &&
11417 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11418 k++) {
11419 next =
11420 StaParams.
11421 supported_channels[j] +
11422 wifi_chan_index;
11423 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11424 StaParams.
11425 supported_channels[j
11426 +
11427 1]
11428 = next;
11429 } else {
11430 continue;
11431 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011432 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011433 j + 1,
11434 StaParams.
11435 supported_channels[j +
11436 1]);
11437 j += 1;
11438 }
11439 }
11440 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011441 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011443 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011444 StaParams.
11445 supported_channels[i]);
11446 }
11447 if (MAX_CHANNEL < num_unique_channels)
11448 num_unique_channels = MAX_CHANNEL;
11449 StaParams.supported_channels_len =
11450 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011451 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 StaParams.supported_channels_len);
11453 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011454 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455 params->supported_oper_classes,
11456 params->supported_oper_classes_len);
11457 StaParams.supported_oper_classes_len =
11458 params->supported_oper_classes_len;
11459
11460 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011461 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011462 params->ext_capab,
11463 sizeof(StaParams.extn_capability));
11464
11465 if (NULL != params->ht_capa) {
11466 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011467 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011468 sizeof(tSirHTCap));
11469 }
11470
11471 StaParams.supported_rates_len =
11472 params->supported_rates_len;
11473
11474 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11475 * The supported_rates array , for all the structures propogating till Add Sta
11476 * to the firmware has to be modified , if the supplicant (ieee80211) is
11477 * modified to send more rates.
11478 */
11479
11480 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11481 */
11482 if (StaParams.supported_rates_len >
11483 SIR_MAC_MAX_SUPP_RATES)
11484 StaParams.supported_rates_len =
11485 SIR_MAC_MAX_SUPP_RATES;
11486
11487 if (0 != StaParams.supported_rates_len) {
11488 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011489 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011490 params->supported_rates,
11491 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011492 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011493 StaParams.supported_rates_len);
11494 for (i = 0; i < StaParams.supported_rates_len;
11495 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011496 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011497 StaParams.supported_rates[i]);
11498 }
11499
11500 if (NULL != params->vht_capa) {
11501 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011502 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011503 params->vht_capa,
11504 sizeof(tSirVHTCap));
11505 }
11506
11507 if (0 != params->ext_capab_len) {
11508 /*Define A Macro : TODO Sunil */
11509 if ((1 << 4) & StaParams.extn_capability[3]) {
11510 isBufSta = 1;
11511 }
11512 /* TDLS Channel Switching Support */
11513 if ((1 << 6) & StaParams.extn_capability[3]) {
11514 isOffChannelSupported = 1;
11515 }
11516 }
11517
Nitesh Shah99934ac2016-09-05 15:54:08 +053011518 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011519 (params->ht_capa || params->vht_capa ||
11520 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011521 is_qos_wmm_sta = true;
11522
11523 hdd_notice("%s: TDLS Peer is QOS capable"
11524 " is_qos_wmm_sta= %d HTcapPresent = %d",
11525 __func__, is_qos_wmm_sta,
11526 StaParams.htcap_present);
11527
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011529 &StaParams,
11530 isBufSta,
11531 isOffChannelSupported,
11532 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011533 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011534 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535 return -EINVAL;
11536 }
11537
11538 status =
11539 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11540 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011541 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011542 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543 return -EINVAL;
11544 }
11545 }
11546#endif
11547 }
11548 EXIT();
11549 return ret;
11550}
11551
11552/**
11553 * wlan_hdd_change_station() - cfg80211 change station handler function
11554 * @wiphy: Pointer to the wiphy structure
11555 * @dev: Pointer to the net device.
11556 * @mac: bssid
11557 * @params: Pointer to station parameters
11558 *
11559 * This is the cfg80211 change station handler function which invokes
11560 * the internal function @__wlan_hdd_change_station with
11561 * SSR protection.
11562 *
11563 * Return: 0 for success, error number on failure.
11564 */
11565#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11566static int wlan_hdd_change_station(struct wiphy *wiphy,
11567 struct net_device *dev,
11568 const u8 *mac,
11569 struct station_parameters *params)
11570#else
11571static int wlan_hdd_change_station(struct wiphy *wiphy,
11572 struct net_device *dev,
11573 u8 *mac,
11574 struct station_parameters *params)
11575#endif
11576{
11577 int ret;
11578
11579 cds_ssr_protect(__func__);
11580 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11581 cds_ssr_unprotect(__func__);
11582
11583 return ret;
11584}
11585
11586/*
11587 * FUNCTION: __wlan_hdd_cfg80211_add_key
11588 * This function is used to initialize the key information
11589 */
11590static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11591 struct net_device *ndev,
11592 u8 key_index, bool pairwise,
11593 const u8 *mac_addr,
11594 struct key_params *params)
11595{
11596 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11597 tCsrRoamSetKey setKey;
11598 int status;
11599 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011601 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011602 hdd_context_t *pHddCtx;
11603 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11604
11605 ENTER();
11606
Anurag Chouhan6d760662016-02-20 16:05:43 +053011607 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011608 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 return -EINVAL;
11610 }
11611
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011612 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11613 hdd_err("invalid session id: %d", pAdapter->sessionId);
11614 return -EINVAL;
11615 }
11616
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011617 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11619 pAdapter->sessionId, params->key_len));
11620 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11621 status = wlan_hdd_validate_context(pHddCtx);
11622
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011623 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011624 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011625
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011626 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011627 hdd_device_mode_to_string(pAdapter->device_mode),
11628 pAdapter->device_mode);
11629
11630 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011631 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632
11633 return -EINVAL;
11634 }
11635
11636 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011637 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638
11639 return -EINVAL;
11640 }
11641
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011642 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643
11644 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011645 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011646 setKey.keyId = key_index;
11647 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011648 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649
11650 switch (params->cipher) {
11651 case WLAN_CIPHER_SUITE_WEP40:
11652 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11653 break;
11654
11655 case WLAN_CIPHER_SUITE_WEP104:
11656 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11657 break;
11658
11659 case WLAN_CIPHER_SUITE_TKIP:
11660 {
11661 u8 *pKey = &setKey.Key[0];
11662 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11663
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011664 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011665
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011666 /* Supplicant sends the 32bytes key in this order
11667 *
11668 * |--------------|----------|----------|
11669 * | Tk1 |TX-MIC | RX Mic |
11670 * |--------------|----------|----------|
11671 * <---16bytes---><--8bytes--><--8bytes-->
11672 *
11673 * Sme expects the 32 bytes key to be in the below order
11674 *
11675 * |--------------|----------|----------|
11676 * | Tk1 |RX-MIC | TX Mic |
11677 * |--------------|----------|----------|
11678 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011679 */
11680 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011681 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682
11683 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011684 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011685
11686 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011687 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688
11689 break;
11690 }
11691
11692 case WLAN_CIPHER_SUITE_CCMP:
11693 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11694 break;
11695
11696#ifdef FEATURE_WLAN_WAPI
11697 case WLAN_CIPHER_SUITE_SMS4:
11698 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011699 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011700 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11701 mac_addr, params->key,
11702 params->key_len);
11703 return 0;
11704 }
11705#endif
11706
11707#ifdef FEATURE_WLAN_ESE
11708 case WLAN_CIPHER_SUITE_KRK:
11709 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11710 break;
11711#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11712 case WLAN_CIPHER_SUITE_BTK:
11713 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11714 break;
11715#endif
11716#endif
11717
11718#ifdef WLAN_FEATURE_11W
11719 case WLAN_CIPHER_SUITE_AES_CMAC:
11720 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11721 break;
11722#endif
11723
11724 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011725 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011726 return -EOPNOTSUPP;
11727 }
11728
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011729 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011730
11731 if (!pairwise) {
11732 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011733 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011734 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011735 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736 } else {
11737 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011738 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011740 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011742 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011743 /* if a key is already installed, block all subsequent ones */
11744 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011745 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011746 return 0;
11747 }
11748
11749 setKey.keyDirection = eSIR_TX_RX;
11750 /*Set the group key */
11751 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11752 pAdapter->sessionId, &setKey, &roamId);
11753
11754 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011755 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756 return -EINVAL;
11757 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011758 /* Save the keys here and call sme_roam_set_key for setting
11759 * the PTK after peer joins the IBSS network
11760 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011761 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011762 &setKey, sizeof(tCsrRoamSetKey));
11763
11764 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11765 return status;
11766 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011767 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11768 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11770 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011771 status = wlansap_set_key_sta(
11772 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011773 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011774 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775 __LINE__, status);
11776 }
11777 }
11778
11779 /* Save the key in ap ctx for use on START_BASS and restart */
11780 if (pairwise ||
11781 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11782 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011783 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 sizeof(tCsrRoamSetKey));
11785 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011786 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011787 sizeof(tCsrRoamSetKey));
11788
Krunal Sonib4326f22016-03-10 13:05:51 -080011789 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11790 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791 hdd_wext_state_t *pWextState =
11792 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11793 hdd_station_ctx_t *pHddStaCtx =
11794 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11795
11796 if (!pairwise) {
11797 /* set group key */
11798 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011799 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011800 __func__, __LINE__);
11801 hdd_perform_roam_set_key_complete(pAdapter);
11802 }
11803 }
11804
11805 pWextState->roamProfile.Keys.KeyLength[key_index] =
11806 (u8) params->key_len;
11807
11808 pWextState->roamProfile.Keys.defaultIndex = key_index;
11809
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011810 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011811 KeyMaterial[key_index][0], params->key,
11812 params->key_len);
11813
11814 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11815
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011816 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011817 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11818 setKey.keyDirection);
11819
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011820 /* The supplicant may attempt to set the PTK once
11821 * pre-authentication is done. Save the key in the
11822 * UMAC and include it in the ADD BSS request
11823 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011824 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011825 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011826 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011827 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011828 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011829 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011830 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011831 return -EINVAL;
11832 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011833
11834 /* issue set key request to SME */
11835 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11836 pAdapter->sessionId, &setKey, &roamId);
11837
11838 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011839 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840 pHddStaCtx->roam_info.roamingState =
11841 HDD_ROAM_STATE_NONE;
11842 return -EINVAL;
11843 }
11844
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011845 /* in case of IBSS as there was no information
11846 * available about WEP keys during IBSS join, group
11847 * key intialized with NULL key, so re-initialize
11848 * group key with correct value
11849 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850 if ((eCSR_BSS_TYPE_START_IBSS ==
11851 pWextState->roamProfile.BSSType)
11852 &&
11853 !((IW_AUTH_KEY_MGMT_802_1X ==
11854 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11855 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11856 pHddStaCtx->conn_info.authType)
11857 )
11858 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11859 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11860 )
11861 ) {
11862 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011863 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011864
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011865 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011866 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11867 setKey.keyDirection);
11868
11869 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11870 pAdapter->sessionId, &setKey,
11871 &roamId);
11872
11873 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011874 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011875 pHddStaCtx->roam_info.roamingState =
11876 HDD_ROAM_STATE_NONE;
11877 return -EINVAL;
11878 }
11879 }
11880 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011881 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882 return 0;
11883}
11884
11885static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11886 struct net_device *ndev,
11887 u8 key_index, bool pairwise,
11888 const u8 *mac_addr,
11889 struct key_params *params)
11890{
11891 int ret;
11892 cds_ssr_protect(__func__);
11893 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11894 mac_addr, params);
11895 cds_ssr_unprotect(__func__);
11896
11897 return ret;
11898}
11899
11900/*
11901 * FUNCTION: __wlan_hdd_cfg80211_get_key
11902 * This function is used to get the key information
11903 */
11904static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11905 struct net_device *ndev,
11906 u8 key_index, bool pairwise,
11907 const u8 *mac_addr, void *cookie,
11908 void (*callback)(void *cookie,
11909 struct key_params *)
11910 )
11911{
11912 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11913 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11914 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11915 struct key_params params;
11916
11917 ENTER();
11918
Anurag Chouhan6d760662016-02-20 16:05:43 +053011919 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011920 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011921 return -EINVAL;
11922 }
11923
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011924 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011925 hdd_device_mode_to_string(pAdapter->device_mode),
11926 pAdapter->device_mode);
11927
11928 memset(&params, 0, sizeof(params));
11929
11930 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011931 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011932 key_index);
11933 return -EINVAL;
11934 }
11935
11936 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11937 case eCSR_ENCRYPT_TYPE_NONE:
11938 params.cipher = IW_AUTH_CIPHER_NONE;
11939 break;
11940
11941 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11942 case eCSR_ENCRYPT_TYPE_WEP40:
11943 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11944 break;
11945
11946 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11947 case eCSR_ENCRYPT_TYPE_WEP104:
11948 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11949 break;
11950
11951 case eCSR_ENCRYPT_TYPE_TKIP:
11952 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11953 break;
11954
11955 case eCSR_ENCRYPT_TYPE_AES:
11956 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11957 break;
11958
11959 default:
11960 params.cipher = IW_AUTH_CIPHER_NONE;
11961 break;
11962 }
11963
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011964 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011965 TRACE_CODE_HDD_CFG80211_GET_KEY,
11966 pAdapter->sessionId, params.cipher));
11967
11968 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11969 params.seq_len = 0;
11970 params.seq = NULL;
11971 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11972 callback(cookie, &params);
11973
11974 EXIT();
11975 return 0;
11976}
11977
11978static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11979 struct net_device *ndev,
11980 u8 key_index, bool pairwise,
11981 const u8 *mac_addr, void *cookie,
11982 void (*callback)(void *cookie,
11983 struct key_params *)
11984 )
11985{
11986 int ret;
11987
11988 cds_ssr_protect(__func__);
11989 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11990 mac_addr, cookie, callback);
11991 cds_ssr_unprotect(__func__);
11992
11993 return ret;
11994}
11995
11996/**
11997 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11998 * @wiphy: wiphy interface context
11999 * @ndev: pointer to net device
12000 * @key_index: Key index used in 802.11 frames
12001 * @unicast: true if it is unicast key
12002 * @multicast: true if it is multicast key
12003 *
12004 * This function is required for cfg80211_ops API.
12005 * It is used to delete the key information
12006 * Underlying hardware implementation does not have API to delete the
12007 * encryption key. It is automatically deleted when the peer is
12008 * removed. Hence this function currently does nothing.
12009 * Future implementation may interprete delete key operation to
12010 * replacing the key with a random junk value, effectively making it
12011 * useless.
12012 *
12013 * Return: status code, always 0.
12014 */
12015
12016static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12017 struct net_device *ndev,
12018 u8 key_index,
12019 bool pairwise, const u8 *mac_addr)
12020{
12021 EXIT();
12022 return 0;
12023}
12024
12025/**
12026 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12027 * @wiphy: Pointer to wiphy structure.
12028 * @dev: Pointer to net_device structure.
12029 * @key_index: key index
12030 * @pairwise: pairwise
12031 * @mac_addr: mac address
12032 *
12033 * This is the cfg80211 delete key handler function which invokes
12034 * the internal function @__wlan_hdd_cfg80211_del_key with
12035 * SSR protection.
12036 *
12037 * Return: 0 for success, error number on failure.
12038 */
12039static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12040 struct net_device *dev,
12041 u8 key_index,
12042 bool pairwise, const u8 *mac_addr)
12043{
12044 int ret;
12045
12046 cds_ssr_protect(__func__);
12047 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12048 pairwise, mac_addr);
12049 cds_ssr_unprotect(__func__);
12050
12051 return ret;
12052}
12053
12054/*
12055 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12056 * This function is used to set the default tx key index
12057 */
12058static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12059 struct net_device *ndev,
12060 u8 key_index,
12061 bool unicast, bool multicast)
12062{
12063 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12064 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12065 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12066 hdd_context_t *pHddCtx;
12067 int status;
12068
12069 ENTER();
12070
Anurag Chouhan6d760662016-02-20 16:05:43 +053012071 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012072 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012073 return -EINVAL;
12074 }
12075
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012076 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12077 hdd_err("invalid session id: %d", pAdapter->sessionId);
12078 return -EINVAL;
12079 }
12080
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012081 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12083 pAdapter->sessionId, key_index));
12084
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012085 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012086 hdd_device_mode_to_string(pAdapter->device_mode),
12087 pAdapter->device_mode, key_index);
12088
12089 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012090 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091 return -EINVAL;
12092 }
12093
12094 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12095 status = wlan_hdd_validate_context(pHddCtx);
12096
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012097 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012099
Krunal Sonib4326f22016-03-10 13:05:51 -080012100 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12101 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012102 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12103 pHddStaCtx->conn_info.ucEncryptionType) &&
12104 (eCSR_ENCRYPT_TYPE_AES !=
12105 pHddStaCtx->conn_info.ucEncryptionType)) {
12106 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012107 * then update the default key index
12108 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012109
12110 tCsrRoamSetKey setKey;
12111 uint32_t roamId = 0xFF;
12112 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12113
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012114 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012115
12116 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012117 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118 setKey.keyId = key_index;
12119 setKey.keyLength = Keys->KeyLength[key_index];
12120
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012121 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122 &Keys->KeyMaterial[key_index][0],
12123 Keys->KeyLength[key_index]);
12124
12125 setKey.keyDirection = eSIR_TX_RX;
12126
Anurag Chouhanc5548422016-02-24 18:33:27 +053012127 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012128 &pHddStaCtx->conn_info.bssId);
12129
12130 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12131 pWextState->roamProfile.EncryptionType.
12132 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012133 /* In the case of dynamic wep
12134 * supplicant hardcodes DWEP type to
12135 * eCSR_ENCRYPT_TYPE_WEP104 even
12136 * though ap is configured for WEP-40
12137 * encryption. In this canse the key
12138 * length is 5 but the encryption type
12139 * is 104 hence checking the key
12140 * lenght(5) and encryption type(104)
12141 * and switching encryption type to 40
12142 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143 pWextState->roamProfile.EncryptionType.
12144 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12145 pWextState->roamProfile.mcEncryptionType.
12146 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12147 }
12148
12149 setKey.encType =
12150 pWextState->roamProfile.EncryptionType.
12151 encryptionType[0];
12152
12153 /* Issue set key request */
12154 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12155 pAdapter->sessionId, &setKey,
12156 &roamId);
12157
12158 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012159 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012160 status);
12161 return -EINVAL;
12162 }
12163 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012164 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012165 /* In SoftAp mode setting key direction for default mode */
12166 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12167 pWextState->roamProfile.EncryptionType.encryptionType[0])
12168 && (eCSR_ENCRYPT_TYPE_AES !=
12169 pWextState->roamProfile.EncryptionType.
12170 encryptionType[0])) {
12171 /* Saving key direction for default key index to TX default */
12172 hdd_ap_ctx_t *pAPCtx =
12173 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12174 pAPCtx->wepKey[key_index].keyDirection =
12175 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012176 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012177 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012178 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012179 }
12180 }
12181
12182 EXIT();
12183 return status;
12184}
12185
12186static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12187 struct net_device *ndev,
12188 u8 key_index,
12189 bool unicast, bool multicast)
12190{
12191 int ret;
12192 cds_ssr_protect(__func__);
12193 ret =
12194 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12195 multicast);
12196 cds_ssr_unprotect(__func__);
12197
12198 return ret;
12199}
12200
Abhishek Singhc9941602016-08-09 16:06:22 +053012201/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012202 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12203 * interface that BSS might have been lost.
12204 * @pAdapter: adaptor
12205 * @bssid: bssid which might have been lost
12206 *
12207 * Return: bss which is unlinked from kernel cache
12208 */
12209struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12210 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012211{
12212 struct net_device *dev = pAdapter->dev;
12213 struct wireless_dev *wdev = dev->ieee80211_ptr;
12214 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012215 struct cfg80211_bss *bss = NULL;
12216
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012217 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012218 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012219 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012220 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012221 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012222 hdd_info("cfg80211_unlink_bss called for BSSID "
12223 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 cfg80211_unlink_bss(wiphy, bss);
12225 }
12226 return bss;
12227}
12228
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012229#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12230 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12231static struct cfg80211_bss *
12232wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12233 struct ieee80211_channel *chan,
12234 struct ieee80211_mgmt *mgmt,
12235 size_t frame_len,
12236 int rssi, gfp_t gfp,
12237 uint64_t boottime_ns)
12238{
12239 struct cfg80211_bss *bss_status = NULL;
12240 struct cfg80211_inform_bss data = {0};
12241
12242 data.chan = chan;
12243 data.boottime_ns = boottime_ns;
12244 data.signal = rssi;
12245 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12246 frame_len, gfp);
12247 return bss_status;
12248}
12249#else
12250static struct cfg80211_bss *
12251wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12252 struct ieee80211_channel *chan,
12253 struct ieee80211_mgmt *mgmt,
12254 size_t frame_len,
12255 int rssi, gfp_t gfp,
12256 uint64_t boottime_ns)
12257{
12258 struct cfg80211_bss *bss_status = NULL;
12259
12260 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12261 rssi, gfp);
12262 return bss_status;
12263}
12264#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012265
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012266/**
12267 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12268 * @pAdapter: Pointer to adapter
12269 * @bss_desc: Pointer to bss descriptor
12270 *
12271 * This function is used to inform the BSS details to nl80211 interface.
12272 *
12273 * Return: struct cfg80211_bss pointer
12274 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012275struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12276 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012277{
12278 /*
12279 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12280 * already exists in bss data base of cfg80211 for that particular BSS
12281 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12282 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12283 * As of now there is no possibility to get the mgmt(probe response)
12284 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12285 * and passing to cfg80211_inform_bss_frame.
12286 */
12287 struct net_device *dev = pAdapter->dev;
12288 struct wireless_dev *wdev = dev->ieee80211_ptr;
12289 struct wiphy *wiphy = wdev->wiphy;
12290 int chan_no = bss_desc->channelId;
12291#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12292 qcom_ie_age *qie_age = NULL;
12293 int ie_length =
12294 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12295#else
12296 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12297#endif
12298 const char *ie =
12299 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12300 unsigned int freq;
12301 struct ieee80211_channel *chan;
12302 struct ieee80211_mgmt *mgmt = NULL;
12303 struct cfg80211_bss *bss_status = NULL;
12304 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12305 int rssi = 0;
12306 hdd_context_t *pHddCtx;
12307 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012308 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012309 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310
12311 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12312 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012313 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012314 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012315
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012316 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012317 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012318 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012319 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 return NULL;
12321 }
12322
12323 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012325 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012326 * Instead it wants a monotonic increasing value
12327 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012328 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329 mgmt->u.probe_resp.timestamp =
12330 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331
12332 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12333 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12334
12335#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12336 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12337 /* Assuming this is the last IE, copy at the end */
12338 ie_length -= sizeof(qcom_ie_age);
12339 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12340 qie_age->element_id = QCOM_VENDOR_IE_ID;
12341 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12342 qie_age->oui_1 = QCOM_OUI1;
12343 qie_age->oui_2 = QCOM_OUI2;
12344 qie_age->oui_3 = QCOM_OUI3;
12345 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012346 /*
12347 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12348 * all bss related timestamp is in units of ms. Due to this when scan
12349 * results are sent to lowi the scan age is high.To address this,
12350 * send age in units of 1/10 ms.
12351 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012352 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012353 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012355 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12356 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012357 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12358 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012359#endif
12360
12361 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12362 if (bss_desc->fProbeRsp) {
12363 mgmt->frame_control |=
12364 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12365 } else {
12366 mgmt->frame_control |=
12367 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12368 }
12369
12370 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012371 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372 freq =
12373 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012374 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012375 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012376 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 freq =
12378 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012379 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012380 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012381 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012382 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383 return NULL;
12384 }
12385
12386 chan = __ieee80211_get_channel(wiphy, freq);
12387 /* When the band is changed on the fly using the GUI, three things are done
12388 * 1. scan abort
12389 * 2. flush scan results from cache
12390 * 3. update the band with the new band user specified (refer to the
12391 * hdd_set_band_helper function) as part of the scan abort, message will be
12392 * queued to PE and we proceed with flushing and changinh the band.
12393 * PE will stop the scanning further and report back the results what ever
12394 * it had till now by calling the call back function.
12395 * if the time between update band and scandone call back is sufficient
12396 * enough the band change reflects in SME, SME validates the channels
12397 * and discards the channels correponding to previous band and calls back
12398 * with zero bss results. but if the time between band update and scan done
12399 * callback is very small then band change will not reflect in SME and SME
12400 * reports to HDD all the channels correponding to previous band.this is due
12401 * to race condition.but those channels are invalid to the new band and so
12402 * this function __ieee80211_get_channel will return NULL.Each time we
12403 * report scan result with this pointer null warning kernel trace is printed.
12404 * if the scan results contain large number of APs continuosly kernel
12405 * warning trace is printed and it will lead to apps watch dog bark.
12406 * So drop the bss and continue to next bss.
12407 */
12408 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012409 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12410 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012411 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012412 return NULL;
12413 }
12414
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012415 /* Based on .ini configuration, raw rssi can be reported for bss.
12416 * Raw rssi is typically used for estimating power.
12417 */
12418
12419 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12420 bss_desc->rssi;
12421
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012422 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012423 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012424
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012425 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012426 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012427 (int)(rssi / 100),
12428 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012430 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12431 frame_len, rssi,
12432 GFP_KERNEL,
12433 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012434 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012435 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 return bss_status;
12437}
12438
12439/**
12440 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12441 * @pAdapter: Pointer to adapter
12442 * @pRoamInfo: Pointer to roam info
12443 *
12444 * This function is used to update the BSS data base of CFG8011
12445 *
12446 * Return: struct cfg80211_bss pointer
12447 */
12448struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12449 tCsrRoamInfo *pRoamInfo)
12450{
12451 tCsrRoamConnectedProfile roamProfile;
12452 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12453 struct cfg80211_bss *bss = NULL;
12454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12456 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12457
12458 if (NULL != roamProfile.pBssDesc) {
12459 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12460 roamProfile.pBssDesc);
12461
12462 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012463 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012465 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012466 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012467 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012468 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469 return bss;
12470}
12471/**
12472 * wlan_hdd_cfg80211_update_bss() - update bss
12473 * @wiphy: Pointer to wiphy
12474 * @pAdapter: Pointer to adapter
12475 * @scan_time: scan request timestamp
12476 *
12477 * Return: zero if success, non-zero otherwise
12478 */
12479int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12480 hdd_adapter_t *pAdapter,
12481 uint32_t scan_time)
12482{
12483 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12484 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012485 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 tScanResultHandle pResult;
12487 struct cfg80211_bss *bss_status = NULL;
12488 hdd_context_t *pHddCtx;
12489 int ret;
12490
12491 ENTER();
12492
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012493 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12494 hdd_err("invalid session id: %d", pAdapter->sessionId);
12495 return -EINVAL;
12496 }
12497
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012498 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012499 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12500 NO_SESSION, pAdapter->sessionId));
12501
12502 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12503 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012504 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012505 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506
12507 /* start getting scan results and populate cgf80211 BSS database */
12508 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12509
12510 /* no scan results */
12511 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012512 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012513 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012514 }
12515
12516 pScanResult = sme_scan_result_get_first(hHal, pResult);
12517
12518 while (pScanResult) {
12519 /*
12520 * - cfg80211_inform_bss() is not updating ie field of bss
12521 * entry if entry already exists in bss data base of cfg80211
12522 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12523 * to update thebss entry instead of cfg80211_inform_bss,
12524 * But this call expects mgmt packet as input. As of now
12525 * there is no possibility to get the mgmt(probe response)
12526 * frame from PE, converting bss_desc to
12527 * ieee80211_mgmt(probe response) and passing to c
12528 * fg80211_inform_bss_frame.
12529 * - Update BSS only if beacon timestamp is later than
12530 * scan request timestamp.
12531 */
12532 if ((scan_time == 0) ||
12533 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012534 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012535 bss_status =
12536 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12537 &pScanResult->BssDescriptor);
12538
12539 if (NULL == bss_status) {
12540 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12541 } else {
12542 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012543 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012544 bss_status);
12545 }
12546 } else {
12547 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12548 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12549 }
12550 pScanResult = sme_scan_result_get_next(hHal, pResult);
12551 }
12552
12553 sme_scan_result_purge(hHal, pResult);
12554 /*
12555 * For SAP mode, scan is invoked by hostapd during SAP start
12556 * if hostapd is restarted, we need to flush previous scan
12557 * result so that it will reflect environment change
12558 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012559 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012560#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12561 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12562#endif
12563 )
12564 sme_scan_flush_result(hHal);
12565
12566 EXIT();
12567 return 0;
12568}
12569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012570/**
12571 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12572 * @pAdapter: Pointer to adapter
12573 * @pRoamInfo: Pointer to roam info
12574 * @index: Index
12575 * @preauth: Preauth flag
12576 *
12577 * This function is used to notify the supplicant of a new PMKSA candidate.
12578 *
12579 * Return: 0 for success, non-zero for failure
12580 */
12581int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12582 tCsrRoamInfo *pRoamInfo,
12583 int index, bool preauth)
12584{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012585 struct net_device *dev = pAdapter->dev;
12586 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12587
12588 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012589 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590
12591 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012592 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012593 return -EINVAL;
12594 }
12595
12596 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012597 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12599 cfg80211_pmksa_candidate_notify(dev, index,
12600 pRoamInfo->bssid.bytes,
12601 preauth, GFP_KERNEL);
12602 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012603 return 0;
12604}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012605
12606#ifdef FEATURE_WLAN_LFR_METRICS
12607/**
12608 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12609 * @pAdapter: Pointer to adapter
12610 * @pRoamInfo: Pointer to roam info
12611 *
12612 * 802.11r/LFR metrics reporting function to report preauth initiation
12613 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012614 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012615 */
12616#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012617QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 tCsrRoamInfo *pRoamInfo)
12619{
12620 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12621 union iwreq_data wrqu;
12622
12623 ENTER();
12624
12625 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012626 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012627 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012628 }
12629
12630 /* create the event */
12631 memset(&wrqu, 0, sizeof(wrqu));
12632 memset(metrics_notification, 0, sizeof(metrics_notification));
12633
12634 wrqu.data.pointer = metrics_notification;
12635 wrqu.data.length = scnprintf(metrics_notification,
12636 sizeof(metrics_notification),
12637 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12638 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12639
12640 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12641 metrics_notification);
12642
12643 EXIT();
12644
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012645 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012646}
12647
12648/**
12649 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12650 * @pAdapter: Pointer to adapter
12651 * @pRoamInfo: Pointer to roam info
12652 * @preauth_status: Preauth status
12653 *
12654 * 802.11r/LFR metrics reporting function to report handover initiation
12655 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012656 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012657 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012658QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12660 tCsrRoamInfo *pRoamInfo,
12661 bool preauth_status)
12662{
12663 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12664 union iwreq_data wrqu;
12665
12666 ENTER();
12667
12668 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012669 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012670 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671 }
12672
12673 /* create the event */
12674 memset(&wrqu, 0, sizeof(wrqu));
12675 memset(metrics_notification, 0, sizeof(metrics_notification));
12676
12677 scnprintf(metrics_notification, sizeof(metrics_notification),
12678 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12679 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12680
12681 if (1 == preauth_status)
12682 strlcat(metrics_notification, " true",
12683 sizeof(metrics_notification));
12684 else
12685 strlcat(metrics_notification, " false",
12686 sizeof(metrics_notification));
12687
12688 wrqu.data.pointer = metrics_notification;
12689 wrqu.data.length = strlen(metrics_notification);
12690
12691 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12692 metrics_notification);
12693
12694 EXIT();
12695
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012696 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012697}
12698
12699/**
12700 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12701 * @pAdapter: Pointer to adapter
12702 * @pRoamInfo: Pointer to roam info
12703 *
12704 * 802.11r/LFR metrics reporting function to report handover initiation
12705 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012706 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012707 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012708QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012709 tCsrRoamInfo *pRoamInfo)
12710{
12711 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12712 union iwreq_data wrqu;
12713
12714 ENTER();
12715
12716 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012717 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012718 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012719 }
12720
12721 /* create the event */
12722 memset(&wrqu, 0, sizeof(wrqu));
12723 memset(metrics_notification, 0, sizeof(metrics_notification));
12724
12725 wrqu.data.pointer = metrics_notification;
12726 wrqu.data.length = scnprintf(metrics_notification,
12727 sizeof(metrics_notification),
12728 "QCOM: LFR_PREAUTH_HANDOVER "
12729 MAC_ADDRESS_STR,
12730 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12731
12732 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12733 metrics_notification);
12734
12735 EXIT();
12736
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012737 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012738}
12739#endif
12740
12741/**
12742 * hdd_select_cbmode() - select channel bonding mode
12743 * @pAdapter: Pointer to adapter
12744 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012745 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012746 *
12747 * Return: none
12748 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012749void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12750 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012751{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012752 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012753 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012754 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012755
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012756 /*
12757 * CDS api expects secondary channel for calculating
12758 * the channel params
12759 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012760 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012761 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12762 if (operationChannel >= 1 && operationChannel <= 5)
12763 sec_ch = operationChannel + 4;
12764 else if (operationChannel >= 6 && operationChannel <= 13)
12765 sec_ch = operationChannel - 4;
12766 }
12767
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012768 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012769 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012770
12771 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012772 eHddDot11Mode hdd_dot11_mode;
12773 uint8_t iniDot11Mode =
12774 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12775
12776 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12777 switch (iniDot11Mode) {
12778 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012779 case eHDD_DOT11_MODE_11ax:
12780 case eHDD_DOT11_MODE_11ax_ONLY:
12781 if (sme_is_feature_supported_by_fw(DOT11AX))
12782 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12783 else if (sme_is_feature_supported_by_fw(DOT11AC))
12784 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12785 else
12786 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12787 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012788 case eHDD_DOT11_MODE_11ac:
12789 case eHDD_DOT11_MODE_11ac_ONLY:
12790 if (sme_is_feature_supported_by_fw(DOT11AC))
12791 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12792 else
12793 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12794 break;
12795 case eHDD_DOT11_MODE_11n:
12796 case eHDD_DOT11_MODE_11n_ONLY:
12797 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12798 break;
12799 default:
12800 hdd_dot11_mode = iniDot11Mode;
12801 break;
12802 }
12803 ch_info->channel_width = ch_params->ch_width;
12804 ch_info->phy_mode =
12805 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012806 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012807 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012808 hdd_info("ch_info width %d, phymode %d channel %d",
12809 ch_info->channel_width, ch_info->phy_mode,
12810 ch_info->channel);
12811 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012812}
12813
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012814/**
12815 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12816 * @adapter: STA adapter
12817 * @roam_profile: STA roam profile
12818 *
12819 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12820 *
12821 * Return: false if sta-sap conc is not allowed, else return true
12822 */
12823static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12824 tCsrRoamProfile *roam_profile)
12825{
12826 hdd_context_t *hdd_ctx;
12827 hdd_adapter_t *ap_adapter;
12828 hdd_ap_ctx_t *hdd_ap_ctx;
12829 hdd_hostapd_state_t *hostapd_state;
12830 uint8_t channel = 0;
12831 QDF_STATUS status;
12832
12833 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12834 if (!hdd_ctx) {
12835 hdd_err("HDD context is NULL");
12836 return true;
12837 }
12838
12839 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12840 /* probably no sap running, no handling required */
12841 if (ap_adapter == NULL)
12842 return true;
12843
12844 /*
12845 * sap is not in started state, so it is fine to go ahead with sta.
12846 * if sap is currently doing CAC then don't allow sta to go further.
12847 */
12848 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12849 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12850 return true;
12851
12852 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12853 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12854 return false;
12855 }
12856
12857 /*
12858 * log and return error, if we allow STA to go through, we don't
12859 * know what is going to happen better stop sta connection
12860 */
12861 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12862 if (NULL == hdd_ap_ctx) {
12863 hdd_err("AP context not found");
12864 return false;
12865 }
12866
12867 /* sap is on non-dfs channel, nothing to handle */
12868 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12869 hdd_info("sap is on non-dfs channel, sta is allowed");
12870 return true;
12871 }
12872 /*
12873 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012874 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012875 */
12876 status = cds_get_channel_from_scan_result(adapter,
12877 roam_profile, &channel);
12878
Nitesh Shah59774522016-09-16 15:14:21 +053012879 /*
12880 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12881 * channels for roaming case.
12882 */
12883 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12884 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12885 return true;
12886 }
12887
12888 /*
12889 * If channel is 0 or DFS then better to call pcl and find out the
12890 * best channel. If channel is non-dfs 5 GHz then better move SAP
12891 * to STA's channel to make scc, so we have room for 3port MCC
12892 * scenario.
12893 */
12894 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012895 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12896 true);
12897
12898 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12899 qdf_event_reset(&hostapd_state->qdf_event);
12900 status = wlansap_set_channel_change_with_csa(
12901 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12902 hdd_ap_ctx->sapConfig.ch_width_orig);
12903
12904 if (QDF_STATUS_SUCCESS != status) {
12905 hdd_err("Set channel with CSA IE failed, can't allow STA");
12906 return false;
12907 }
12908
12909 /*
12910 * wait here for SAP to finish the channel switch. When channel
12911 * switch happens, SAP sends few beacons with CSA_IE. After
12912 * successfully Transmission of those beacons, it will move its
12913 * state from started to disconnected and move to new channel.
12914 * once it moves to new channel, sap again moves its state
12915 * machine from disconnected to started and set this event.
12916 * wait for 10 secs to finish this.
12917 */
12918 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12919 if (!QDF_IS_STATUS_SUCCESS(status)) {
12920 hdd_err("wait for qdf_event failed, STA not allowed!!");
12921 return false;
12922 }
12923
12924 return true;
12925}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012926
Abhishek Singhcfb44482017-03-10 12:42:37 +053012927#ifdef WLAN_FEATURE_11W
12928/**
12929 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12930 * @roam_profile: pointer to roam profile
12931 *
12932 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12933 * or pmf=2 is an explicit configuration in the supplicant
12934 * configuration, drop the connection request.
12935 *
12936 * Return: 0 if check result is valid, otherwise return error code
12937 */
12938static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12939{
12940 if (roam_profile->MFPEnabled &&
12941 !(roam_profile->MFPRequired ||
12942 roam_profile->MFPCapable)) {
12943 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12944 roam_profile->MFPEnabled,
12945 roam_profile->MFPRequired,
12946 roam_profile->MFPCapable);
12947 return -EINVAL;
12948 }
12949 return 0;
12950}
12951#else
12952static inline
12953int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12954{
12955 return 0;
12956}
12957#endif
12958
Krunal Soni31949422016-07-29 17:17:53 -070012959/**
12960 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012962 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012963 * @ssid_len: Length of ssid
12964 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012965 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012966 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012967 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012968 *
12969 * This function is used to start the association process
12970 *
12971 * Return: 0 for success, non-zero for failure
12972 */
Krunal Soni31949422016-07-29 17:17:53 -070012973static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012975 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012976 u8 operatingChannel,
12977 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012978{
12979 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012980 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012981 hdd_wext_state_t *pWextState;
12982 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012983 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012984 uint32_t roamId;
12985 tCsrRoamProfile *pRoamProfile;
12986 eCsrAuthType RSNAuthType;
12987 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012988 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012989
12990 ENTER();
12991
12992 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12993 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012994 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995
12996 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012997 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012998 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012999
13000 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013001 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013002 status = -EINVAL;
13003 goto ret_status;
13004 }
13005
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +053013006 if (true == cds_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013007 hdd_err("Connection refused: conn in progress");
13008 status = -EINVAL;
13009 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010 }
13011
13012 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013013 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13014 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015
13016 if (pRoamProfile) {
13017 hdd_station_ctx_t *pHddStaCtx;
13018 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13019
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013020 /* Restart the opportunistic timer
13021 *
13022 * If hw_mode_change_in_progress is true, then wait
13023 * till firmware sends the callback for hw_mode change.
13024 *
13025 * Else set connect_in_progress as true and proceed.
13026 */
13027 cds_restart_opportunistic_timer(false);
13028 if (cds_is_hw_mode_change_in_progress()) {
13029 status = qdf_wait_for_connection_update();
13030 if (!QDF_IS_STATUS_SUCCESS(status)) {
13031 hdd_err("qdf wait for event failed!!");
13032 status = -EINVAL;
13033 goto ret_status;
13034 }
13035 }
13036 cds_set_connection_in_progress(true);
13037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013038 if (HDD_WMM_USER_MODE_NO_QOS ==
13039 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13040 /*QoS not enabled in cfg file */
13041 pRoamProfile->uapsd_mask = 0;
13042 } else {
13043 /*QoS enabled, update uapsd mask from cfg file */
13044 pRoamProfile->uapsd_mask =
13045 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13046 }
13047
13048 pRoamProfile->SSIDs.numOfSSIDs = 1;
13049 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013050 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013051 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013052 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 ssid, ssid_len);
13054
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013055 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013056 /* cleanup bssid hint */
13057 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13058 QDF_MAC_ADDR_SIZE);
13059 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13060 QDF_MAC_ADDR_SIZE);
13061
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013062 if (bssid) {
13063 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013064 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013065 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013066 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013067 /*
13068 * Save BSSID in seperate variable as
13069 * pRoamProfile's BSSID is getting zeroed out in the
13070 * association process. In case of join failure
13071 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013072 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013073 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013074 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013075 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013077 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13078 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013079 /*
13080 * Save BSSID in a separate variable as
13081 * pRoamProfile's BSSID is getting zeroed out in the
13082 * association process. In case of join failure
13083 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013085 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013086 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013087 hdd_info("bssid_hint is given by upper layer %pM",
13088 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013089 }
13090
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013091 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013092 pRoamProfile->SSIDs.SSIDList->SSID.length,
13093 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13094 operatingChannel);
13095
13096 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13097 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013099 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13100 }
13101#ifdef FEATURE_WLAN_WAPI
13102 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013103 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013104 switch (pAdapter->wapi_info.wapiAuthMode) {
13105 case WAPI_AUTH_MODE_PSK:
13106 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013107 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013108 pAdapter->wapi_info.wapiAuthMode);
13109 pRoamProfile->AuthType.authType[0] =
13110 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13111 break;
13112 }
13113 case WAPI_AUTH_MODE_CERT:
13114 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013115 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013116 pAdapter->wapi_info.wapiAuthMode);
13117 pRoamProfile->AuthType.authType[0] =
13118 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13119 break;
13120 }
13121 } /* End of switch */
13122 if (pAdapter->wapi_info.wapiAuthMode ==
13123 WAPI_AUTH_MODE_PSK
13124 || pAdapter->wapi_info.wapiAuthMode ==
13125 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013126 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013127 pRoamProfile->AuthType.numEntries = 1;
13128 pRoamProfile->EncryptionType.numEntries = 1;
13129 pRoamProfile->EncryptionType.encryptionType[0] =
13130 eCSR_ENCRYPT_TYPE_WPI;
13131 pRoamProfile->mcEncryptionType.numEntries = 1;
13132 pRoamProfile->mcEncryptionType.
13133 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13134 }
13135 }
Krunal Soni31949422016-07-29 17:17:53 -070013136#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013137 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138 pRoamProfile->csrPersona = pAdapter->device_mode;
13139
13140 if (operatingChannel) {
13141 pRoamProfile->ChannelInfo.ChannelList =
13142 &operatingChannel;
13143 pRoamProfile->ChannelInfo.numOfChannels = 1;
13144 } else {
13145 pRoamProfile->ChannelInfo.ChannelList = NULL;
13146 pRoamProfile->ChannelInfo.numOfChannels = 0;
13147 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013148 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013149 && operatingChannel) {
13150 /*
13151 * Need to post the IBSS power save parameters
13152 * to WMA. WMA will configure this parameters
13153 * to firmware if power save is enabled by the
13154 * firmware.
13155 */
13156 status = hdd_set_ibss_power_save_params(pAdapter);
13157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013158 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013159 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013160 status = -EINVAL;
13161 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013162 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013163 pRoamProfile->ch_params.ch_width =
13164 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013165 /*
13166 * In IBSS mode while operating in 2.4 GHz,
13167 * the device supports only 20 MHz.
13168 */
13169 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13170 pRoamProfile->ch_params.ch_width =
13171 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013172 hdd_select_cbmode(pAdapter, operatingChannel,
13173 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013174 }
13175
Abhishek Singhcfb44482017-03-10 12:42:37 +053013176 if (wlan_hdd_cfg80211_check_pmf_valid(
13177 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013178 status = -EINVAL;
13179 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 }
13181
Krunal Soni31949422016-07-29 17:17:53 -070013182 /*
13183 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013184 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013185 * enhancements, the supplicant is not issuing the scan command
13186 * now. So the unicast frames which are sent from the host are
13187 * not having the additional IEs. If it is P2P CLIENT and there
13188 * is no additional IE present in roamProfile, then use the
13189 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013190 */
13191
Krunal Sonib4326f22016-03-10 13:05:51 -080013192 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013193 (!pRoamProfile->pAddIEScan)) {
13194 pRoamProfile->pAddIEScan =
13195 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13196 pRoamProfile->nAddIEScanLength =
13197 pAdapter->scan_info.scanAddIE.length;
13198 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199
Krunal Soni3091bcc2016-06-23 12:28:21 -070013200 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013201 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13202 pRoamProfile))) {
13203 hdd_err("sap-sta conc will fail, can't allow sta");
13204 hdd_conn_set_connection_state(pAdapter,
13205 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013206 status = -ENOMEM;
13207 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013208 }
13209
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013210 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211 if (!sme_config) {
13212 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013213 hdd_conn_set_connection_state(pAdapter,
13214 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013215 status = -ENOMEM;
13216 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013218 sme_get_config_param(pHddCtx->hHal, sme_config);
13219 /* These values are not sessionized. So, any change in these SME
13220 * configs on an older or parallel interface will affect the
13221 * cb mode. So, restoring the default INI params before starting
13222 * interfaces such as sta, cli etc.,
13223 */
13224 sme_config->csrConfig.channelBondingMode5GHz =
13225 pHddCtx->config->nChannelBondingMode5GHz;
13226 sme_config->csrConfig.channelBondingMode24GHz =
13227 pHddCtx->config->nChannelBondingMode24GHz;
13228 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013229 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013230 /*
13231 * Change conn_state to connecting before sme_roam_connect(),
13232 * because sme_roam_connect() has a direct path to call
13233 * hdd_sme_roam_callback(), which will change the conn_state
13234 * If direct path, conn_state will be accordingly changed to
13235 * NotConnected or Associated by either
13236 * hdd_association_completion_handler() or
13237 * hdd_dis_connect_handler() in sme_RoamCallback()if
13238 * sme_RomConnect is to be queued,
13239 * Connecting state will remain until it is completed.
13240 *
13241 * If connection state is not changed, connection state will
13242 * remain in eConnectionState_NotConnected state.
13243 * In hdd_association_completion_handler, "hddDisconInProgress"
13244 * is set to true if conn state is
13245 * eConnectionState_NotConnected.
13246 * If "hddDisconInProgress" is set to true then cfg80211 layer
13247 * is not informed of connect result indication which
13248 * is an issue.
13249 */
13250 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013251 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013252 hdd_conn_set_connection_state(pAdapter,
13253 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013254
Komal Seelama89be8d2016-09-29 11:09:26 +053013255 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13256 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013257 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 pAdapter->sessionId, pRoamProfile,
13259 &roamId);
13260
Rajeev Kumard31e1542017-01-13 14:37:42 -080013261 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013262 (QDF_STA_MODE == pAdapter->device_mode ||
13263 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013264 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013265 "qdf_status %d. -> NotConnected",
13266 pAdapter->sessionId, qdf_status);
13267 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268 /* change back to NotAssociated */
13269 hdd_conn_set_connection_state(pAdapter,
13270 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013271 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13272 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013273 }
13274
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013275 /* Reset connect_in_progress */
13276 cds_set_connection_in_progress(false);
13277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278 pRoamProfile->ChannelInfo.ChannelList = NULL;
13279 pRoamProfile->ChannelInfo.numOfChannels = 0;
13280
Nitesh Shah044fd672016-10-13 18:53:25 +053013281 if ((QDF_STA_MODE == pAdapter->device_mode)
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013282 && wma_is_current_hwmode_dbs() &&
13283 !wma_is_hw_dbs_2x2_capable()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013284 cds_get_channel_from_scan_result(pAdapter,
13285 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013286 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013287 if (channel)
13288 cds_checkn_update_hw_mode_single_mac_mode
13289 (channel);
13290 }
13291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013293 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013294 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013295 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013296 goto ret_status;
13297
13298conn_failure:
13299 /* Reset connect_in_progress */
13300 cds_set_connection_in_progress(false);
13301
13302ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013303 EXIT();
13304 return status;
13305}
13306
13307/**
13308 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13309 * @pAdapter: Pointer to adapter
13310 * @auth_type: Auth type
13311 *
13312 * This function is used to set the authentication type (OPEN/SHARED).
13313 *
13314 * Return: 0 for success, non-zero for failure
13315 */
13316static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13317 enum nl80211_auth_type auth_type)
13318{
13319 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13320 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013322 /*set authentication type */
13323 switch (auth_type) {
13324 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013325 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13327 break;
13328
13329 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013330 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013331 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13333 break;
13334
13335 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013336 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013337 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13338 break;
13339#ifdef FEATURE_WLAN_ESE
13340 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013341 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13343 break;
13344#endif
13345
13346 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013347 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13349 return -EINVAL;
13350 }
13351
13352 pWextState->roamProfile.AuthType.authType[0] =
13353 pHddStaCtx->conn_info.authType;
13354 return 0;
13355}
13356
13357/**
13358 * wlan_hdd_set_akm_suite() - set key management type
13359 * @pAdapter: Pointer to adapter
13360 * @key_mgmt: Key management type
13361 *
13362 * This function is used to set the key mgmt type(PSK/8021x).
13363 *
13364 * Return: 0 for success, non-zero for failure
13365 */
13366static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13367{
13368 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13371#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13372 /*set key mgmt type */
13373 switch (key_mgmt) {
13374 case WLAN_AKM_SUITE_PSK:
13375 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013376 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013377 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013378 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13379 break;
13380
13381 case WLAN_AKM_SUITE_8021X_SHA256:
13382 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013383 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013384 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013385 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13386 break;
13387#ifdef FEATURE_WLAN_ESE
13388#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13389#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13390 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013391 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13393 break;
13394#endif
13395#ifndef WLAN_AKM_SUITE_OSEN
13396#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13397#endif
13398 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013399 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013400 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13401 break;
13402
13403 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013404 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013405 return -EINVAL;
13406
13407 }
13408 return 0;
13409}
13410
13411/**
13412 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13413 * @pAdapter: Pointer to adapter
13414 * @cipher: Cipher type
13415 * @ucast: Unicast flag
13416 *
13417 * This function is used to set the encryption type
13418 * (NONE/WEP40/WEP104/TKIP/CCMP).
13419 *
13420 * Return: 0 for success, non-zero for failure
13421 */
13422static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13423 u32 cipher, bool ucast)
13424{
13425 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13426 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13427 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013430 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013431 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13432 } else {
13433
13434 /*set encryption method */
13435 switch (cipher) {
13436 case IW_AUTH_CIPHER_NONE:
13437 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13438 break;
13439
13440 case WLAN_CIPHER_SUITE_WEP40:
13441 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13442 break;
13443
13444 case WLAN_CIPHER_SUITE_WEP104:
13445 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13446 break;
13447
13448 case WLAN_CIPHER_SUITE_TKIP:
13449 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13450 break;
13451
13452 case WLAN_CIPHER_SUITE_CCMP:
13453 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13454 break;
13455#ifdef FEATURE_WLAN_WAPI
13456 case WLAN_CIPHER_SUITE_SMS4:
13457 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13458 break;
13459#endif
13460
13461#ifdef FEATURE_WLAN_ESE
13462 case WLAN_CIPHER_SUITE_KRK:
13463 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13464 break;
13465#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13466 case WLAN_CIPHER_SUITE_BTK:
13467 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13468 break;
13469#endif
13470#endif
13471 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013472 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013473 return -EOPNOTSUPP;
13474 }
13475 }
13476
13477 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013478 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013479 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13480 pWextState->roamProfile.EncryptionType.numEntries = 1;
13481 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13482 encryptionType;
13483 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013484 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013485 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13486 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13487 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13488 encryptionType;
13489 }
13490
13491 return 0;
13492}
13493
13494/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013495 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13496 * @wext_state: Pointer to wext state
13497 * @gen_ie: Pointer to IE data
13498 * @len: length of IE data
13499 *
13500 * Return: 0 for success, non-zero for failure
13501 */
13502static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13503 const uint8_t *gen_ie, uint16_t len)
13504{
13505 uint16_t cur_add_ie_len =
13506 wext_state->assocAddIE.length;
13507
13508 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13509 (wext_state->assocAddIE.length + len)) {
13510 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13511 QDF_ASSERT(0);
13512 return -ENOMEM;
13513 }
13514 memcpy(wext_state->assocAddIE.addIEdata +
13515 cur_add_ie_len, gen_ie, len);
13516 wext_state->assocAddIE.length += len;
13517
13518 wext_state->roamProfile.pAddIEAssoc =
13519 wext_state->assocAddIE.addIEdata;
13520 wext_state->roamProfile.nAddIEAssocLength =
13521 wext_state->assocAddIE.length;
13522 return 0;
13523}
13524
13525/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 * wlan_hdd_cfg80211_set_ie() - set IEs
13527 * @pAdapter: Pointer to adapter
13528 * @ie: Pointer ot ie
13529 * @ie: IE length
13530 *
13531 * Return: 0 for success, non-zero for failure
13532 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013533static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534 size_t ie_len)
13535{
13536 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13537 const uint8_t *genie = ie;
13538 uint16_t remLen = ie_len;
13539#ifdef FEATURE_WLAN_WAPI
13540 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13541 u16 *tmp;
13542 uint16_t akmsuiteCount;
13543 int *akmlist;
13544#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013545 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546
13547 /* clear previous assocAddIE */
13548 pWextState->assocAddIE.length = 0;
13549 pWextState->roamProfile.bWPSAssociation = false;
13550 pWextState->roamProfile.bOSENAssociation = false;
13551
13552 while (remLen >= 2) {
13553 uint16_t eLen = 0;
13554 uint8_t elementId;
13555 elementId = *genie++;
13556 eLen = *genie++;
13557 remLen -= 2;
13558
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013559 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013560
13561 switch (elementId) {
13562 case DOT11F_EID_WPA:
13563 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 -070013564 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565 return -EINVAL;
13566 } else if (0 ==
13567 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13568 uint16_t curAddIELen =
13569 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013570 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571
13572 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13573 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013574 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013575 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013576 return -ENOMEM;
13577 }
13578 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13579 memcpy(pWextState->assocAddIE.addIEdata +
13580 curAddIELen, genie - 2, eLen + 2);
13581 pWextState->assocAddIE.length += eLen + 2;
13582
13583 pWextState->roamProfile.bWPSAssociation = true;
13584 pWextState->roamProfile.pAddIEAssoc =
13585 pWextState->assocAddIE.addIEdata;
13586 pWextState->roamProfile.nAddIEAssocLength =
13587 pWextState->assocAddIE.length;
13588 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013589 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590 memset(pWextState->WPARSNIE, 0,
13591 MAX_WPA_RSN_IE_LEN);
13592 memcpy(pWextState->WPARSNIE, genie - 2,
13593 (eLen + 2));
13594 pWextState->roamProfile.pWPAReqIE =
13595 pWextState->WPARSNIE;
13596 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13597 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13598 P2P_OUI_TYPE_SIZE))) {
13599 uint16_t curAddIELen =
13600 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013601 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013602
13603 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13604 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013605 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013606 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 return -ENOMEM;
13608 }
13609 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13610 memcpy(pWextState->assocAddIE.addIEdata +
13611 curAddIELen, genie - 2, eLen + 2);
13612 pWextState->assocAddIE.length += eLen + 2;
13613
13614 pWextState->roamProfile.pAddIEAssoc =
13615 pWextState->assocAddIE.addIEdata;
13616 pWextState->roamProfile.nAddIEAssocLength =
13617 pWextState->assocAddIE.length;
13618 }
13619#ifdef WLAN_FEATURE_WFD
13620 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13621 WFD_OUI_TYPE_SIZE)) &&
13622 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013623 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013624 pAdapter->device_mode)) {
13625 uint16_t curAddIELen =
13626 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013627 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013628
13629 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13630 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013631 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013632 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013633 return -ENOMEM;
13634 }
13635 /* WFD IE is saved to Additional IE ; it should
13636 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013637 * WFD IE
13638 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 memcpy(pWextState->assocAddIE.addIEdata +
13640 curAddIELen, genie - 2, eLen + 2);
13641 pWextState->assocAddIE.length += eLen + 2;
13642
13643 pWextState->roamProfile.pAddIEAssoc =
13644 pWextState->assocAddIE.addIEdata;
13645 pWextState->roamProfile.nAddIEAssocLength =
13646 pWextState->assocAddIE.length;
13647 }
13648#endif
13649 /* Appending HS 2.0 Indication Element in Assiciation Request */
13650 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13651 HS20_OUI_TYPE_SIZE))) {
13652 uint16_t curAddIELen =
13653 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013654 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655
13656 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13657 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013658 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013659 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 return -ENOMEM;
13661 }
13662 memcpy(pWextState->assocAddIE.addIEdata +
13663 curAddIELen, genie - 2, eLen + 2);
13664 pWextState->assocAddIE.length += eLen + 2;
13665
13666 pWextState->roamProfile.pAddIEAssoc =
13667 pWextState->assocAddIE.addIEdata;
13668 pWextState->roamProfile.nAddIEAssocLength =
13669 pWextState->assocAddIE.length;
13670 }
13671 /* Appending OSEN Information Element in Assiciation Request */
13672 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13673 OSEN_OUI_TYPE_SIZE))) {
13674 uint16_t curAddIELen =
13675 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013676 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013677
13678 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13679 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013680 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013681 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013682 return -ENOMEM;
13683 }
13684 memcpy(pWextState->assocAddIE.addIEdata +
13685 curAddIELen, genie - 2, eLen + 2);
13686 pWextState->assocAddIE.length += eLen + 2;
13687
13688 pWextState->roamProfile.bOSENAssociation = true;
13689 pWextState->roamProfile.pAddIEAssoc =
13690 pWextState->assocAddIE.addIEdata;
13691 pWextState->roamProfile.nAddIEAssocLength =
13692 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013693 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13694 MBO_OUI_TYPE_SIZE))){
13695 hdd_info("Set MBO IE(len %d)", eLen + 2);
13696 status = wlan_hdd_add_assoc_ie(pWextState,
13697 genie - 2, eLen + 2);
13698 if (status)
13699 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 } else {
13701 uint16_t add_ie_len =
13702 pWextState->assocAddIE.length;
13703
13704 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13705
13706 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13707 (pWextState->assocAddIE.length + eLen)) {
13708 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013709 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013710 return -ENOMEM;
13711 }
13712
13713 memcpy(pWextState->assocAddIE.addIEdata +
13714 add_ie_len, genie - 2, eLen + 2);
13715 pWextState->assocAddIE.length += eLen + 2;
13716
13717 pWextState->roamProfile.pAddIEAssoc =
13718 pWextState->assocAddIE.addIEdata;
13719 pWextState->roamProfile.nAddIEAssocLength =
13720 pWextState->assocAddIE.length;
13721 }
13722 break;
13723 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013724 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13726 memcpy(pWextState->WPARSNIE, genie - 2,
13727 (eLen + 2));
13728 pWextState->roamProfile.pRSNReqIE =
13729 pWextState->WPARSNIE;
13730 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13731 break;
13732 /*
13733 * Appending Extended Capabilities with Interworking bit set
13734 * in Assoc Req.
13735 *
13736 * In assoc req this EXT Cap will only be taken into account if
13737 * interworkingService bit is set to 1. Currently
13738 * driver is only interested in interworkingService capability
13739 * from supplicant. If in future any other EXT Cap info is
13740 * required from supplicat, it needs to be handled while
13741 * sending Assoc Req in LIM.
13742 */
13743 case DOT11F_EID_EXTCAP:
13744 {
13745 uint16_t curAddIELen =
13746 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013747 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748
13749 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13750 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013751 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013752 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013753 return -ENOMEM;
13754 }
13755 memcpy(pWextState->assocAddIE.addIEdata +
13756 curAddIELen, genie - 2, eLen + 2);
13757 pWextState->assocAddIE.length += eLen + 2;
13758
13759 pWextState->roamProfile.pAddIEAssoc =
13760 pWextState->assocAddIE.addIEdata;
13761 pWextState->roamProfile.nAddIEAssocLength =
13762 pWextState->assocAddIE.length;
13763 break;
13764 }
13765#ifdef FEATURE_WLAN_WAPI
13766 case WLAN_EID_WAPI:
13767 /* Setting WAPI Mode to ON=1 */
13768 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013769 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013770 tmp = (u16 *) ie;
13771 tmp = tmp + 2; /* Skip element Id and Len, Version */
13772 akmsuiteCount = WPA_GET_LE16(tmp);
13773 tmp = tmp + 1;
13774 akmlist = (int *)(tmp);
13775 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13776 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13777 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013778 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013779 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 return -EINVAL;
13781 }
13782
13783 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013784 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013785 pAdapter->wapi_info.wapiAuthMode =
13786 WAPI_AUTH_MODE_PSK;
13787 }
13788 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013789 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013790 pAdapter->wapi_info.wapiAuthMode =
13791 WAPI_AUTH_MODE_CERT;
13792 }
13793 break;
13794#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013795 case DOT11F_EID_SUPPOPERATINGCLASSES:
13796 {
13797 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13798 status = wlan_hdd_add_assoc_ie(pWextState,
13799 genie - 2, eLen + 2);
13800 if (status)
13801 return status;
13802 break;
13803 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013804 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013805 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013806 /* when Unknown IE is received we break
13807 * and continue to the next IE in the buffer
13808 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013809 break;
13810 }
13811 genie += eLen;
13812 remLen -= eLen;
13813 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013814 return 0;
13815}
13816
13817/**
13818 * hdd_is_wpaie_present() - check for WPA ie
13819 * @ie: Pointer to ie
13820 * @ie_len: Ie length
13821 *
13822 * Parse the received IE to find the WPA IE
13823 *
13824 * Return: true if wpa ie is found else false
13825 */
13826static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13827{
13828 uint8_t eLen = 0;
13829 uint16_t remLen = ie_len;
13830 uint8_t elementId = 0;
13831
13832 while (remLen >= 2) {
13833 elementId = *ie++;
13834 eLen = *ie++;
13835 remLen -= 2;
13836 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013837 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013838 return false;
13839 }
13840 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13841 /* OUI - 0x00 0X50 0XF2
13842 * WPA Information Element - 0x01
13843 * WPA version - 0x01
13844 */
13845 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13846 return true;
13847 }
13848 ie += eLen;
13849 remLen -= eLen;
13850 }
13851 return false;
13852}
13853
13854/**
13855 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13856 * @pAdapter: Pointer to adapter
13857 * @req: Pointer to security parameters
13858 *
13859 * Return: 0 for success, non-zero for failure
13860 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013861static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13862 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013863{
13864 int status = 0;
13865 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13866 ENTER();
13867
13868 /*set wpa version */
13869 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13870
13871 if (req->crypto.wpa_versions) {
13872 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13873 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13874 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13875 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13876 }
13877 }
13878
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013879 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880
13881 /*set authentication type */
13882 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13883
13884 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013885 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013886 return status;
13887 }
13888
13889 /*set key mgmt type */
13890 if (req->crypto.n_akm_suites) {
13891 status =
13892 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13893 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013894 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013895 return status;
13896 }
13897 }
13898
13899 /*set pairwise cipher type */
13900 if (req->crypto.n_ciphers_pairwise) {
13901 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13902 req->crypto.
13903 ciphers_pairwise[0],
13904 true);
13905 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013906 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013907 return status;
13908 }
13909 } else {
13910 /*Reset previous cipher suite to none */
13911 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13912 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013913 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 return status;
13915 }
13916 }
13917
13918 /*set group cipher type */
13919 status =
13920 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13921 false);
13922
13923 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013924 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013925 return status;
13926 }
13927#ifdef WLAN_FEATURE_11W
13928 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13929#endif
13930
13931 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13932 if (req->ie_len) {
13933 status =
13934 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13935 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013936 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 return status;
13938 }
13939 }
13940
13941 /*incase of WEP set default key information */
13942 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013943 u8 key_len = req->key_len;
13944 u8 key_idx = req->key_idx;
13945
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013946 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13947 || (WLAN_CIPHER_SUITE_WEP104 ==
13948 req->crypto.ciphers_pairwise[0])
13949 ) {
13950 if (IW_AUTH_KEY_MGMT_802_1X
13951 ==
13952 (pWextState->
13953 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013954 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013955 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013956 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013957
Jeff Johnson68755312017-02-10 11:46:55 -080013958 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13959 && (CSR_MAX_NUM_KEY > key_idx)) {
13960 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13961 key_idx, key_len);
13962 qdf_mem_copy(&pWextState->roamProfile.
13963 Keys.
13964 KeyMaterial[key_idx][0],
13965 req->key, key_len);
13966 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013968 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013969 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013970 }
13971 }
13972 }
13973
13974 return status;
13975}
13976
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013977int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013978{
13979 unsigned long rc;
13980 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013981 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013982 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983
13984 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013985 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13986 if (pAdapter->device_mode == QDF_STA_MODE) {
13987 hdd_notice("Stop firmware roaming");
13988 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
13989 }
13990 /*
13991 * If firmware has already started roaming process, driver
13992 * needs to defer the processing of this disconnect request.
13993 *
13994 */
13995 if (hdd_is_roaming_in_progress(pAdapter)) {
13996 /*
13997 * Defer the disconnect action until firmware roaming
13998 * result is received. If STA is in connected state after
13999 * that, send the disconnect command to CSR, otherwise
14000 * CSR would have already sent disconnect event to upper
14001 * layer.
14002 */
14003
14004 hdd_err("Roaming in progress, <try disconnect> deferred.");
14005 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14006 pAdapter->cfg80211_disconnect_reason =
14007 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14008 return 0;
14009 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014010
Jeff Johnson9edf9572016-10-03 15:24:49 -070014011 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014012 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14013 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14014 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014015 hdd_conn_set_connection_state(pAdapter,
14016 eConnectionState_Disconnecting);
14017 /* Issue disconnect to CSR */
14018 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014019
14020 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14021 pAdapter->sessionId,
14022 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14023 /*
14024 * Wait here instead of returning directly, this will block the
14025 * next connect command and allow processing of the scan for
14026 * ssid and the previous connect command in CSR. Else we might
14027 * hit some race conditions leading to SME and HDD out of sync.
14028 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014029 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014030 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
14031 } else if (0 != status) {
14032 hdd_err("csrRoamDisconnect failure, returned %d",
14033 (int)status);
14034 pHddStaCtx->staDebugState = status;
14035 result = -EINVAL;
14036 goto disconnected;
14037 }
14038
14039 rc = wait_for_completion_timeout(
14040 &pAdapter->disconnect_comp_var,
14041 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014042 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014043 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
14044 pAdapter->sessionId, pHddStaCtx->staDebugState);
14045 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 }
14047 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014048 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014049 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014050 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014051 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014052 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014053 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014054 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014055 }
14056 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014057disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014058 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14059 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060}
14061
14062/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014063 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14064 * @adapter: Pointer to the HDD adapter
14065 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014066 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014067 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014068 * This function will start reassociation if prev_bssid is set and bssid/
14069 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014070 *
Naveen Rawat07332902016-07-27 09:13:17 -070014071 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014072 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014073#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14074 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014075static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14076 struct cfg80211_connect_params *req,
14077 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014078{
Naveen Rawat07332902016-07-27 09:13:17 -070014079 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014080 const uint8_t *bssid = NULL;
14081 uint16_t channel = 0;
14082
14083 if (req->bssid)
14084 bssid = req->bssid;
14085 else if (req->bssid_hint)
14086 bssid = req->bssid_hint;
14087
14088 if (req->channel)
14089 channel = req->channel->hw_value;
14090 else if (req->channel_hint)
14091 channel = req->channel_hint->hw_value;
14092
14093 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014094 reassoc = true;
14095 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014096 channel, MAC_ADDR_ARRAY(bssid));
14097 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014098 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014099 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014100 }
Naveen Rawat07332902016-07-27 09:13:17 -070014101 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014102}
14103#else
Naveen Rawat07332902016-07-27 09:13:17 -070014104static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14105 struct cfg80211_connect_params *req,
14106 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014107{
Naveen Rawat07332902016-07-27 09:13:17 -070014108 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014109}
14110#endif
14111
14112/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014113 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14114 * @wiphy: Pointer to wiphy
14115 * @dev: Pointer to network device
14116 * @req: Pointer to cfg80211 connect request
14117 *
14118 * This function is used to start the association process
14119 *
14120 * Return: 0 for success, non-zero for failure
14121 */
14122static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14123 struct net_device *ndev,
14124 struct cfg80211_connect_params *req)
14125{
14126 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014127 u16 channel;
14128#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14129 const u8 *bssid_hint = req->bssid_hint;
14130#else
14131 const u8 *bssid_hint = NULL;
14132#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14134 hdd_context_t *pHddCtx;
14135
14136 ENTER();
14137
Anurag Chouhan6d760662016-02-20 16:05:43 +053014138 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014139 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014140 return -EINVAL;
14141 }
14142
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014143 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14144 hdd_err("invalid session id: %d", pAdapter->sessionId);
14145 return -EINVAL;
14146 }
14147
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014148 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014149 TRACE_CODE_HDD_CFG80211_CONNECT,
14150 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014151 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014152 hdd_device_mode_to_string(pAdapter->device_mode),
14153 pAdapter->device_mode);
14154
Krunal Sonib4326f22016-03-10 13:05:51 -080014155 if (pAdapter->device_mode != QDF_STA_MODE &&
14156 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014157 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014158 hdd_device_mode_to_string(pAdapter->device_mode),
14159 pAdapter->device_mode);
14160 return -EINVAL;
14161 }
14162
14163 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14164 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014165 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014166 return -EINVAL;
14167 }
14168
14169 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014170 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014171 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014172
Naveen Rawat07332902016-07-27 09:13:17 -070014173 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014174 return status;
14175
Agrawal Ashishf156e942016-08-04 14:54:47 +053014176 /* Try disconnecting if already in connected state */
14177 status = wlan_hdd_try_disconnect(pAdapter);
14178 if (0 > status) {
14179 hdd_err("Failed to disconnect the existing connection");
14180 return -EALREADY;
14181 }
14182
14183 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014184 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014185 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014186 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014187 pAdapter->device_mode),
14188 req->channel->hw_value, HW_MODE_20_MHZ)) {
14189 hdd_err("This concurrency combination is not allowed");
14190 return -ECONNREFUSED;
14191 }
14192 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014193 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014194 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014195 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14196 hdd_err("This concurrency combination is not allowed");
14197 return -ECONNREFUSED;
14198 }
14199 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014200
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014201 /*initialise security parameters */
14202 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14203
14204 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014205 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014206 return status;
14207 }
14208
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014209 if (req->channel)
14210 channel = req->channel->hw_value;
14211 else
14212 channel = 0;
14213 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14214 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014215 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014217 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014218 return status;
14219 }
14220 EXIT();
14221 return status;
14222}
14223
14224/**
14225 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14226 * @wiphy: Pointer to wiphy
14227 * @dev: Pointer to network device
14228 * @req: Pointer to cfg80211 connect request
14229 *
14230 * Return: 0 for success, non-zero for failure
14231 */
14232static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14233 struct net_device *ndev,
14234 struct cfg80211_connect_params *req)
14235{
14236 int ret;
14237 cds_ssr_protect(__func__);
14238 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14239 cds_ssr_unprotect(__func__);
14240
14241 return ret;
14242}
14243
14244/**
14245 * wlan_hdd_disconnect() - hdd disconnect api
14246 * @pAdapter: Pointer to adapter
14247 * @reason: Disconnect reason code
14248 *
14249 * This function is used to issue a disconnect request to SME
14250 *
14251 * Return: 0 for success, non-zero for failure
14252 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014253static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014254{
14255 int status, result = 0;
14256 unsigned long rc;
14257 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14258 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014259 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014260 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014262 ENTER();
14263
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 status = wlan_hdd_validate_context(pHddCtx);
14265
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014266 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014268 if (pAdapter->device_mode == QDF_STA_MODE) {
14269 hdd_notice("Stop firmware roaming");
14270 status = sme_stop_roaming(hal, pAdapter->sessionId,
14271 eCsrHddIssued);
14272 }
14273 /*
14274 * If firmware has already started roaming process, driver
14275 * needs to defer the processing of this disconnect request.
14276 */
14277 if (hdd_is_roaming_in_progress(pAdapter)) {
14278 /*
14279 * Defer the disconnect action until firmware roaming
14280 * result is received. If STA is in connected state after
14281 * that, send the disconnect command to CSR, otherwise
14282 * CSR would have already sent disconnect event to upper
14283 * layer.
14284 */
14285 hdd_err("Roaming in progress, disconnect command deferred.");
14286 pAdapter->defer_disconnect =
14287 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14288 pAdapter->cfg80211_disconnect_reason = reason;
14289 return 0;
14290 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014291
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014292 prev_conn_state = pHddStaCtx->conn_info.connState;
14293
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014294 /* stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014295 hdd_notice("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014296 wlan_hdd_netif_queue_control(pAdapter,
14297 WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014298 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14300 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14301
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014302 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303
14304 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14305 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014306 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14307 prev_conn_state != eConnectionState_Connecting) {
14308 hdd_notice("status = %d, already disconnected", status);
14309 result = 0;
14310 goto disconnected;
14311 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14312 /*
14313 * Wait here instead of returning directly, this will block the
14314 * next connect command and allow processing of the scan for
14315 * ssid and the previous connect command in CSR. Else we might
14316 * hit some race conditions leading to SME and HDD out of sync.
14317 */
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014318 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014319 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014320 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014321 (int)status);
14322 pHddStaCtx->staDebugState = status;
14323 result = -EINVAL;
14324 goto disconnected;
14325 }
14326 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14327 msecs_to_jiffies
14328 (WLAN_WAIT_TIME_DISCONNECT));
14329
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014330 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014331 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014332 result = -ETIMEDOUT;
14333 }
14334disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14336#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14337 /* Sending disconnect event to userspace for kernel version < 3.11
14338 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14339 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014340 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014341 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14342 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343#endif
14344
14345 return result;
14346}
14347
14348/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014349 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14350 * @reason: ieee80211 reason code.
14351 *
14352 * This utility function helps log string conversion of reason code.
14353 *
14354 * Return: string conversion of reason code, if match found;
14355 * "Unknown" otherwise.
14356 */
14357static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14358{
14359 switch (reason) {
14360 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14361 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14362 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14363 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14364 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14365 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14366 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14367 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14368 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14369 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14370 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14371 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14372 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14373 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14374 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14375 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14376 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14377 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14378 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14379 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14380 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14381 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14382 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14383 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14384 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14385 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14386 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14387 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14388 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14389 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14390 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14391 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14392 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14393 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14394 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14395 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14396 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14397 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14398 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14399 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14400 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14401 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14402 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14403 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14404 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14405 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14406 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14407 default:
14408 return "Unknown";
14409 }
14410}
14411
14412/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014413 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14414 * @wiphy: Pointer to wiphy
14415 * @dev: Pointer to network device
14416 * @reason: Disconnect reason code
14417 *
14418 * This function is used to issue a disconnect request to SME
14419 *
14420 * Return: 0 for success, non-zero for failure
14421 */
14422static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14423 struct net_device *dev, u16 reason)
14424{
14425 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14426 int status;
14427 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14428 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14429#ifdef FEATURE_WLAN_TDLS
14430 uint8_t staIdx;
14431#endif
14432
14433 ENTER();
14434
Anurag Chouhan6d760662016-02-20 16:05:43 +053014435 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014436 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014437 return -EINVAL;
14438 }
14439
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014440 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14441 hdd_err("invalid session id: %d", pAdapter->sessionId);
14442 return -EINVAL;
14443 }
14444
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014445 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014446 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14447 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014448 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014449 hdd_device_mode_to_string(pAdapter->device_mode),
14450 pAdapter->device_mode, reason);
14451
14452 status = wlan_hdd_validate_context(pHddCtx);
14453
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014454 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014455 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014456
14457 /* Issue disconnect request to SME, if station is in connected state */
14458 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14459 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14460 eCsrRoamDisconnectReason reasonCode =
14461 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14462 hdd_scaninfo_t *pScanInfo;
14463
14464 switch (reason) {
14465 case WLAN_REASON_MIC_FAILURE:
14466 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14467 break;
14468
14469 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14470 case WLAN_REASON_DISASSOC_AP_BUSY:
14471 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14472 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14473 break;
14474
14475 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14476 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14477 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14478 break;
14479
14480 case WLAN_REASON_DEAUTH_LEAVING:
14481 reasonCode =
14482 pHddCtx->config->
14483 gEnableDeauthToDisassocMap ?
14484 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14485 eCSR_DISCONNECT_REASON_DEAUTH;
14486 break;
14487 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14488 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14489 break;
14490 default:
14491 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14492 break;
14493 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014494 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014495 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496 pScanInfo = &pAdapter->scan_info;
14497 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014498 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014500 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014501 eCSR_SCAN_ABORT_DEFAULT);
14502 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014503 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014504#ifdef FEATURE_WLAN_TDLS
14505 /* First clean up the tdls peers if any */
14506 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14507 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14508 pAdapter->sessionId)
14509 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14510 uint8_t *mac;
14511 mac =
14512 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014513 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14514 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 pHddCtx->tdlsConnInfo[staIdx].staId,
14516 pAdapter->sessionId,
14517 MAC_ADDR_ARRAY(mac));
14518 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14519 (pAdapter),
14520 pAdapter->sessionId, mac);
14521 }
14522 }
14523#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014524 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014525 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014526 hdd_info("Disconnect request from user space with reason: %s",
14527 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014528 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14529 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014530 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014531 return -EINVAL;
14532 }
14533 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014534 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014535 pHddStaCtx->conn_info.connState);
14536 }
14537
14538 return status;
14539}
14540
14541/**
14542 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14543 * @wiphy: Pointer to wiphy
14544 * @dev: Pointer to network device
14545 * @reason: Disconnect reason code
14546 *
14547 * Return: 0 for success, non-zero for failure
14548 */
14549static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14550 struct net_device *dev, u16 reason)
14551{
14552 int ret;
14553 cds_ssr_protect(__func__);
14554 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14555 cds_ssr_unprotect(__func__);
14556
14557 return ret;
14558}
14559
14560/**
14561 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14562 * @pAdapter: Pointer to adapter
14563 * @param: Pointer to IBSS parameters
14564 *
14565 * This function is used to initialize the security settings in IBSS mode
14566 *
14567 * Return: 0 for success, non-zero for failure
14568 */
14569static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14570 struct cfg80211_ibss_params
14571 *params)
14572{
14573 int status = 0;
14574 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14575 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14576 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14577
14578 ENTER();
14579
14580 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014581 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 pHddStaCtx->ibss_enc_key_installed = 0;
14583
14584 if (params->ie_len && (NULL != params->ie)) {
14585 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14586 params->ie_len, WLAN_EID_RSN)) {
14587 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14588 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14589 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14590 tDot11fIEWPA dot11WPAIE;
14591 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14592 u8 *ie;
14593
14594 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14595 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14596 params->ie_len,
14597 DOT11F_EID_WPA);
14598 if (NULL != ie) {
14599 pWextState->wpaVersion =
14600 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014601 /* Unpack the WPA IE
14602 * Skip past the EID byte and length byte
14603 * and four byte WiFi OUI
14604 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14606 &ie[2 + 4],
14607 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014608 /* Extract the multicast cipher, the
14609 * encType for unicast cipher for
14610 * wpa-none is none
14611 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014612 encryptionType =
14613 hdd_translate_wpa_to_csr_encryption_type
14614 (dot11WPAIE.multicast_cipher);
14615 }
14616 }
14617
14618 status =
14619 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14620 params->ie_len);
14621
14622 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014623 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 return status;
14625 }
14626 }
14627
14628 pWextState->roamProfile.AuthType.authType[0] =
14629 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14630
14631 if (params->privacy) {
14632 /* Security enabled IBSS, At this time there is no information
14633 * available about the security paramters, so initialise the
14634 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14635 * The correct security parameters will be updated later in
14636 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14637 * set inorder enable privacy bit in beacons
14638 */
14639
14640 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14641 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014642 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014643 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14644 pWextState->roamProfile.EncryptionType.numEntries = 1;
14645 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14646 encryptionType;
14647 return status;
14648}
14649
14650/**
14651 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14652 * @wiphy: Pointer to wiphy
14653 * @dev: Pointer to network device
14654 * @param: Pointer to IBSS join parameters
14655 *
14656 * This function is used to create/join an IBSS network
14657 *
14658 * Return: 0 for success, non-zero for failure
14659 */
14660static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14661 struct net_device *dev,
14662 struct cfg80211_ibss_params *params)
14663{
14664 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14665 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14666 tCsrRoamProfile *pRoamProfile;
14667 int status;
14668 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14669 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014670 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014671 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014672
14673 ENTER();
14674
Anurag Chouhan6d760662016-02-20 16:05:43 +053014675 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014676 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014677 return -EINVAL;
14678 }
14679
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014680 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14681 hdd_err("invalid session id: %d", pAdapter->sessionId);
14682 return -EINVAL;
14683 }
14684
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014685 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014686 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14687 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014688 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689 hdd_device_mode_to_string(pAdapter->device_mode),
14690 pAdapter->device_mode);
14691
14692 status = wlan_hdd_validate_context(pHddCtx);
14693
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014694 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014695 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696
14697 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014698 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014699 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14700 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14701 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14702 int indx;
14703
14704 /* Get channel number */
14705 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014706 params->
14707 chandef.
14708 chan->
14709 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014710
14711 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14712 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014713 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014714 return -EOPNOTSUPP;
14715 }
14716
14717 for (indx = 0; indx < numChans; indx++) {
14718 if (channelNum == validChan[indx]) {
14719 break;
14720 }
14721 }
14722 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014723 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014724 return -EINVAL;
14725 }
14726 }
14727
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014728 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014729 HW_MODE_20_MHZ)) {
14730 hdd_err("This concurrency combination is not allowed");
14731 return -ECONNREFUSED;
14732 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733
Krunal Soni3091bcc2016-06-23 12:28:21 -070014734 status = qdf_reset_connection_update();
14735 if (!QDF_IS_STATUS_SUCCESS(status))
14736 hdd_err("ERR: clear event failed");
14737
14738 status = cds_current_connections_update(pAdapter->sessionId,
14739 channelNum,
14740 SIR_UPDATE_REASON_JOIN_IBSS);
14741 if (QDF_STATUS_E_FAILURE == status) {
14742 hdd_err("ERROR: connections update failed!!");
14743 return -EINVAL;
14744 }
14745
14746 if (QDF_STATUS_SUCCESS == status) {
14747 status = qdf_wait_for_connection_update();
14748 if (!QDF_IS_STATUS_SUCCESS(status)) {
14749 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750 return -EINVAL;
14751 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014752 }
14753
14754 /*Try disconnecting if already in connected state */
14755 status = wlan_hdd_try_disconnect(pAdapter);
14756 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014757 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014758 return -EALREADY;
14759 }
14760
14761 pRoamProfile = &pWextState->roamProfile;
14762
14763 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014764 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014765 return -EINVAL;
14766 }
14767
14768 /* enable selected protection checks in IBSS mode */
14769 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14770
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014771 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14773 pHddCtx->config->
14774 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014775 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014776 }
14777
14778 /* BSSID is provided by upper layers hence no need to AUTO generate */
14779 if (NULL != params->bssid) {
14780 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014781 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014782 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014783 return -EIO;
14784 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014785 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014786 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14787 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014788 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014789 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014790 return -EIO;
14791 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014792 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 }
14794 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14795 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14796 pRoamProfile->beaconInterval = params->beacon_interval;
14797 else {
14798 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014799 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014800 params->beacon_interval, pRoamProfile->beaconInterval);
14801 }
14802
14803 /* Set Channel */
14804 if (channelNum) {
14805 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014806 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014807 pRoamProfile->ChannelInfo.numOfChannels = 1;
14808 pHddStaCtx->conn_info.operationChannel = channelNum;
14809 pRoamProfile->ChannelInfo.ChannelList =
14810 &pHddStaCtx->conn_info.operationChannel;
14811 }
14812
14813 /* Initialize security parameters */
14814 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14815 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014816 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014817 return status;
14818 }
14819
14820 /* Issue connect start */
14821 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14822 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014823 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014824 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014825 operationChannel,
14826 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014827
14828 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014829 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 return status;
14831 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014832 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014833 return 0;
14834}
14835
14836/**
14837 * wlan_hdd_cfg80211_join_ibss() - join ibss
14838 * @wiphy: Pointer to wiphy
14839 * @dev: Pointer to network device
14840 * @param: Pointer to IBSS join parameters
14841 *
14842 * This function is used to create/join an IBSS network
14843 *
14844 * Return: 0 for success, non-zero for failure
14845 */
14846static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14847 struct net_device *dev,
14848 struct cfg80211_ibss_params *params)
14849{
14850 int ret = 0;
14851
14852 cds_ssr_protect(__func__);
14853 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14854 cds_ssr_unprotect(__func__);
14855
14856 return ret;
14857}
14858
14859/**
14860 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14861 * @wiphy: Pointer to wiphy
14862 * @dev: Pointer to network device
14863 *
14864 * This function is used to leave an IBSS network
14865 *
14866 * Return: 0 for success, non-zero for failure
14867 */
14868static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14869 struct net_device *dev)
14870{
14871 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14872 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14873 tCsrRoamProfile *pRoamProfile;
14874 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14875 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014876 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014877 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014878 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879
14880 ENTER();
14881
Anurag Chouhan6d760662016-02-20 16:05:43 +053014882 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014883 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014884 return -EINVAL;
14885 }
14886
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014887 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14888 hdd_err("invalid session id: %d", pAdapter->sessionId);
14889 return -EINVAL;
14890 }
14891
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014892 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014893 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14894 pAdapter->sessionId,
14895 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14896 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014897 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014898 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014899
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014900 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014901 hdd_device_mode_to_string(pAdapter->device_mode),
14902 pAdapter->device_mode);
14903 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014904 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014905 return -EIO;
14906 }
14907
14908 pRoamProfile = &pWextState->roamProfile;
14909
14910 /* Issue disconnect only if interface type is set to IBSS */
14911 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014912 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014913 return -EINVAL;
14914 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014915 /* Clearing add IE of beacon */
14916 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14917 sizeof(tSirMacAddr));
14918 updateIE.smeSessionId = pAdapter->sessionId;
14919 updateIE.ieBufferlength = 0;
14920 updateIE.pAdditionIEBuffer = NULL;
14921 updateIE.append = true;
14922 updateIE.notify = true;
14923 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14924 &updateIE,
14925 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014926 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014927 }
14928
14929 /* Reset WNI_CFG_PROBE_RSP Flags */
14930 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014931
14932 /* Issue Disconnect request */
14933 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14934 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14935 pAdapter->sessionId,
14936 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014937 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014938 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014939 hal_status);
14940 return -EAGAIN;
14941 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014942
14943 /* wait for mc thread to cleanup and then return to upper stack
14944 * so by the time upper layer calls the change interface, we are
14945 * all set to proceed further
14946 */
14947 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14948 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14949 if (!rc) {
14950 hdd_err("Failed to disconnect, timed out");
14951 return -ETIMEDOUT;
14952 }
14953
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014954 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014955 return 0;
14956}
14957
14958/**
14959 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14960 * @wiphy: Pointer to wiphy
14961 * @dev: Pointer to network device
14962 *
14963 * This function is used to leave an IBSS network
14964 *
14965 * Return: 0 for success, non-zero for failure
14966 */
14967static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14968 struct net_device *dev)
14969{
14970 int ret = 0;
14971
14972 cds_ssr_protect(__func__);
14973 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14974 cds_ssr_unprotect(__func__);
14975
14976 return ret;
14977}
14978
14979/**
14980 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14981 * @wiphy: Pointer to wiphy
14982 * @changed: Parameters changed
14983 *
14984 * This function is used to set the phy parameters. RTS Threshold/FRAG
14985 * Threshold/Retry Count etc.
14986 *
14987 * Return: 0 for success, non-zero for failure
14988 */
14989static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14990 u32 changed)
14991{
14992 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14993 tHalHandle hHal = pHddCtx->hHal;
14994 int status;
14995
14996 ENTER();
14997
Anurag Chouhan6d760662016-02-20 16:05:43 +053014998 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014999 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015000 return -EINVAL;
15001 }
15002
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015003 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015004 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15005 NO_SESSION, wiphy->rts_threshold));
15006 status = wlan_hdd_validate_context(pHddCtx);
15007
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015008 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015009 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015010
15011 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15012 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15013 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15014
15015 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15016 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015017 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015018 rts_threshold);
15019 return -EINVAL;
15020 }
15021
15022 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15023 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015024 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025 rts_threshold);
15026 return -EIO;
15027 }
15028
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015029 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 }
15031
15032 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15033 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15034 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15035 wiphy->frag_threshold;
15036
15037 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15038 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015039 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015040 frag_threshold);
15041 return -EINVAL;
15042 }
15043
15044 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15045 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015046 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015047 frag_threshold);
15048 return -EIO;
15049 }
15050
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015051 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 }
15053
15054 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15055 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15056 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15057 wiphy->retry_short : wiphy->retry_long;
15058
15059 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15060 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015061 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015062 return -EINVAL;
15063 }
15064
15065 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15066 if (0 != sme_cfg_set_int(hHal,
15067 WNI_CFG_LONG_RETRY_LIMIT,
15068 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015069 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 retry_value);
15071 return -EIO;
15072 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015073 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015074 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15075 if (0 != sme_cfg_set_int(hHal,
15076 WNI_CFG_SHORT_RETRY_LIMIT,
15077 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015078 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015079 retry_value);
15080 return -EIO;
15081 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015082 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015083 }
15084 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015085 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015086 return 0;
15087}
15088
15089/**
15090 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15091 * @wiphy: Pointer to wiphy
15092 * @changed: Parameters changed
15093 *
15094 * Return: 0 for success, non-zero for failure
15095 */
15096static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15097{
15098 int ret;
15099
15100 cds_ssr_protect(__func__);
15101 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15102 cds_ssr_unprotect(__func__);
15103
15104 return ret;
15105}
15106
15107/**
15108 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15109 * key
15110 * @wiphy: Pointer to wiphy
15111 * @dev: Pointer to network device
15112 * @key_index: Key index
15113 *
15114 * Return: 0
15115 */
15116static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15117 struct net_device *netdev,
15118 u8 key_index)
15119{
15120 ENTER();
15121 return 0;
15122}
15123
15124/**
15125 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15126 * wlan_hdd_set_default_mgmt_key
15127 * @wiphy: pointer to wiphy
15128 * @netdev: pointer to net_device structure
15129 * @key_index: key index
15130 *
15131 * Return: 0 on success, error number on failure
15132 */
15133static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15134 struct net_device *netdev,
15135 u8 key_index)
15136{
15137 int ret;
15138
15139 cds_ssr_protect(__func__);
15140 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15141 cds_ssr_unprotect(__func__);
15142
15143 return ret;
15144}
15145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015146/**
15147 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15148 * @wiphy: Pointer to wiphy
15149 * @dev: Pointer to network device
15150 * @params: Pointer to tx queue parameters
15151 *
15152 * Return: 0
15153 */
15154static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15155 struct net_device *dev,
15156 struct ieee80211_txq_params *params)
15157{
15158 ENTER();
15159 return 0;
15160}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015161
15162/**
15163 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15164 * @wiphy: pointer to wiphy
15165 * @netdev: pointer to net_device structure
15166 * @params: pointer to ieee80211_txq_params
15167 *
15168 * Return: 0 on success, error number on failure
15169 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015170static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15171 struct net_device *dev,
15172 struct ieee80211_txq_params *params)
15173{
15174 int ret;
15175
15176 cds_ssr_protect(__func__);
15177 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15178 cds_ssr_unprotect(__func__);
15179
15180 return ret;
15181}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015182
15183/**
15184 * __wlan_hdd_cfg80211_del_station() - delete station v2
15185 * @wiphy: Pointer to wiphy
15186 * @param: Pointer to delete station parameter
15187 *
15188 * Return: 0 for success, non-zero for failure
15189 */
15190static
15191int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15192 struct net_device *dev,
15193 struct tagCsrDelStaParams *pDelStaParams)
15194{
15195 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15196 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015197 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015198 hdd_hostapd_state_t *hapd_state;
15199 int status;
15200 uint8_t staId;
15201 uint8_t *mac;
15202
15203 ENTER();
15204
Anurag Chouhan6d760662016-02-20 16:05:43 +053015205 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015206 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015207 return -EINVAL;
15208 }
15209
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015210 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15211 hdd_err("invalid session id: %d", pAdapter->sessionId);
15212 return -EINVAL;
15213 }
15214
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015215 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015216 TRACE_CODE_HDD_CFG80211_DEL_STA,
15217 pAdapter->sessionId, pAdapter->device_mode));
15218
15219 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15220 status = wlan_hdd_validate_context(pHddCtx);
15221
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015222 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015224
15225 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15226
Krunal Sonib4326f22016-03-10 13:05:51 -080015227 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15228 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015229
15230 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15231 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015232 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233 return 0;
15234 }
15235
Anurag Chouhanc5548422016-02-24 18:33:27 +053015236 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015237 uint16_t i;
15238 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15239 if ((pAdapter->aStaInfo[i].isUsed) &&
15240 (!pAdapter->aStaInfo[i].
15241 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015242 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015243 mac,
15244 pAdapter->aStaInfo[i].
15245 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015246 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15248 hdd_ipa_wlan_evt(pAdapter,
15249 pAdapter->
15250 aStaInfo[i].
15251 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015252 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015253 mac);
15254 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015255 hdd_notice("Delete STA with MAC::"
15256 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015257 MAC_ADDR_ARRAY(mac));
15258
15259 if (pHddCtx->dev_dfs_cac_status ==
15260 DFS_CAC_IN_PROGRESS)
15261 goto fn_end;
15262
Wei Song2f76f642016-11-18 16:32:53 +080015263 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015265 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015266 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015267 hdd_softap_sta_deauth(pAdapter,
15268 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015269 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270 pAdapter->aStaInfo[i].
15271 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015272 qdf_status =
15273 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015274 &hapd_state->
15275 qdf_sta_disassoc_event,
15276 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015277 if (!QDF_IS_STATUS_SUCCESS(
15278 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015279 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015280 }
15281 }
15282 }
15283 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015284 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015285 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015286 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015287 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015288 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015289 hdd_notice("Skip DEL STA as this is not used::"
15290 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291 MAC_ADDR_ARRAY(mac));
15292 return -ENOENT;
15293 }
15294
15295 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15296 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015297 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298 }
15299
15300 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15301 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015302 hdd_notice("Skip DEL STA as deauth is in progress::"
15303 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 MAC_ADDR_ARRAY(mac));
15305 return -ENOENT;
15306 }
15307
15308 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15309
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015310 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311 MAC_ADDR_ARRAY(mac));
15312
15313 /* Case: SAP in ACS selected DFS ch and client connected
15314 * Now Radar detected. Then if random channel is another
15315 * DFS ch then new CAC is initiated and no TX allowed.
15316 * So do not send any mgmt frames as it will timeout
15317 * during CAC.
15318 */
15319
15320 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15321 goto fn_end;
15322
Wei Song2f76f642016-11-18 16:32:53 +080015323 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015324 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15325 (pAdapter), pAdapter->sessionId,
15326 (uint8_t *)&pDelStaParams->peerMacAddr,
15327 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015328 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015330 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015331 pAdapter->aStaInfo[staId].isDeauthInProgress =
15332 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015333 hdd_notice("STA removal failed for ::"
15334 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015335 MAC_ADDR_ARRAY(mac));
15336 return -ENOENT;
15337 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015338 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015339 &hapd_state->
15340 qdf_sta_disassoc_event,
15341 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015342 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015343 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015344 }
15345 }
15346 }
15347
15348fn_end:
15349 EXIT();
15350 return 0;
15351}
15352
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015353#if defined(USE_CFG80211_DEL_STA_V2)
15354/**
15355 * wlan_hdd_del_station() - delete station wrapper
15356 * @adapter: pointer to the hdd adapter
15357 *
15358 * Return: None
15359 */
15360void wlan_hdd_del_station(hdd_adapter_t *adapter)
15361{
15362 struct station_del_parameters del_sta;
15363 del_sta.mac = NULL;
15364 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15365 del_sta.reason_code = eCsrForcedDeauthSta;
15366
15367 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15368 &del_sta);
15369}
15370#else
15371void wlan_hdd_del_station(hdd_adapter_t *adapter)
15372{
15373 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15374}
15375#endif
15376
15377#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015378/**
15379 * wlan_hdd_cfg80211_del_station() - delete station v2
15380 * @wiphy: Pointer to wiphy
15381 * @param: Pointer to delete station parameter
15382 *
15383 * Return: 0 for success, non-zero for failure
15384 */
15385int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15386 struct net_device *dev,
15387 struct station_del_parameters *param)
15388#else
15389/**
15390 * wlan_hdd_cfg80211_del_station() - delete station
15391 * @wiphy: Pointer to wiphy
15392 * @mac: Pointer to station mac address
15393 *
15394 * Return: 0 for success, non-zero for failure
15395 */
15396#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15397int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15398 struct net_device *dev,
15399 const uint8_t *mac)
15400#else
15401int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15402 struct net_device *dev,
15403 uint8_t *mac)
15404#endif
15405#endif
15406{
15407 int ret;
15408 struct tagCsrDelStaParams delStaParams;
15409
15410 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015411#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015412 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015413 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015414 return -EINVAL;
15415 }
15416 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15417 param->subtype, &delStaParams);
15418#else
15419 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15420 (SIR_MAC_MGMT_DEAUTH >> 4),
15421 &delStaParams);
15422#endif
15423 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15424 cds_ssr_unprotect(__func__);
15425
15426 return ret;
15427}
15428
15429/**
15430 * __wlan_hdd_cfg80211_add_station() - add station
15431 * @wiphy: Pointer to wiphy
15432 * @mac: Pointer to station mac address
15433 * @pmksa: Pointer to add station parameter
15434 *
15435 * Return: 0 for success, non-zero for failure
15436 */
15437static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15438 struct net_device *dev,
15439 const uint8_t *mac,
15440 struct station_parameters *params)
15441{
15442 int status = -EPERM;
15443#ifdef FEATURE_WLAN_TDLS
15444 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15445 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15446 u32 mask, set;
15447
15448 ENTER();
15449
Anurag Chouhan6d760662016-02-20 16:05:43 +053015450 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015451 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015452 return -EINVAL;
15453 }
15454
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015455 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15456 hdd_err("invalid session id: %d", pAdapter->sessionId);
15457 return -EINVAL;
15458 }
15459
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015460 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015461 TRACE_CODE_HDD_CFG80211_ADD_STA,
15462 pAdapter->sessionId, params->listen_interval));
15463
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015464 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015465 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015466
15467 mask = params->sta_flags_mask;
15468
15469 set = params->sta_flags_set;
15470
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015471 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015472 MAC_ADDR_ARRAY(mac));
15473
15474 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15475 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15476 status =
15477 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15478 }
15479 }
15480#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015481 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015482 return status;
15483}
15484
15485/**
15486 * wlan_hdd_cfg80211_add_station() - add station
15487 * @wiphy: Pointer to wiphy
15488 * @mac: Pointer to station mac address
15489 * @pmksa: Pointer to add station parameter
15490 *
15491 * Return: 0 for success, non-zero for failure
15492 */
15493#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15494static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15495 struct net_device *dev,
15496 const uint8_t *mac,
15497 struct station_parameters *params)
15498#else
15499static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15500 struct net_device *dev, uint8_t *mac,
15501 struct station_parameters *params)
15502#endif
15503{
15504 int ret;
15505
15506 cds_ssr_protect(__func__);
15507 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15508 cds_ssr_unprotect(__func__);
15509
15510 return ret;
15511}
15512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015513/**
15514 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15515 * @wiphy: Pointer to wiphy
15516 * @dev: Pointer to network device
15517 * @pmksa: Pointer to set pmksa parameter
15518 *
15519 * Return: 0 for success, non-zero for failure
15520 */
15521static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15522 struct net_device *dev,
15523 struct cfg80211_pmksa *pmksa)
15524{
15525 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15526 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15527 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015528 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015529 int status;
15530 tPmkidCacheInfo pmk_id;
15531
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015532 ENTER();
15533
Anurag Chouhan6d760662016-02-20 16:05:43 +053015534 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015535 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015536 return -EINVAL;
15537 }
15538
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015539 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15540 hdd_err("invalid session id: %d", pAdapter->sessionId);
15541 return -EINVAL;
15542 }
15543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015544 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015545 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015546 return -EINVAL;
15547 }
15548
15549 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015550 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015551 pmksa->bssid, pmksa->pmkid);
15552 return -EINVAL;
15553 }
15554
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015555 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015556 MAC_ADDR_ARRAY(pmksa->bssid));
15557
15558 status = wlan_hdd_validate_context(pHddCtx);
15559
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015560 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015561 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562
15563 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15564
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015565 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15566 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015567
15568 /* Add to the PMKSA ID Cache in CSR */
15569 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15570 &pmk_id, 1, false);
15571
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015572 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015573 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15574 pAdapter->sessionId, result));
15575
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015576 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015577 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015578}
15579
15580/**
15581 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15582 * @wiphy: Pointer to wiphy
15583 * @dev: Pointer to network device
15584 * @pmksa: Pointer to set pmksa parameter
15585 *
15586 * Return: 0 for success, non-zero for failure
15587 */
15588static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15589 struct net_device *dev,
15590 struct cfg80211_pmksa *pmksa)
15591{
15592 int ret;
15593
15594 cds_ssr_protect(__func__);
15595 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15596 cds_ssr_unprotect(__func__);
15597
15598 return ret;
15599}
15600
15601/**
15602 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15603 * @wiphy: Pointer to wiphy
15604 * @dev: Pointer to network device
15605 * @pmksa: Pointer to pmksa parameter
15606 *
15607 * Return: 0 for success, non-zero for failure
15608 */
15609static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15610 struct net_device *dev,
15611 struct cfg80211_pmksa *pmksa)
15612{
15613 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15614 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15615 tHalHandle halHandle;
15616 int status = 0;
15617
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015618 ENTER();
15619
Anurag Chouhan6d760662016-02-20 16:05:43 +053015620 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015621 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015622 return -EINVAL;
15623 }
15624
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015625 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15626 hdd_err("invalid session id: %d", pAdapter->sessionId);
15627 return -EINVAL;
15628 }
15629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015630 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015631 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015632 return -EINVAL;
15633 }
15634
15635 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015636 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015637 return -EINVAL;
15638 }
15639
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015640 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015641 MAC_ADDR_ARRAY(pmksa->bssid));
15642
15643 status = wlan_hdd_validate_context(pHddCtx);
15644
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015645 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015646 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015647
15648 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15649
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015650 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015651 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15652 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015653 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015654 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015655 sme_roam_del_pmkid_from_cache(halHandle,
15656 pAdapter->sessionId, pmksa->bssid,
15657 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015658 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659 MAC_ADDR_ARRAY(pmksa->bssid));
15660 status = -EINVAL;
15661 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015662 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015663 return status;
15664}
15665
15666/**
15667 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15668 * @wiphy: Pointer to wiphy
15669 * @dev: Pointer to network device
15670 * @pmksa: Pointer to pmksa parameter
15671 *
15672 * Return: 0 for success, non-zero for failure
15673 */
15674static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15675 struct net_device *dev,
15676 struct cfg80211_pmksa *pmksa)
15677{
15678 int ret;
15679
15680 cds_ssr_protect(__func__);
15681 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15682 cds_ssr_unprotect(__func__);
15683
15684 return ret;
15685
15686}
15687
15688/**
15689 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15690 * @wiphy: Pointer to wiphy
15691 * @dev: Pointer to network device
15692 *
15693 * Return: 0 for success, non-zero for failure
15694 */
15695static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15696 struct net_device *dev)
15697{
15698 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15699 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15700 tHalHandle halHandle;
15701 int status = 0;
15702
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015703 ENTER();
15704
Anurag Chouhan6d760662016-02-20 16:05:43 +053015705 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015706 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015707 return -EINVAL;
15708 }
15709
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015710 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15711 hdd_err("invalid session id: %d", pAdapter->sessionId);
15712 return -EINVAL;
15713 }
15714
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015715 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015716
15717 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15718 status = wlan_hdd_validate_context(pHddCtx);
15719
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015720 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015721 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015722
15723 /* Retrieve halHandle */
15724 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15725
15726 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015727 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15729 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015730 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015731 status = -EINVAL;
15732 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015733 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734 return status;
15735}
15736
15737/**
15738 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15739 * @wiphy: Pointer to wiphy
15740 * @dev: Pointer to network device
15741 *
15742 * Return: 0 for success, non-zero for failure
15743 */
15744static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15745 struct net_device *dev)
15746{
15747 int ret;
15748
15749 cds_ssr_protect(__func__);
15750 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15751 cds_ssr_unprotect(__func__);
15752
15753 return ret;
15754}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015755
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015756#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757/**
15758 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15759 * @wiphy: Pointer to wiphy
15760 * @dev: Pointer to network device
15761 * @ftie: Pointer to fast transition ie parameter
15762 *
15763 * Return: 0 for success, non-zero for failure
15764 */
15765static int
15766__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15767 struct net_device *dev,
15768 struct cfg80211_update_ft_ies_params *ftie)
15769{
15770 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15771 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15772 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15773 int status;
15774
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015775 ENTER();
15776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015777 status = wlan_hdd_validate_context(hdd_ctx);
15778 if (status)
15779 return status;
15780
Anurag Chouhan6d760662016-02-20 16:05:43 +053015781 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015782 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015783 return -EINVAL;
15784 }
15785
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015786 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15787 hdd_err("invalid session id: %d", pAdapter->sessionId);
15788 return -EINVAL;
15789 }
15790
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015791 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015792 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15793 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15794 /* Added for debug on reception of Re-assoc Req. */
15795 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015796 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015797 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015798 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015799 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015800 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015801 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015802
15803 /* Pass the received FT IEs to SME */
15804 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15805 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015806 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015807 return 0;
15808}
15809
15810/**
15811 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15812 * @wiphy: Pointer to wiphy
15813 * @dev: Pointer to network device
15814 * @ftie: Pointer to fast transition ie parameter
15815 *
15816 * Return: 0 for success, non-zero for failure
15817 */
15818static int
15819wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15820 struct net_device *dev,
15821 struct cfg80211_update_ft_ies_params *ftie)
15822{
15823 int ret;
15824
15825 cds_ssr_protect(__func__);
15826 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15827 cds_ssr_unprotect(__func__);
15828
15829 return ret;
15830}
15831#endif
15832
Mukul Sharma3d36c392017-01-18 18:39:12 +053015833void wlan_hdd_cfg80211_update_replay_counter_callback(
15834 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15835
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015837 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15838 uint8_t temp_replay_counter[8];
15839 int i;
15840 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015841
15842 ENTER();
15843
Mukul Sharma3d36c392017-01-18 18:39:12 +053015844 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015845 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015846 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015847 }
15848
Mukul Sharma3d36c392017-01-18 18:39:12 +053015849 if (!gtk_rsp_param) {
15850 hdd_err("gtk_rsp_param is Null");
15851 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015852 }
15853
Mukul Sharma3d36c392017-01-18 18:39:12 +053015854 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015855 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015856 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015857 }
15858
Mukul Sharma3d36c392017-01-18 18:39:12 +053015859 hdd_notice("updated replay counter: %llu from fwr",
15860 gtk_rsp_param->replay_counter);
15861 /* convert little to big endian since supplicant works on big endian */
15862 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15863 for (i = 0; i < 8; i++)
15864 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015865
Mukul Sharma3d36c392017-01-18 18:39:12 +053015866 hdd_notice("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015867 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015868 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015869 gtk_rsp_param->bssid.bytes,
15870 temp_replay_counter, GFP_KERNEL);
15871out:
15872 EXIT();
15873
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015874}
15875
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015876static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015877int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015878 struct net_device *dev,
15879 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015880{
15881 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015882 int result, i;
15883 struct pmo_gtk_req *gtk_req = NULL;
15884 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15885 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015886 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887
15888 ENTER();
15889
Anurag Chouhan6d760662016-02-20 16:05:43 +053015890 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015891 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015892 result = -EINVAL;
15893 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894 }
15895
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015896 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15897 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015898 result = -EINVAL;
15899 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015900 }
15901
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015902 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015903 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15904 pAdapter->sessionId, pAdapter->device_mode));
15905
Mukul Sharma3d36c392017-01-18 18:39:12 +053015906 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015907 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015908 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015909
Mukul Sharma3d36c392017-01-18 18:39:12 +053015910 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15911 if (!gtk_req) {
15912 hdd_err("cannot allocate gtk_req");
15913 result = -ENOMEM;
15914 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015915 }
15916
Mukul Sharma3d36c392017-01-18 18:39:12 +053015917 /* convert big to little endian since driver work on little endian */
15918 buf = (uint8_t *)&gtk_req->replay_counter;
15919 for (i = 0; i < 8; i++)
15920 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015921
Mukul Sharma3d36c392017-01-18 18:39:12 +053015922 hdd_notice("current replay counter: %llu in user space",
15923 gtk_req->replay_counter);
15924 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15925 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15926 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15927 if (status != QDF_STATUS_SUCCESS) {
15928 hdd_err("Failed to cache GTK Offload");
15929 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015930 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015931out:
15932 if (gtk_req)
15933 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015934 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015936 return result;
15937}
15938
15939/**
15940 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15941 * @wiphy: Pointer to wiphy
15942 * @dev: Pointer to network device
15943 * @data: Pointer to rekey data
15944 *
15945 * This function is used to offload GTK rekeying job to the firmware.
15946 *
15947 * Return: 0 for success, non-zero for failure
15948 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015949static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015950int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15951 struct net_device *dev,
15952 struct cfg80211_gtk_rekey_data *data)
15953{
15954 int ret;
15955
15956 cds_ssr_protect(__func__);
15957 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15958 cds_ssr_unprotect(__func__);
15959
15960 return ret;
15961}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015962
15963/**
15964 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15965 * @wiphy: Pointer to wiphy
15966 * @dev: Pointer to network device
15967 * @param: Pointer to access control parameter
15968 *
15969 * Return: 0 for success, non-zero for failure
15970 */
15971static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15972 struct net_device *dev,
15973 const struct cfg80211_acl_data *params)
15974{
15975 int i;
15976 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15977 hdd_hostapd_state_t *pHostapdState;
15978 tsap_Config_t *pConfig;
15979 v_CONTEXT_t p_cds_context = NULL;
15980 hdd_context_t *pHddCtx;
15981 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015982 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015983
15984 ENTER();
15985
Anurag Chouhan6d760662016-02-20 16:05:43 +053015986 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015987 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015988 return -EINVAL;
15989 }
15990
15991 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015992 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015993 return -EINVAL;
15994 }
15995
15996 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15997 status = wlan_hdd_validate_context(pHddCtx);
15998
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015999 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016001
16002 p_cds_context = pHddCtx->pcds_context;
16003 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16004
16005 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016006 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016007 return -EINVAL;
16008 }
16009
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016010 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016011 params->n_acl_entries);
16012
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016013 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016014 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16015 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016016 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16018
16019 /* default value */
16020 pConfig->num_accept_mac = 0;
16021 pConfig->num_deny_mac = 0;
16022
16023 /**
16024 * access control policy
16025 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16026 * listed in hostapd.deny file.
16027 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16028 * listed in hostapd.accept file.
16029 */
16030 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16031 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16032 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16033 params->acl_policy) {
16034 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16035 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016036 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016037 params->acl_policy);
16038 return -ENOTSUPP;
16039 }
16040
16041 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16042 pConfig->num_accept_mac = params->n_acl_entries;
16043 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016044 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
16045 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016046 MAC_ADDR_ARRAY(
16047 params->mac_addrs[i].addr));
16048
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016049 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 params->mac_addrs[i].addr,
16051 sizeof(qcmacaddr));
16052 }
16053 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16054 pConfig->num_deny_mac = params->n_acl_entries;
16055 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016056 hdd_notice("** Add ACL MAC entry %i in BlackList :"
16057 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016058 MAC_ADDR_ARRAY(
16059 params->mac_addrs[i].addr));
16060
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016061 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016062 params->mac_addrs[i].addr,
16063 sizeof(qcmacaddr));
16064 }
16065 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016066 qdf_status = wlansap_set_mac_acl(
16067 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016068 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016069 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016070 return -EINVAL;
16071 }
16072 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016073 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016074 hdd_device_mode_to_string(pAdapter->device_mode),
16075 pAdapter->device_mode);
16076 return -EINVAL;
16077 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016078 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016079 return 0;
16080}
16081
16082/**
16083 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16084 * __wlan_hdd_cfg80211_set_mac_acl
16085 * @wiphy: pointer to wiphy structure
16086 * @dev: pointer to net_device
16087 * @params: pointer to cfg80211_acl_data
16088 *
16089 * Return; 0 on success, error number otherwise
16090 */
16091static int
16092wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16093 struct net_device *dev,
16094 const struct cfg80211_acl_data *params)
16095{
16096 int ret;
16097
16098 cds_ssr_protect(__func__);
16099 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16100 cds_ssr_unprotect(__func__);
16101
16102 return ret;
16103}
16104
16105#ifdef WLAN_NL80211_TESTMODE
16106#ifdef FEATURE_WLAN_LPHB
16107/**
16108 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16109 * @pHddCtx: Pointer to hdd context
16110 * @lphbInd: Pointer to low power heart beat indication parameter
16111 *
16112 * Return: none
16113 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016114static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
16115 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016116{
16117 struct sk_buff *skb;
16118
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016119 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016120
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016121 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016122 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016123
16124 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016125 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016126 return;
16127 }
16128
16129 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
16130 wiphy, sizeof(tSirLPHBInd),
16131 GFP_ATOMIC);
16132 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016133 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016134 return;
16135 }
16136
16137 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016138 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016139 goto nla_put_failure;
16140 }
16141 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016142 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143 goto nla_put_failure;
16144 }
16145 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016146 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016147 goto nla_put_failure;
16148 }
16149 cfg80211_testmode_event(skb, GFP_ATOMIC);
16150 return;
16151
16152nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016153 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016154 kfree_skb(skb);
16155
16156 return;
16157}
16158#endif /* FEATURE_WLAN_LPHB */
16159
16160/**
16161 * __wlan_hdd_cfg80211_testmode() - test mode
16162 * @wiphy: Pointer to wiphy
16163 * @data: Data pointer
16164 * @len: Data length
16165 *
16166 * Return: 0 for success, non-zero for failure
16167 */
16168static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16169 void *data, int len)
16170{
16171 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16172 int err;
16173 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16174
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016175 ENTER();
16176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016177 err = wlan_hdd_validate_context(pHddCtx);
16178 if (err)
16179 return err;
16180
16181 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16182 len, wlan_hdd_tm_policy);
16183 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016184 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016185 return err;
16186 }
16187
16188 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016189 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016190 return -EINVAL;
16191 }
16192
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016193 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016194 TRACE_CODE_HDD_CFG80211_TESTMODE,
16195 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016196 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16197#ifdef FEATURE_WLAN_LPHB
16198 /* Low Power Heartbeat configuration request */
16199 case WLAN_HDD_TM_CMD_WLAN_HB:
16200 {
16201 int buf_len;
16202 void *buf;
16203 tSirLPHBReq *hb_params = NULL;
16204 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016205 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016206
16207 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016208 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016209 return -EINVAL;
16210 }
16211
16212 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16213 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16214
16215 hb_params_temp = (tSirLPHBReq *) buf;
16216 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16217 && (hb_params_temp->params.lphbTcpParamReq.
16218 timePeriodSec == 0))
16219 return -EINVAL;
16220
16221 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016222 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016224 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016225 return -ENOMEM;
16226 }
16227
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016228 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016229 smeStatus =
16230 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16231 hb_params,
16232 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016233 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016234 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016235 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236 }
16237 return 0;
16238 }
16239#endif /* FEATURE_WLAN_LPHB */
16240
16241#if defined(QCA_WIFI_FTM)
16242 case WLAN_HDD_TM_CMD_WLAN_FTM:
16243 {
16244 int buf_len;
16245 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016246 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016247 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016248 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 return -EINVAL;
16250 }
16251
16252 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16253 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16254
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016255 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016256
16257 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16258
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016259 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016260 err = -EBUSY;
16261 break;
16262 }
16263#endif
16264
16265 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016266 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016267 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16268 return -EOPNOTSUPP;
16269 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016270 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016271 return err;
16272}
16273
16274/**
16275 * wlan_hdd_cfg80211_testmode() - test mode
16276 * @wiphy: Pointer to wiphy
16277 * @dev: Pointer to network device
16278 * @data: Data pointer
16279 * @len: Data length
16280 *
16281 * Return: 0 for success, non-zero for failure
16282 */
16283static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16284#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16285 struct wireless_dev *wdev,
16286#endif
16287 void *data, int len)
16288{
16289 int ret;
16290
16291 cds_ssr_protect(__func__);
16292 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16293 cds_ssr_unprotect(__func__);
16294
16295 return ret;
16296}
16297
16298#if defined(QCA_WIFI_FTM)
16299/**
16300 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16301 * @buf: Pointer to buffer
16302 * @buf_len: Buffer length
16303 *
16304 * Return: none
16305 */
16306void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16307{
16308 struct sk_buff *skb;
16309 hdd_context_t *hdd_ctx;
16310
16311 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016312 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016313 return;
16314 }
16315
Anurag Chouhan6d760662016-02-20 16:05:43 +053016316 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016317 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016318 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016319 return;
16320 }
16321
16322 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16323 buf_len, GFP_KERNEL);
16324 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016325 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016326 return;
16327 }
16328
16329 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16330 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16331 goto nla_put_failure;
16332
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016333 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016334
16335 cfg80211_testmode_event(skb, GFP_KERNEL);
16336 return;
16337
16338nla_put_failure:
16339 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016340 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016341}
16342#endif
16343#endif /* CONFIG_NL80211_TESTMODE */
16344
16345#ifdef QCA_HT_2040_COEX
16346/**
16347 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16348 * @wiphy: Pointer to wiphy
16349 * @dev: Pointer to network device
16350 * @chandef: Pointer to channel definition parameter
16351 *
16352 * Return: 0 for success, non-zero for failure
16353 */
16354static int
16355__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16356 struct net_device *dev,
16357 struct cfg80211_chan_def *chandef)
16358{
16359 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16360 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016361 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016362 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016363 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016364
Anurag Chouhan6d760662016-02-20 16:05:43 +053016365 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016366 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016367 return -EINVAL;
16368 }
16369
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016370 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16371 hdd_err("invalid session id: %d", pAdapter->sessionId);
16372 return -EINVAL;
16373 }
16374
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016375 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16376 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016377 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016378 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016379
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016380 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016381 sme_get_config_param(pHddCtx->hHal, &sme_config);
16382 switch (chandef->width) {
16383 case NL80211_CHAN_WIDTH_20:
16384 if (sme_config.csrConfig.channelBondingMode24GHz !=
16385 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16386 sme_config.csrConfig.channelBondingMode24GHz =
16387 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16388 sme_update_config(pHddCtx->hHal, &sme_config);
16389 cbModeChange = true;
16390 }
16391 break;
16392
16393 case NL80211_CHAN_WIDTH_40:
16394 if (sme_config.csrConfig.channelBondingMode24GHz ==
16395 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16396 if (NL80211_CHAN_HT40MINUS ==
16397 cfg80211_get_chandef_type(chandef))
16398 sme_config.csrConfig.channelBondingMode24GHz =
16399 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16400 else
16401 sme_config.csrConfig.channelBondingMode24GHz =
16402 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16403 sme_update_config(pHddCtx->hHal, &sme_config);
16404 cbModeChange = true;
16405 }
16406 break;
16407
16408 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016409 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016410 return -EINVAL;
16411 }
16412
16413 if (!cbModeChange)
16414 return 0;
16415
Krunal Sonib4326f22016-03-10 13:05:51 -080016416 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016417 return 0;
16418
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016419 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016420 sme_config.csrConfig.channelBondingMode24GHz);
16421
16422 /* Change SAP ht2040 mode */
16423 status = hdd_set_sap_ht2040_mode(pAdapter,
16424 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016425 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016426 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016427 return -EINVAL;
16428 }
16429
16430 return 0;
16431}
16432
16433/**
16434 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16435 * @wiphy: Pointer to wiphy
16436 * @dev: Pointer to network device
16437 * @chandef: Pointer to channel definition parameter
16438 *
16439 * Return: 0 for success, non-zero for failure
16440 */
16441static int
16442wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16443 struct net_device *dev,
16444 struct cfg80211_chan_def *chandef)
16445{
16446 int ret;
16447
16448 cds_ssr_protect(__func__);
16449 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16450 cds_ssr_unprotect(__func__);
16451
16452 return ret;
16453}
16454#endif
16455
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016456#ifdef CHANNEL_SWITCH_SUPPORTED
16457/**
16458 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16459 * channel in SAP/GO
16460 * @wiphy: wiphy pointer
16461 * @dev: dev pointer.
16462 * @csa_params: Change channel params
16463 *
16464 * This function is called to switch channel in SAP/GO
16465 *
16466 * Return: 0 if success else return non zero
16467 */
16468static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16469 struct net_device *dev,
16470 struct cfg80211_csa_settings *csa_params)
16471{
16472 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16473 hdd_context_t *hdd_ctx;
16474 uint8_t channel;
16475 uint16_t freq;
16476 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016477 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016478
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016479 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016480 csa_params->chandef.chan->center_freq);
16481
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016482 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16483 hdd_err("invalid session id: %d", adapter->sessionId);
16484 return -EINVAL;
16485 }
16486
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016487 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16488 ret = wlan_hdd_validate_context(hdd_ctx);
16489
16490 if (0 != ret)
16491 return ret;
16492
Krunal Sonib4326f22016-03-10 13:05:51 -080016493 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16494 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016495 return -ENOTSUPP;
16496
16497 freq = csa_params->chandef.chan->center_freq;
16498 channel = cds_freq_to_chan(freq);
16499
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016500 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16501
16502 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016503 return ret;
16504}
16505
16506/**
16507 * wlan_hdd_cfg80211_channel_switch()- function to switch
16508 * channel in SAP/GO
16509 * @wiphy: wiphy pointer
16510 * @dev: dev pointer.
16511 * @csa_params: Change channel params
16512 *
16513 * This function is called to switch channel in SAP/GO
16514 *
16515 * Return: 0 if success else return non zero
16516 */
16517static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16518 struct net_device *dev,
16519 struct cfg80211_csa_settings *csa_params)
16520{
16521 int ret;
16522
16523 cds_ssr_protect(__func__);
16524 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16525 cds_ssr_unprotect(__func__);
16526 return ret;
16527}
16528#endif
16529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016530/**
16531 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16532 * translation from NL to policy manager type
16533 * @type: Generic connection mode type defined in NL
16534 *
16535 *
16536 * This function provides the type translation
16537 *
16538 * Return: cds_con_mode enum
16539 */
16540enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16541 enum nl80211_iftype type)
16542{
16543 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16544 switch (type) {
16545 case NL80211_IFTYPE_STATION:
16546 mode = CDS_STA_MODE;
16547 break;
16548 case NL80211_IFTYPE_P2P_CLIENT:
16549 mode = CDS_P2P_CLIENT_MODE;
16550 break;
16551 case NL80211_IFTYPE_P2P_GO:
16552 mode = CDS_P2P_GO_MODE;
16553 break;
16554 case NL80211_IFTYPE_AP:
16555 mode = CDS_SAP_MODE;
16556 break;
16557 case NL80211_IFTYPE_ADHOC:
16558 mode = CDS_IBSS_MODE;
16559 break;
16560 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016561 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016562 type);
16563 }
16564 return mode;
16565}
16566
16567/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016568 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16569 * @wiphy: Handle to struct wiphy to get handle to module context.
16570 * @chandef: Contains information about the capture channel to be set.
16571 *
16572 * This interface is called if and only if monitor mode interface alone is
16573 * active.
16574 *
16575 * Return: 0 success or error code on failure.
16576 */
16577static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16578 struct cfg80211_chan_def *chandef)
16579{
16580 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16581 hdd_adapter_t *adapter;
16582 hdd_station_ctx_t *sta_ctx;
16583 struct hdd_mon_set_ch_info *ch_info;
16584 QDF_STATUS status;
16585 tHalHandle hal_hdl;
16586 struct qdf_mac_addr bssid;
16587 tCsrRoamProfile roam_profile;
16588 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016589 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016590 int ret;
16591 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16592
16593 ENTER();
16594
16595 ret = wlan_hdd_validate_context(hdd_ctx);
16596 if (ret)
16597 return ret;
16598
16599 hal_hdl = hdd_ctx->hHal;
16600
16601 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16602 if (!adapter)
16603 return -EIO;
16604
16605 hdd_info("%s: set monitor mode Channel %d and freq %d",
16606 adapter->dev->name, chan_num, chandef->chan->center_freq);
16607
16608 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16609 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016610 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16611 roam_profile.ChannelInfo.numOfChannels = 1;
16612 roam_profile.phyMode = ch_info->phy_mode;
16613 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016614 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016615
16616 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16617 QDF_MAC_ADDR_SIZE);
16618
16619 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016620 /*
16621 * CDS api expects secondary channel for calculating
16622 * the channel params
16623 */
16624 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16625 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16626 if (chan_num >= 1 && chan_num <= 5)
16627 sec_ch = chan_num + 4;
16628 else if (chan_num >= 6 && chan_num <= 13)
16629 sec_ch = chan_num - 4;
16630 }
16631 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016632 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16633 &roam_profile);
16634 if (status) {
16635 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16636 status);
16637 ret = qdf_status_to_os_return(status);
16638 return ret;
16639 }
16640 EXIT();
16641 return 0;
16642}
16643
16644/**
16645 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16646 * @wiphy: Handle to struct wiphy to get handle to module context.
16647 * @chandef: Contains information about the capture channel to be set.
16648 *
16649 * This interface is called if and only if monitor mode interface alone is
16650 * active.
16651 *
16652 * Return: 0 success or error code on failure.
16653 */
16654static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16655 struct cfg80211_chan_def *chandef)
16656{
16657 int ret;
16658
16659 cds_ssr_protect(__func__);
16660 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16661 cds_ssr_unprotect(__func__);
16662 return ret;
16663}
16664
16665/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016666 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16667 * @adapter: pointer to adapter
16668 *
16669 * Wrapper function to clear link layer stats.
16670 * return - void
16671 */
16672void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16673{
16674 tSirLLStatsClearReq link_layer_stats_clear_req;
16675 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16676
Mukul Sharma491021c2016-09-29 21:39:19 +053016677 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16678 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016679 link_layer_stats_clear_req.stopReq = 0;
16680 link_layer_stats_clear_req.reqId = 1;
16681 link_layer_stats_clear_req.staId = adapter->sessionId;
16682 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16683
16684 return;
16685}
16686
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016687/**
16688 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16689 * @adapter: HDD Adapter
16690 *
16691 * If roaming is in progress and there is a request to
16692 * disconnect the session, then it is deferred. Once
16693 * roaming is complete/aborted, then this routine is
16694 * used to resume the disconnect that was deferred
16695 *
16696 * Return: None
16697 */
16698void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16699{
16700 switch (adapter->defer_disconnect) {
16701 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16702 adapter->defer_disconnect = 0;
16703 wlan_hdd_disconnect(adapter,
16704 adapter->cfg80211_disconnect_reason);
16705 break;
16706 case DEFER_DISCONNECT_TRY_DISCONNECT:
16707 wlan_hdd_try_disconnect(adapter);
16708 adapter->defer_disconnect = 0;
16709 break;
16710 default:
16711 hdd_info("Invalid source to defer:%d. Hence not handling it",
16712 adapter->defer_disconnect);
16713 break;
16714 }
16715}
16716
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016717#define CNT_DIFF(cur, prev) \
16718 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16719#define MAX_COUNT 0xffffffff
16720static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16721 struct scan_chan_info *chan,
16722 struct scan_chan_info *info, uint32_t cmd_flag)
16723{
16724 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16725 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16726 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16727
16728 mutex_lock(&hdd_ctx->chan_info_lock);
16729
16730 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16731 qdf_mem_zero(chan, sizeof(*chan));
16732
16733 chan->freq = info->freq;
16734 chan->noise_floor = info->noise_floor;
16735 chan->clock_freq = info->clock_freq;
16736 chan->cmd_flag = info->cmd_flag;
16737 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16738
16739 chan->rx_clear_count =
16740 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16741
16742 chan->tx_frame_count =
16743 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16744
16745 mutex_unlock(&hdd_ctx->chan_info_lock);
16746
16747}
16748#undef CNT_DIFF
16749#undef MAX_COUNT
16750
16751/**
16752 * wlan_hdd_chan_info_cb() - channel info callback
16753 * @chan_info: struct scan_chan_info
16754 *
16755 * Store channel info into HDD context
16756 *
16757 * Return: None.
16758 */
16759static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16760{
16761 hdd_context_t *hdd_ctx;
16762 struct scan_chan_info *chan;
16763 uint8_t idx;
16764
16765 ENTER();
16766
16767 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16768 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16769 hdd_err("hdd_ctx is invalid");
16770 return;
16771 }
16772
16773 if (!hdd_ctx->chan_info) {
16774 hdd_err("chan_info is NULL");
16775 return;
16776 }
16777
16778 chan = hdd_ctx->chan_info;
16779 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16780 if (chan[idx].freq == info->freq) {
16781 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16782 info->cmd_flag);
16783 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16784 chan[idx].cmd_flag, chan[idx].freq,
16785 chan[idx].noise_floor,
16786 chan[idx].cycle_count, chan[idx].rx_clear_count,
16787 chan[idx].clock_freq, chan[idx].cmd_flag,
16788 chan[idx].tx_frame_count, idx);
16789 if (chan[idx].freq == 0)
16790 break;
16791
16792 }
16793 }
16794
16795 EXIT();
16796}
16797
16798/**
16799 * wlan_hdd_init_chan_info() - init chan info in hdd context
16800 * @hdd_ctx: HDD context pointer
16801 *
16802 * Return: none
16803 */
16804void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16805{
16806 uint8_t num_2g, num_5g, index = 0;
16807
16808 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16809 hdd_info("SNR monitoring is disabled");
16810 return;
16811 }
16812
16813 hdd_ctx->chan_info =
16814 qdf_mem_malloc(sizeof(struct scan_chan_info)
16815 * QDF_MAX_NUM_CHAN);
16816 if (hdd_ctx->chan_info == NULL) {
16817 hdd_err("Failed to malloc for chan info");
16818 return;
16819 }
16820 mutex_init(&hdd_ctx->chan_info_lock);
16821
16822 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16823 for (; index < num_2g; index++) {
16824 hdd_ctx->chan_info[index].freq =
16825 hdd_channels_2_4_ghz[index].center_freq;
16826 }
16827
16828 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16829 for (; (index - num_2g) < num_5g; index++) {
16830 if (cds_is_dsrc_channel(
16831 hdd_channels_5_ghz[index - num_2g].center_freq))
16832 continue;
16833 hdd_ctx->chan_info[index].freq =
16834 hdd_channels_5_ghz[index - num_2g].center_freq;
16835 }
16836 sme_set_chan_info_callback(hdd_ctx->hHal,
16837 &wlan_hdd_chan_info_cb);
16838}
16839
16840/**
16841 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16842 * @hdd_ctx: hdd context pointer
16843 *
16844 * Return: none
16845 */
16846void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16847{
16848 struct scan_chan_info *chan;
16849
16850 chan = hdd_ctx->chan_info;
16851 hdd_ctx->chan_info = NULL;
16852 if (chan)
16853 qdf_mem_free(chan);
16854}
16855
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016856/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016857 * struct cfg80211_ops - cfg80211_ops
16858 *
16859 * @add_virtual_intf: Add virtual interface
16860 * @del_virtual_intf: Delete virtual interface
16861 * @change_virtual_intf: Change virtual interface
16862 * @change_station: Change station
16863 * @add_beacon: Add beacon in sap mode
16864 * @del_beacon: Delete beacon in sap mode
16865 * @set_beacon: Set beacon in sap mode
16866 * @start_ap: Start ap
16867 * @change_beacon: Change beacon
16868 * @stop_ap: Stop ap
16869 * @change_bss: Change bss
16870 * @add_key: Add key
16871 * @get_key: Get key
16872 * @del_key: Delete key
16873 * @set_default_key: Set default key
16874 * @set_channel: Set channel
16875 * @scan: Scan
16876 * @connect: Connect
16877 * @disconnect: Disconnect
16878 * @join_ibss = Join ibss
16879 * @leave_ibss = Leave ibss
16880 * @set_wiphy_params = Set wiphy params
16881 * @set_tx_power = Set tx power
16882 * @get_tx_power = get tx power
16883 * @remain_on_channel = Remain on channel
16884 * @cancel_remain_on_channel = Cancel remain on channel
16885 * @mgmt_tx = Tx management frame
16886 * @mgmt_tx_cancel_wait = Cancel management tx wait
16887 * @set_default_mgmt_key = Set default management key
16888 * @set_txq_params = Set tx queue parameters
16889 * @get_station = Get station
16890 * @set_power_mgmt = Set power management
16891 * @del_station = Delete station
16892 * @add_station = Add station
16893 * @set_pmksa = Set pmksa
16894 * @del_pmksa = Delete pmksa
16895 * @flush_pmksa = Flush pmksa
16896 * @update_ft_ies = Update FT IEs
16897 * @tdls_mgmt = Tdls management
16898 * @tdls_oper = Tdls operation
16899 * @set_rekey_data = Set rekey data
16900 * @sched_scan_start = Scheduled scan start
16901 * @sched_scan_stop = Scheduled scan stop
16902 * @resume = Resume wlan
16903 * @suspend = Suspend wlan
16904 * @set_mac_acl = Set mac acl
16905 * @testmode_cmd = Test mode command
16906 * @set_ap_chanwidth = Set AP channel bandwidth
16907 * @dump_survey = Dump survey
16908 * @key_mgmt_set_pmk = Set pmk key management
16909 */
16910static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16911 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16912 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16913 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16914 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016915 .start_ap = wlan_hdd_cfg80211_start_ap,
16916 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16917 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016918 .change_bss = wlan_hdd_cfg80211_change_bss,
16919 .add_key = wlan_hdd_cfg80211_add_key,
16920 .get_key = wlan_hdd_cfg80211_get_key,
16921 .del_key = wlan_hdd_cfg80211_del_key,
16922 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16923 .scan = wlan_hdd_cfg80211_scan,
16924 .connect = wlan_hdd_cfg80211_connect,
16925 .disconnect = wlan_hdd_cfg80211_disconnect,
16926 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16927 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16928 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16929 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16930 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16931 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16932 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16933 .mgmt_tx = wlan_hdd_mgmt_tx,
16934 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16935 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16936 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016937 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016938 .get_station = wlan_hdd_cfg80211_get_station,
16939 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16940 .del_station = wlan_hdd_cfg80211_del_station,
16941 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016942 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16943 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16944 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016945#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016946 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16947#endif
16948#ifdef FEATURE_WLAN_TDLS
16949 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16950 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16951#endif
16952#ifdef WLAN_FEATURE_GTK_OFFLOAD
16953 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16954#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16955#ifdef FEATURE_WLAN_SCAN_PNO
16956 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16957 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16958#endif /*FEATURE_WLAN_SCAN_PNO */
16959 .resume = wlan_hdd_cfg80211_resume_wlan,
16960 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16961 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16962#ifdef WLAN_NL80211_TESTMODE
16963 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16964#endif
16965#ifdef QCA_HT_2040_COEX
16966 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16967#endif
16968 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016969#ifdef CHANNEL_SWITCH_SUPPORTED
16970 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16971#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016972 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016973#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16974 defined(CFG80211_ABORT_SCAN)
16975 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16976#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016977};