blob: 6ff3e7c188b4fcd62f8128f0adfc395b1fa372ab [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"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700112
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113#define g_mode_rates_size (12)
114#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
116 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
117
118/*
119 * Android CTS verifier needs atleast this much wait time (in msec)
120 */
121#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
122
123/*
124 * Refer @tCfgProtection structure for definition of the bit map.
125 * below value is obtained by setting the following bit-fields.
126 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
127 */
128#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
129
130#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700131 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800132 .center_freq = (freq), \
133 .hw_value = (chan), \
134 .flags = (flag), \
135 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800136 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800137}
138
139#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700140 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141 .center_freq = (freq), \
142 .hw_value = (chan), \
143 .flags = (flag), \
144 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800145 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146}
147
148#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
149 { \
150 .bitrate = rate, \
151 .hw_value = rate_id, \
152 .flags = flag, \
153 }
154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
156#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157
158#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
Agrawal Ashish65634612016-08-18 13:24:32 +0530160#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
161 mode <= DFS_MODE_DEPRIORITIZE))
162#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
163 || (channel >= 36 && channel <= 184))
164
Peng Xu4d67c8f2015-10-16 16:02:26 -0700165#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530166#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168static const u32 hdd_cipher_suites[] = {
169 WLAN_CIPHER_SUITE_WEP40,
170 WLAN_CIPHER_SUITE_WEP104,
171 WLAN_CIPHER_SUITE_TKIP,
172#ifdef FEATURE_WLAN_ESE
173#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
174#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
175 WLAN_CIPHER_SUITE_BTK,
176 WLAN_CIPHER_SUITE_KRK,
177 WLAN_CIPHER_SUITE_CCMP,
178#else
179 WLAN_CIPHER_SUITE_CCMP,
180#endif
181#ifdef FEATURE_WLAN_WAPI
182 WLAN_CIPHER_SUITE_SMS4,
183#endif
184#ifdef WLAN_FEATURE_11W
185 WLAN_CIPHER_SUITE_AES_CMAC,
186#endif
187};
188
Abhishek Singhf512bf32016-05-04 16:47:46 +0530189static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800190 HDD2GHZCHAN(2412, 1, 0),
191 HDD2GHZCHAN(2417, 2, 0),
192 HDD2GHZCHAN(2422, 3, 0),
193 HDD2GHZCHAN(2427, 4, 0),
194 HDD2GHZCHAN(2432, 5, 0),
195 HDD2GHZCHAN(2437, 6, 0),
196 HDD2GHZCHAN(2442, 7, 0),
197 HDD2GHZCHAN(2447, 8, 0),
198 HDD2GHZCHAN(2452, 9, 0),
199 HDD2GHZCHAN(2457, 10, 0),
200 HDD2GHZCHAN(2462, 11, 0),
201 HDD2GHZCHAN(2467, 12, 0),
202 HDD2GHZCHAN(2472, 13, 0),
203 HDD2GHZCHAN(2484, 14, 0),
204};
205
Abhishek Singhf512bf32016-05-04 16:47:46 +0530206static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 HDD5GHZCHAN(5180, 36, 0),
208 HDD5GHZCHAN(5200, 40, 0),
209 HDD5GHZCHAN(5220, 44, 0),
210 HDD5GHZCHAN(5240, 48, 0),
211 HDD5GHZCHAN(5260, 52, 0),
212 HDD5GHZCHAN(5280, 56, 0),
213 HDD5GHZCHAN(5300, 60, 0),
214 HDD5GHZCHAN(5320, 64, 0),
215 HDD5GHZCHAN(5500, 100, 0),
216 HDD5GHZCHAN(5520, 104, 0),
217 HDD5GHZCHAN(5540, 108, 0),
218 HDD5GHZCHAN(5560, 112, 0),
219 HDD5GHZCHAN(5580, 116, 0),
220 HDD5GHZCHAN(5600, 120, 0),
221 HDD5GHZCHAN(5620, 124, 0),
222 HDD5GHZCHAN(5640, 128, 0),
223 HDD5GHZCHAN(5660, 132, 0),
224 HDD5GHZCHAN(5680, 136, 0),
225 HDD5GHZCHAN(5700, 140, 0),
226 HDD5GHZCHAN(5720, 144, 0),
227 HDD5GHZCHAN(5745, 149, 0),
228 HDD5GHZCHAN(5765, 153, 0),
229 HDD5GHZCHAN(5785, 157, 0),
230 HDD5GHZCHAN(5805, 161, 0),
231 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 HDD5GHZCHAN(5852, 170, 0),
233 HDD5GHZCHAN(5855, 171, 0),
234 HDD5GHZCHAN(5860, 172, 0),
235 HDD5GHZCHAN(5865, 173, 0),
236 HDD5GHZCHAN(5870, 174, 0),
237 HDD5GHZCHAN(5875, 175, 0),
238 HDD5GHZCHAN(5880, 176, 0),
239 HDD5GHZCHAN(5885, 177, 0),
240 HDD5GHZCHAN(5890, 178, 0),
241 HDD5GHZCHAN(5895, 179, 0),
242 HDD5GHZCHAN(5900, 180, 0),
243 HDD5GHZCHAN(5905, 181, 0),
244 HDD5GHZCHAN(5910, 182, 0),
245 HDD5GHZCHAN(5915, 183, 0),
246 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800247};
248
249static struct ieee80211_rate g_mode_rates[] = {
250 HDD_G_MODE_RATETAB(10, 0x1, 0),
251 HDD_G_MODE_RATETAB(20, 0x2, 0),
252 HDD_G_MODE_RATETAB(55, 0x4, 0),
253 HDD_G_MODE_RATETAB(110, 0x8, 0),
254 HDD_G_MODE_RATETAB(60, 0x10, 0),
255 HDD_G_MODE_RATETAB(90, 0x20, 0),
256 HDD_G_MODE_RATETAB(120, 0x40, 0),
257 HDD_G_MODE_RATETAB(180, 0x80, 0),
258 HDD_G_MODE_RATETAB(240, 0x100, 0),
259 HDD_G_MODE_RATETAB(360, 0x200, 0),
260 HDD_G_MODE_RATETAB(480, 0x400, 0),
261 HDD_G_MODE_RATETAB(540, 0x800, 0),
262};
263
264static struct ieee80211_rate a_mode_rates[] = {
265 HDD_G_MODE_RATETAB(60, 0x10, 0),
266 HDD_G_MODE_RATETAB(90, 0x20, 0),
267 HDD_G_MODE_RATETAB(120, 0x40, 0),
268 HDD_G_MODE_RATETAB(180, 0x80, 0),
269 HDD_G_MODE_RATETAB(240, 0x100, 0),
270 HDD_G_MODE_RATETAB(360, 0x200, 0),
271 HDD_G_MODE_RATETAB(480, 0x400, 0),
272 HDD_G_MODE_RATETAB(540, 0x800, 0),
273};
274
275static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530276 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700278 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 .bitrates = g_mode_rates,
280 .n_bitrates = g_mode_rates_size,
281 .ht_cap.ht_supported = 1,
282 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
283 | IEEE80211_HT_CAP_GRN_FLD
284 | IEEE80211_HT_CAP_DSSSCCK40
285 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
286 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
287 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
288 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
289 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
290 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
291 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
292};
293
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530295 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700297 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .bitrates = a_mode_rates,
299 .n_bitrates = a_mode_rates_size,
300 .ht_cap.ht_supported = 1,
301 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
302 | IEEE80211_HT_CAP_GRN_FLD
303 | IEEE80211_HT_CAP_DSSSCCK40
304 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
305 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
306 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
307 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
308 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
309 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
310 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
311 .vht_cap.vht_supported = 1,
312};
313
314/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800315 * TX/RX direction for each kind of interface
316 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800317static const struct ieee80211_txrx_stypes
318 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
319 [NL80211_IFTYPE_STATION] = {
320 .tx = 0xffff,
321 .rx = BIT(SIR_MAC_MGMT_ACTION) |
322 BIT(SIR_MAC_MGMT_PROBE_REQ),
323 },
324 [NL80211_IFTYPE_AP] = {
325 .tx = 0xffff,
326 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
328 BIT(SIR_MAC_MGMT_PROBE_REQ) |
329 BIT(SIR_MAC_MGMT_DISASSOC) |
330 BIT(SIR_MAC_MGMT_AUTH) |
331 BIT(SIR_MAC_MGMT_DEAUTH) |
332 BIT(SIR_MAC_MGMT_ACTION),
333 },
334 [NL80211_IFTYPE_ADHOC] = {
335 .tx = 0xffff,
336 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ) |
339 BIT(SIR_MAC_MGMT_DISASSOC) |
340 BIT(SIR_MAC_MGMT_AUTH) |
341 BIT(SIR_MAC_MGMT_DEAUTH) |
342 BIT(SIR_MAC_MGMT_ACTION),
343 },
344 [NL80211_IFTYPE_P2P_CLIENT] = {
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ACTION) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ),
348 },
349 [NL80211_IFTYPE_P2P_GO] = {
350 /* This is also same as for SoftAP */
351 .tx = 0xffff,
352 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_PROBE_REQ) |
355 BIT(SIR_MAC_MGMT_DISASSOC) |
356 BIT(SIR_MAC_MGMT_AUTH) |
357 BIT(SIR_MAC_MGMT_DEAUTH) |
358 BIT(SIR_MAC_MGMT_ACTION),
359 },
360};
361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362/* Interface limits and combinations registered by the driver */
363
364/* STA ( + STA ) combination */
365static const struct ieee80211_iface_limit
366 wlan_hdd_sta_iface_limit[] = {
367 {
368 .max = 3, /* p2p0 is a STA as well */
369 .types = BIT(NL80211_IFTYPE_STATION),
370 },
371};
372
373/* ADHOC (IBSS) limit */
374static const struct ieee80211_iface_limit
375 wlan_hdd_adhoc_iface_limit[] = {
376 {
377 .max = 1,
378 .types = BIT(NL80211_IFTYPE_STATION),
379 },
380 {
381 .max = 1,
382 .types = BIT(NL80211_IFTYPE_ADHOC),
383 },
384};
385
386/* AP ( + AP ) combination */
387static const struct ieee80211_iface_limit
388 wlan_hdd_ap_iface_limit[] = {
389 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530390 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 .types = BIT(NL80211_IFTYPE_AP),
392 },
393};
394
395/* P2P limit */
396static const struct ieee80211_iface_limit
397 wlan_hdd_p2p_iface_limit[] = {
398 {
399 .max = 1,
400 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
401 },
402 {
403 .max = 1,
404 .types = BIT(NL80211_IFTYPE_P2P_GO),
405 },
406};
407
408static const struct ieee80211_iface_limit
409 wlan_hdd_sta_ap_iface_limit[] = {
410 {
411 /* We need 1 extra STA interface for OBSS scan when SAP starts
412 * with HT40 in STA+SAP concurrency mode
413 */
414 .max = (1 + SAP_MAX_OBSS_STA_CNT),
415 .types = BIT(NL80211_IFTYPE_STATION),
416 },
417 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530418 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800419 .types = BIT(NL80211_IFTYPE_AP),
420 },
421};
422
423/* STA + P2P combination */
424static const struct ieee80211_iface_limit
425 wlan_hdd_sta_p2p_iface_limit[] = {
426 {
427 /* One reserved for dedicated P2PDEV usage */
428 .max = 2,
429 .types = BIT(NL80211_IFTYPE_STATION)
430 },
431 {
432 /* Support for two identical (GO + GO or CLI + CLI)
433 * or dissimilar (GO + CLI) P2P interfaces
434 */
435 .max = 2,
436 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
437 },
438};
439
440/* STA + AP + P2PGO combination */
441static const struct ieee80211_iface_limit
442wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
443 /* Support for AP+P2PGO interfaces */
444 {
445 .max = 2,
446 .types = BIT(NL80211_IFTYPE_STATION)
447 },
448 {
449 .max = 1,
450 .types = BIT(NL80211_IFTYPE_P2P_GO)
451 },
452 {
453 .max = 1,
454 .types = BIT(NL80211_IFTYPE_AP)
455 }
456};
457
458/* SAP + P2P combination */
459static const struct ieee80211_iface_limit
460wlan_hdd_sap_p2p_iface_limit[] = {
461 {
462 /* 1 dedicated for p2p0 which is a STA type */
463 .max = 1,
464 .types = BIT(NL80211_IFTYPE_STATION)
465 },
466 {
467 /* The p2p interface in SAP+P2P can be GO/CLI.
468 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
469 */
470 .max = 1,
471 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
472 },
473 {
474 /* SAP+GO to support only one SAP interface */
475 .max = 1,
476 .types = BIT(NL80211_IFTYPE_AP)
477 }
478};
479
480/* P2P + P2P combination */
481static const struct ieee80211_iface_limit
482wlan_hdd_p2p_p2p_iface_limit[] = {
483 {
484 /* 1 dedicated for p2p0 which is a STA type */
485 .max = 1,
486 .types = BIT(NL80211_IFTYPE_STATION)
487 },
488 {
489 /* The p2p interface in P2P+P2P can be GO/CLI.
490 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
491 */
492 .max = 2,
493 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
494 },
495};
496
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700497static const struct ieee80211_iface_limit
498 wlan_hdd_mon_iface_limit[] = {
499 {
500 .max = 3, /* Monitor interface */
501 .types = BIT(NL80211_IFTYPE_MONITOR),
502 },
503};
504
505static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506 wlan_hdd_iface_combination[] = {
507 /* STA */
508 {
509 .limits = wlan_hdd_sta_iface_limit,
510 .num_different_channels = 2,
511 .max_interfaces = 3,
512 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
513 },
514 /* ADHOC */
515 {
516 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700517 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 .max_interfaces = 2,
519 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
520 },
521 /* AP */
522 {
523 .limits = wlan_hdd_ap_iface_limit,
524 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530525 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
527 },
528 /* P2P */
529 {
530 .limits = wlan_hdd_p2p_iface_limit,
531 .num_different_channels = 2,
532 .max_interfaces = 2,
533 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
534 },
535 /* STA + AP */
536 {
537 .limits = wlan_hdd_sta_ap_iface_limit,
538 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530539 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800540 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
541 .beacon_int_infra_match = true,
542 },
543 /* STA + P2P */
544 {
545 .limits = wlan_hdd_sta_p2p_iface_limit,
546 .num_different_channels = 2,
547 /* one interface reserved for P2PDEV dedicated usage */
548 .max_interfaces = 4,
549 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
550 .beacon_int_infra_match = true,
551 },
552 /* STA + P2P GO + SAP */
553 {
554 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
555 /* we can allow 3 channels for three different persona
556 * but due to firmware limitation, allow max 2 concrnt channels.
557 */
558 .num_different_channels = 2,
559 /* one interface reserved for P2PDEV dedicated usage */
560 .max_interfaces = 4,
561 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
562 .beacon_int_infra_match = true,
563 },
564 /* SAP + P2P */
565 {
566 .limits = wlan_hdd_sap_p2p_iface_limit,
567 .num_different_channels = 2,
568 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
569 .max_interfaces = 3,
570 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
571 .beacon_int_infra_match = true,
572 },
573 /* P2P + P2P */
574 {
575 .limits = wlan_hdd_p2p_p2p_iface_limit,
576 .num_different_channels = 2,
577 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
578 .max_interfaces = 3,
579 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
580 .beacon_int_infra_match = true,
581 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530582 /* Monitor */
583 {
584 .limits = wlan_hdd_mon_iface_limit,
585 .max_interfaces = 3,
586 .num_different_channels = 2,
587 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
588 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590
591static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593#ifdef WLAN_NL80211_TESTMODE
594enum wlan_hdd_tm_attr {
595 WLAN_HDD_TM_ATTR_INVALID = 0,
596 WLAN_HDD_TM_ATTR_CMD = 1,
597 WLAN_HDD_TM_ATTR_DATA = 2,
598 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
599 WLAN_HDD_TM_ATTR_TYPE = 4,
600 /* keep last */
601 WLAN_HDD_TM_ATTR_AFTER_LAST,
602 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
603};
604
605enum wlan_hdd_tm_cmd {
606 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
607 WLAN_HDD_TM_CMD_WLAN_HB = 1,
608};
609
610#define WLAN_HDD_TM_DATA_MAX_LEN 5000
611
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530612enum wlan_hdd_vendor_ie_access_policy {
613 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
614 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
615};
616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
618 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
619 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
620 .len = WLAN_HDD_TM_DATA_MAX_LEN},
621};
622#endif /* WLAN_NL80211_TESTMODE */
623
624#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
625static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
626 .flags = WIPHY_WOWLAN_MAGIC_PKT,
627 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
628 .pattern_min_len = 1,
629 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
630};
631#endif
632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530634 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
635 * @flags: Pointer to the flags to Add channel switch flag.
636 *
637 * This Function adds Channel Switch support flag, if channel switch is
638 * supported by kernel.
639 * Return: void.
640 */
641#ifdef CHANNEL_SWITCH_SUPPORTED
642static inline void hdd_add_channel_switch_support(uint32_t *flags)
643{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800644 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530645 return;
646}
647#else
648static inline void hdd_add_channel_switch_support(uint32_t *flags)
649{
650 return;
651}
652#endif
653
Manikandan Mohan22b83722015-12-15 15:03:23 -0800654#ifdef FEATURE_WLAN_TDLS
655
656/* TDLS capabilities params */
657#define PARAM_MAX_TDLS_SESSION \
658 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
659#define PARAM_TDLS_FEATURE_SUPPORT \
660 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
661
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530662/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
664 * @wiphy: WIPHY structure pointer
665 * @wdev: Wireless device structure pointer
666 * @data: Pointer to the data received
667 * @data_len: Length of the data received
668 *
669 * This function provides TDLS capabilities
670 *
671 * Return: 0 on success and errno on failure
672 */
673static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
674 struct wireless_dev *wdev,
675 const void *data,
676 int data_len)
677{
678 int status;
679 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
680 struct sk_buff *skb;
681 uint32_t set = 0;
682
Jeff Johnson1f61b612016-02-12 16:28:33 -0800683 ENTER_DEV(wdev->netdev);
684
Anurag Chouhan6d760662016-02-20 16:05:43 +0530685 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 hdd_err("Command not allowed in FTM mode");
687 return -EPERM;
688 }
689
690 status = wlan_hdd_validate_context(hdd_ctx);
691 if (status)
692 return status;
693
694 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
695 NLMSG_HDRLEN);
696 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700697 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 goto fail;
699 }
700
701 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800702 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
704 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700705 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 goto fail;
707 }
708 } else {
709 set = set | WIFI_TDLS_SUPPORT;
710 set = set | (hdd_ctx->config->fTDLSExternalControl ?
711 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
712 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
713 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800714 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
716 hdd_ctx->max_num_tdls_sta) ||
717 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
718 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700719 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720 goto fail;
721 }
722 }
723 return cfg80211_vendor_cmd_reply(skb);
724fail:
725 if (skb)
726 kfree_skb(skb);
727 return -EINVAL;
728}
729
730/**
731 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
732 * @wiphy: WIPHY structure pointer
733 * @wdev: Wireless device structure pointer
734 * @data: Pointer to the data received
735 * @data_len: Length of the data received
736 *
737 * This function provides TDLS capabilities
738 *
739 * Return: 0 on success and errno on failure
740 */
741static int
742wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
743 struct wireless_dev *wdev,
744 const void *data,
745 int data_len)
746{
747 int ret;
748
749 cds_ssr_protect(__func__);
750 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
751 data, data_len);
752 cds_ssr_unprotect(__func__);
753
754 return ret;
755}
756#endif
757
758#ifdef QCA_HT_2040_COEX
759static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
760#endif
761
762#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
763/*
764 * FUNCTION: wlan_hdd_send_avoid_freq_event
765 * This is called when wlan driver needs to send vendor specific
766 * avoid frequency range event to userspace
767 */
768int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
769 tHddAvoidFreqList *pAvoidFreqList)
770{
771 struct sk_buff *vendor_event;
772
773 ENTER();
774
775 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700776 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 return -EINVAL;
778 }
779
780 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700781 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 return -EINVAL;
783 }
784
785 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
786 NULL,
787 sizeof(tHddAvoidFreqList),
788 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
789 GFP_KERNEL);
790 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700791 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792 return -EINVAL;
793 }
794
795 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
796 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
797
798 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
799
800 EXIT();
801 return 0;
802}
803#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
804
805/* vendor specific events */
806static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
807#ifdef FEATURE_WLAN_CH_AVOID
808 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
809 .vendor_id =
810 QCA_NL80211_VENDOR_ID,
811 .subcmd =
812 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
813 },
814#endif /* FEATURE_WLAN_CH_AVOID */
815
816#ifdef WLAN_FEATURE_NAN
817 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
818 .vendor_id =
819 QCA_NL80211_VENDOR_ID,
820 .subcmd =
821 QCA_NL80211_VENDOR_SUBCMD_NAN
822 },
823#endif
824
825#ifdef WLAN_FEATURE_STATS_EXT
826 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
827 .vendor_id =
828 QCA_NL80211_VENDOR_ID,
829 .subcmd =
830 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
831 },
832#endif /* WLAN_FEATURE_STATS_EXT */
833#ifdef FEATURE_WLAN_EXTSCAN
834 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
835 .vendor_id =
836 QCA_NL80211_VENDOR_ID,
837 .subcmd =
838 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
839 },
840 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
841 .vendor_id =
842 QCA_NL80211_VENDOR_ID,
843 .subcmd =
844 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
845 },
846 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
847 .
848 vendor_id
849 =
850 QCA_NL80211_VENDOR_ID,
851 .subcmd =
852 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
853 },
854 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
855 .
856 vendor_id
857 =
858 QCA_NL80211_VENDOR_ID,
859 .
860 subcmd =
861 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
862 },
863 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
864 .
865 vendor_id
866 =
867 QCA_NL80211_VENDOR_ID,
868 .
869 subcmd
870 =
871 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
872 },
873 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
874 .
875 vendor_id
876 =
877 QCA_NL80211_VENDOR_ID,
878 .subcmd =
879 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
880 },
881 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
882 .vendor_id =
883 QCA_NL80211_VENDOR_ID,
884 .subcmd =
885 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
886 },
887 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
888 .
889 vendor_id
890 =
891 QCA_NL80211_VENDOR_ID,
892 .subcmd =
893 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
894 },
895 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
896 .
897 vendor_id
898 =
899 QCA_NL80211_VENDOR_ID,
900 .subcmd =
901 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
902 },
903 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
904 .
905 vendor_id
906 =
907 QCA_NL80211_VENDOR_ID,
908 .
909 subcmd
910 =
911 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
912 },
913 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
914 .
915 vendor_id
916 =
917 QCA_NL80211_VENDOR_ID,
918 .
919 subcmd =
920 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
921 },
922 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
923 .
924 vendor_id
925 =
926 QCA_NL80211_VENDOR_ID,
927 .
928 subcmd
929 =
930 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
931 },
932 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
933 .
934 vendor_id
935 =
936 QCA_NL80211_VENDOR_ID,
937 .
938 subcmd
939 =
940 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
941 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942#endif /* FEATURE_WLAN_EXTSCAN */
943
944#ifdef WLAN_FEATURE_LINK_LAYER_STATS
945 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
946 .vendor_id =
947 QCA_NL80211_VENDOR_ID,
948 .subcmd =
949 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
950 },
951 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
952 .vendor_id =
953 QCA_NL80211_VENDOR_ID,
954 .subcmd =
955 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
956 },
957 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
958 .vendor_id =
959 QCA_NL80211_VENDOR_ID,
960 .subcmd =
961 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
962 },
963 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
964 .vendor_id =
965 QCA_NL80211_VENDOR_ID,
966 .subcmd =
967 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
968 },
969 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
970 .vendor_id =
971 QCA_NL80211_VENDOR_ID,
972 .subcmd =
973 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
974 },
975 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
976 .vendor_id =
977 QCA_NL80211_VENDOR_ID,
978 .subcmd =
979 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
980 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800981 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
982 .vendor_id =
983 QCA_NL80211_VENDOR_ID,
984 .subcmd =
985 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
986 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
988 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
989 .vendor_id =
990 QCA_NL80211_VENDOR_ID,
991 .subcmd =
992 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
993 },
994 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
995 .vendor_id = QCA_NL80211_VENDOR_ID,
996 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
997 },
998#ifdef WLAN_FEATURE_ROAM_OFFLOAD
999 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1004 },
1005#endif
1006 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1007 .vendor_id =
1008 QCA_NL80211_VENDOR_ID,
1009 .subcmd =
1010 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1011 },
1012 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1013 .vendor_id =
1014 QCA_NL80211_VENDOR_ID,
1015 .subcmd =
1016 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1017 },
1018 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1019 .vendor_id =
1020 QCA_NL80211_VENDOR_ID,
1021 .subcmd =
1022 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1023 },
1024 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1025 .vendor_id =
1026 QCA_NL80211_VENDOR_ID,
1027 .subcmd =
1028 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1029 },
1030 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1031 .vendor_id =
1032 QCA_NL80211_VENDOR_ID,
1033 .subcmd =
1034 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1035 },
1036#ifdef FEATURE_WLAN_EXTSCAN
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1044 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1048 },
1049#endif /* FEATURE_WLAN_EXTSCAN */
1050 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1053 },
1054#ifdef WLAN_FEATURE_MEMDUMP
1055 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1058 },
1059#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001060#ifdef WLAN_FEATURE_TSF
1061 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1064 },
1065#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1069 },
1070 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1073 },
1074 /* OCB events */
1075 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1078 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001079#ifdef FEATURE_LFR_SUBNET_DETECTION
1080 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1083 },
1084#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001085
1086#ifdef WLAN_FEATURE_NAN_DATAPATH
1087 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1090 },
1091#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001092
1093 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1096 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301097 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1098 .vendor_id = QCA_NL80211_VENDOR_ID,
1099 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1100 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301101 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1102 .vendor_id = QCA_NL80211_VENDOR_ID,
1103 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1104 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001105#ifdef WLAN_UMAC_CONVERGENCE
1106 COMMON_VENDOR_EVENTS
1107#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108};
1109
1110/**
1111 * __is_driver_dfs_capable() - get driver DFS capability
1112 * @wiphy: pointer to wireless wiphy structure.
1113 * @wdev: pointer to wireless_dev structure.
1114 * @data: Pointer to the data to be passed via vendor interface
1115 * @data_len:Length of the data to be passed
1116 *
1117 * This function is called by userspace to indicate whether or not
1118 * the driver supports DFS offload.
1119 *
1120 * Return: 0 on success, negative errno on failure
1121 */
1122static int __is_driver_dfs_capable(struct wiphy *wiphy,
1123 struct wireless_dev *wdev,
1124 const void *data,
1125 int data_len)
1126{
1127 u32 dfs_capability = 0;
1128 struct sk_buff *temp_skbuff;
1129 int ret_val;
1130 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1131
Jeff Johnson1f61b612016-02-12 16:28:33 -08001132 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001133
1134 ret_val = wlan_hdd_validate_context(hdd_ctx);
1135 if (ret_val)
1136 return ret_val;
1137
Anurag Chouhan6d760662016-02-20 16:05:43 +05301138 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139 hdd_err("Command not allowed in FTM mode");
1140 return -EPERM;
1141 }
1142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144
1145 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1146 NLMSG_HDRLEN);
1147
1148 if (temp_skbuff != NULL) {
1149 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1150 dfs_capability);
1151 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001152 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153 kfree_skb(temp_skbuff);
1154
1155 return ret_val;
1156 }
1157
1158 return cfg80211_vendor_cmd_reply(temp_skbuff);
1159 }
1160
Jeff Johnson020db452016-06-29 14:37:26 -07001161 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001162 return -ENOMEM;
1163}
1164
1165/**
1166 * is_driver_dfs_capable() - get driver DFS capability
1167 * @wiphy: pointer to wireless wiphy structure.
1168 * @wdev: pointer to wireless_dev structure.
1169 * @data: Pointer to the data to be passed via vendor interface
1170 * @data_len:Length of the data to be passed
1171 *
1172 * This function is called by userspace to indicate whether or not
1173 * the driver supports DFS offload. This is an SSR-protected
1174 * wrapper function.
1175 *
1176 * Return: 0 on success, negative errno on failure
1177 */
1178static int is_driver_dfs_capable(struct wiphy *wiphy,
1179 struct wireless_dev *wdev,
1180 const void *data,
1181 int data_len)
1182{
1183 int ret;
1184
1185 cds_ssr_protect(__func__);
1186 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1187 cds_ssr_unprotect(__func__);
1188
1189 return ret;
1190}
1191
1192/**
1193 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1194 *
1195 * @adapter: SAP adapter pointer
1196 *
1197 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1198 * radio. So in case of DFS MCC scenario override current SAP given config
1199 * to follow concurrent SAP DFS config
1200 *
1201 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1202 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1204{
1205 hdd_adapter_t *con_sap_adapter;
1206 tsap_Config_t *sap_config, *con_sap_config;
1207 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001208 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001210 if (!hdd_ctx) {
1211 hdd_err("hdd context is NULL");
1212 return 0;
1213 }
1214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 /*
1216 * Check if AP+AP case, once primary AP chooses a DFS
1217 * channel secondary AP should always follow primary APs channel
1218 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001219 if (!policy_mgr_concurrent_beaconing_sessions_running(
1220 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 return 0;
1222
1223 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1224 if (!con_sap_adapter)
1225 return 0;
1226
1227 sap_config = &adapter->sessionCtx.ap.sapConfig;
1228 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1229 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1230
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001231 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 return 0;
1233
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001234 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001236 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 sap_config->channel = con_ch;
1238
1239 if (con_sap_config->acs_cfg.acs_mode == true) {
1240 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1241 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001242 hdd_err("Primary AP channel config error");
1243 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 con_ch, con_sap_config->acs_cfg.pri_ch,
1245 con_sap_config->acs_cfg.ht_sec_ch);
1246 return -EINVAL;
1247 }
1248 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1249 * MCC restriction. So free ch list allocated in do_acs
1250 * func for Sec AP and realloc for Pri AP ch list size
1251 */
1252 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301253 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301255 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256 &con_sap_config->acs_cfg,
1257 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301258 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 sizeof(uint8_t) *
1260 con_sap_config->acs_cfg.ch_list_count);
1261 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001262 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 return -ENOMEM;
1264 }
1265
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301266 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 con_sap_config->acs_cfg.ch_list,
1268 con_sap_config->acs_cfg.ch_list_count);
1269
1270 } else {
1271 sap_config->acs_cfg.pri_ch = con_ch;
1272 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1273 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1274 }
1275
1276 return con_ch;
1277}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001278
1279/**
1280 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1281 * @sap_cfg: pointer to SAP config struct
1282 *
1283 * This function sets the default ACS start and end channel for the given band
1284 * and also parses the given ACS channel list.
1285 *
1286 * Return: None
1287 */
1288
1289static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1290 bool vht_enabled)
1291{
1292 int i;
1293 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001295 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001299 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1300 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001303 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1304 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001307 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1308 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001309 }
1310
1311 if (ht_enabled)
1312 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1313
1314 if (vht_enabled)
1315 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1316
1317
1318 /* Parse ACS Chan list from hostapd */
1319 if (!sap_cfg->acs_cfg.ch_list)
1320 return;
1321
1322 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1323 sap_cfg->acs_cfg.end_ch =
1324 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1325 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301326 /* avoid channel as start channel */
1327 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1328 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001329 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1330 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1331 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1332 }
1333}
1334
1335
1336static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1337
1338/**
1339 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1340 * @adapter: pointer to SAP adapter struct
1341 *
1342 * This function starts the ACS procedure if there are no
1343 * constraints like MBSSID DFS restrictions.
1344 *
1345 * Return: Status of ACS Start procedure
1346 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301347int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001348{
1349
1350 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1351 tsap_Config_t *sap_config;
1352 tpWLAN_SAPEventCB acs_event_callback;
1353 int status;
1354
1355 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301356 if (hdd_ctx->acs_policy.acs_channel)
1357 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1358 else
1359 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360
1361 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001362 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001364
1365 if (status > 0) {
1366 /*notify hostapd about channel override */
1367 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1368 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1369 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 }
Jeff Johnson68755312017-02-10 11:46:55 -08001371
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1373 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001374 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 return -EINVAL;
1376 }
1377
1378 acs_event_callback = hdd_hostapd_sap_event_cb;
1379
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301380 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301381 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301382 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 acs_event_callback, sap_config, adapter->dev);
1386
1387
1388 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001389 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 return -EINVAL;
1391 }
bings394afdd2017-01-09 11:22:38 +08001392 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1393 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1395
1396 return 0;
1397}
1398
1399/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301400 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1401 * @ap_adapter: AP adapter
1402 * @nol: Non-occupancy list
1403 * @nol_len: Length of NOL
1404 *
1405 * Get the NOL for SAP
1406 *
1407 * Return: Zero on success, non-zero on failure
1408 */
1409static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1410 uint32_t *nol_len)
1411{
1412 QDF_STATUS ret;
1413
1414 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1415 nol, nol_len);
1416 if (QDF_IS_STATUS_ERROR(ret))
1417 return -EINVAL;
1418
1419 return 0;
1420}
1421
1422/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301423 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1424 * @hdd_ctx: hdd context
1425 * @acs_chan_params: external acs channel params
1426 * @sap_config: SAP config
1427 *
1428 * This API provides unsorted pcl list.
1429 * this list is a subset of the valid channel list given by hostapd.
1430 * if channel is not present in pcl, weightage will be given as zero
1431 *
1432 * Return: Zero on success, non-zero on failure
1433 */
1434static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1435 struct hdd_vendor_acs_chan_params *acs_chan_params,
1436 tsap_Config_t *sap_config)
1437{
1438 int i, j;
1439
1440 for (i = 0; i < acs_chan_params->channel_count; i++) {
1441 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1442 if (acs_chan_params->channel_list[i] ==
1443 sap_config->acs_cfg.pcl_channels[j]) {
1444 acs_chan_params->vendor_pcl_list[i] =
1445 sap_config->acs_cfg.pcl_channels[j];
1446 acs_chan_params->vendor_weight_list[i] =
1447 sap_config->acs_cfg.
1448 pcl_channels_weight_list[j];
1449 break;
1450 } else {
1451 acs_chan_params->vendor_pcl_list[i] =
1452 acs_chan_params->channel_list[i];
1453 acs_chan_params->vendor_weight_list[i] = 0;
1454 }
1455 }
1456 }
1457 if (hdd_ctx->unsafe_channel_count == 0)
1458 return;
1459 /* Update unsafe channel weight as zero */
1460 for (i = 0; i < acs_chan_params->channel_count; i++) {
1461 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1462 if (acs_chan_params->channel_list[i] ==
1463 hdd_ctx->unsafe_channel_list[j]) {
1464 acs_chan_params->vendor_weight_list[i] = 0;
1465 }
1466 }
1467 }
1468}
1469
1470/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301471 * hdd_update_reg_chan_info : This API contructs channel info
1472 * for all the given channel
1473 * @adapter: pointer to SAP adapter struct
1474 * @channel_count: channel count
1475 * @channel_list: channel list
1476 *
1477 * Return: Status of of channel information updation
1478 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301479static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301480 uint32_t channel_count,
1481 uint8_t *channel_list)
1482{
1483 int i;
1484 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001485 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301486 uint8_t bw_offset = 0, chan = 0;
1487 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1488 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1489
1490 /* memory allocation */
1491 sap_config->channel_info = qdf_mem_malloc(
1492 sizeof(struct hdd_channel_info) *
1493 channel_count);
1494 if (!sap_config->channel_info) {
1495 hdd_err("memory allocation failed");
1496 return -ENOMEM;
1497
1498 }
1499 for (i = 0; i < channel_count; i++) {
1500 icv = &sap_config->channel_info[i];
1501 chan = channel_list[i];
1502
1503 if (chan == 0)
1504 continue;
1505
1506 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1507 bw_offset = 1 << BW_40_OFFSET_BIT;
1508 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1509 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001510 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301511 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001512 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1513 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301514
1515 /* filling demo values */
1516 icv->max_radio_power = HDD_MAX_TX_POWER;
1517 icv->min_radio_power = HDD_MIN_TX_POWER;
1518 /* not supported in current driver */
1519 icv->max_antenna_gain = 0;
1520
1521 icv->reg_class_id = wlan_hdd_find_opclass(
1522 WLAN_HDD_GET_HAL_CTX(adapter),
1523 chan, bw_offset);
1524
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001525 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301526 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001527 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1528 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301529 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1530 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1531 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001532
Kapil Gupta086c6202016-12-11 18:17:06 +05301533 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001534 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301535 sap_config->acs_cfg.ch_width,
1536 sap_config->acs_cfg.is_ht_enabled,
1537 sap_config->acs_cfg.is_vht_enabled,
1538 hdd_ctx->config->enable_sub_20_channel_width);
1539
1540 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1541 icv->freq, icv->flags,
1542 icv->flagext, icv->ieee_chan_number,
1543 icv->max_reg_power, icv->max_radio_power,
1544 icv->min_radio_power, icv->reg_class_id,
1545 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1546 icv->vht_center_freq_seg1);
1547 }
1548 return 0;
1549}
1550
1551/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1552#define CHAN_INFO_ATTR_FLAGS \
1553 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1554#define CHAN_INFO_ATTR_FLAG_EXT \
1555 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1556#define CHAN_INFO_ATTR_FREQ \
1557 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1558#define CHAN_INFO_ATTR_MAX_REG_POWER \
1559 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1560#define CHAN_INFO_ATTR_MAX_POWER \
1561 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1562#define CHAN_INFO_ATTR_MIN_POWER \
1563 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1564#define CHAN_INFO_ATTR_REG_CLASS_ID \
1565 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1566#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1567 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1568#define CHAN_INFO_ATTR_VHT_SEG_0 \
1569 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1570#define CHAN_INFO_ATTR_VHT_SEG_1 \
1571 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1572
1573/**
1574 * hdd_cfg80211_update_channel_info() - add channel info attributes
1575 * @skb: pointer to sk buff
1576 * @hdd_ctx: pointer to hdd station context
1577 * @idx: attribute index
1578 *
1579 * Return: Success(0) or reason code for failure
1580 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301581static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301582hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1583 tsap_Config_t *sap_config, int idx)
1584{
1585 struct nlattr *nla_attr, *channel;
1586 struct hdd_channel_info *icv;
1587 int i;
1588
1589 nla_attr = nla_nest_start(skb, idx);
1590 if (!nla_attr)
1591 goto fail;
1592
1593 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1594 channel = nla_nest_start(skb, i);
1595 if (!channel)
1596 goto fail;
1597
1598 icv = &sap_config->channel_info[i];
1599 if (!icv) {
1600 hdd_err("channel info not found");
1601 goto fail;
1602 }
1603 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1604 icv->freq) ||
1605 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1606 icv->flags) ||
1607 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1608 icv->flagext) ||
1609 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1610 icv->max_reg_power) ||
1611 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1612 icv->max_radio_power) ||
1613 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1614 icv->min_radio_power) ||
1615 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1616 icv->reg_class_id) ||
1617 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1618 icv->max_antenna_gain) ||
1619 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1620 icv->vht_center_freq_seg0) ||
1621 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1622 icv->vht_center_freq_seg1)) {
1623 hdd_err("put fail");
1624 goto fail;
1625 }
1626 nla_nest_end(skb, channel);
1627 }
1628 nla_nest_end(skb, nla_attr);
1629 return 0;
1630fail:
1631 hdd_err("nl channel update failed");
1632 return -EINVAL;
1633}
1634#undef CHAN_INFO_ATTR_FLAGS
1635#undef CHAN_INFO_ATTR_FLAG_EXT
1636#undef CHAN_INFO_ATTR_FREQ
1637#undef CHAN_INFO_ATTR_MAX_REG_POWER
1638#undef CHAN_INFO_ATTR_MAX_POWER
1639#undef CHAN_INFO_ATTR_MIN_POWER
1640#undef CHAN_INFO_ATTR_REG_CLASS_ID
1641#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1642#undef CHAN_INFO_ATTR_VHT_SEG_0
1643#undef CHAN_INFO_ATTR_VHT_SEG_1
1644
1645/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301646 * hdd_cfg80211_update_pcl() - add pcl info attributes
1647 * @skb: pointer to sk buff
1648 * @hdd_ctx: pointer to hdd station context
1649 * @idx: attribute index
1650 * @vendor_pcl_list: PCL list
1651 * @vendor_weight_list: PCL weights
1652 *
1653 * Return: Success(0) or reason code for failure
1654 */
1655static int32_t
1656hdd_cfg80211_update_pcl(struct sk_buff *skb,
1657 uint8_t ch_list_count, int idx,
1658 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1659{
1660 struct nlattr *nla_attr, *channel;
1661 int i;
1662
1663 nla_attr = nla_nest_start(skb, idx);
1664
1665 if (!nla_attr)
1666 goto fail;
1667
1668 for (i = 0; i < ch_list_count; i++) {
1669 channel = nla_nest_start(skb, i);
1670 if (!channel)
1671 goto fail;
1672 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1673 vendor_pcl_list[i]) ||
1674 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1675 vendor_weight_list[i])) {
1676 hdd_err("put fail");
1677 goto fail;
1678 }
1679 nla_nest_end(skb, channel);
1680 }
1681 nla_nest_end(skb, nla_attr);
1682
1683 return 0;
1684fail:
1685 hdd_err("updating pcl list failed");
1686 return -EINVAL;
1687}
1688
1689static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1690{
1691 /* Get scan band */
1692 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1693 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1694 *band = eCSR_BAND_24;
1695 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1696 *band = eCSR_BAND_5G;
1697 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1698 *band = eCSR_BAND_ALL;
1699 }
1700 /* Auto is not supported currently */
1701 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1702 hdd_err("invalid band");
1703 *band = eCSR_BAND_24;
1704 }
1705}
1706
1707void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1708 uint8_t reason)
1709{
1710 struct sk_buff *skb;
1711 tsap_Config_t *sap_config;
1712 uint32_t channel_count = 0, status;
1713 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1714 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1715 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1716 struct hdd_vendor_acs_chan_params acs_chan_params;
1717 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1718 eCsrBand band = eCSR_BAND_24;
1719 eCsrPhyMode phy_mode;
1720
1721 if (!hdd_ctx) {
1722 hdd_err("HDD context is NULL");
1723 return;
1724 }
1725
1726 ENTER();
1727 sap_config = &adapter->sessionCtx.ap.sapConfig;
1728
1729 /* Get valid channels for SAP */
1730 wlan_hdd_sap_get_valid_channellist(adapter,
1731 &channel_count, channel_list);
1732
1733 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1734 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1735 /* Get phymode */
1736 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1737
1738 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1739 &(adapter->wdev),
1740 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1741 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1742 GFP_KERNEL);
1743
1744 if (!skb) {
1745 hdd_err("cfg80211_vendor_event_alloc failed");
1746 return;
1747 }
1748 /*
1749 * Application expects pcl to be a subset of channel list
1750 * Remove all channels which are not in channel list from pcl
1751 * and add weight as zero
1752 */
1753 acs_chan_params.channel_count = channel_count;
1754 acs_chan_params.channel_list = channel_list;
1755 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1756 acs_chan_params.vendor_weight_list = vendor_weight_list;
1757
1758 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1759 sap_config);
1760 /* Update values in NL buffer */
1761 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1762 reason) ||
1763 nla_put_u8(skb,
1764 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1765 false) ||
1766 nla_put_u8(skb,
1767 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1768 true) ||
1769 nla_put_u8(skb,
1770 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1771 true) ||
1772 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1773 sap_config->acs_cfg.ch_width) ||
1774 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1775 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1776 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1777 band) ||
1778 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1779 phy_mode) ||
1780 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1781 channel_count, channel_list)) {
1782 hdd_err("nla put fail");
1783 goto fail;
1784 }
1785 status = hdd_cfg80211_update_pcl(skb, channel_count,
1786 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1787 vendor_pcl_list, vendor_weight_list);
1788
1789 if (status != 0)
1790 goto fail;
1791
1792 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1793 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1794
1795 if (status != 0)
1796 goto fail;
1797
1798 cfg80211_vendor_event(skb, GFP_KERNEL);
1799 return;
1800fail:
1801 if (skb)
1802 kfree_skb(skb);
1803}
1804
1805static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1806{
1807 struct hdd_external_acs_timer_context *timer_context;
1808
1809 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1810 return 0;
1811
1812 hdd_notice("Starting vendor app based ACS");
1813 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1814 timer_context->adapter = adapter;
1815
1816 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1817 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1818 QDF_TIMER_TYPE_SW,
1819 hdd_acs_response_timeout_handler, timer_context);
1820 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1821 return 0;
1822}
1823
1824/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1826 * @wiphy: Linux wiphy struct pointer
1827 * @wdev: Linux wireless device struct pointer
1828 * @data: ACS information from hostapd
1829 * @data_len: ACS information length
1830 *
1831 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1832 * and starts ACS procedure.
1833 *
1834 * Return: ACS procedure start status
1835 */
1836
1837static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1838 struct wireless_dev *wdev,
1839 const void *data, int data_len)
1840{
1841 struct net_device *ndev = wdev->netdev;
1842 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1843 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1844 tsap_Config_t *sap_config;
1845 struct sk_buff *temp_skbuff;
1846 int status = -EINVAL, i = 0;
1847 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1848 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301849 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001850
1851 /* ***Note*** Donot set SME config related to ACS operation here because
1852 * ACS operation is not synchronouse and ACS for Second AP may come when
1853 * ACS operation for first AP is going on. So only do_acs is split to
1854 * seperate start_acs routine. Also SME-PMAC struct that is used to
1855 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1856 * config shall be set only from start_acs.
1857 */
1858
1859 /* nla_policy Policy template. Policy not applied as some attributes are
1860 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1861 *
1862 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1864 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1865 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1866 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1867 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1868 */
1869
Jeff Johnson1f61b612016-02-12 16:28:33 -08001870 ENTER_DEV(ndev);
1871
Anurag Chouhan6d760662016-02-20 16:05:43 +05301872 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 hdd_err("Command not allowed in FTM mode");
1874 return -EPERM;
1875 }
1876
Kapil Gupta8878ad92017-02-13 11:56:04 +05301877 if (hdd_ctx->config->force_sap_acs &&
1878 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001879 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880 return -EPERM;
1881 }
1882
1883 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301884 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301886
Naveen Rawat64e477e2016-05-20 10:34:56 -07001887 if (cds_is_sub_20_mhz_enabled()) {
1888 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1889 status = -EINVAL;
1890 goto out;
1891 }
1892
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301894 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895
1896 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1897 NULL);
1898 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001899 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900 goto out;
1901 }
1902
1903 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001904 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 goto out;
1906 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301907 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1908 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909
1910 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1911 ht_enabled =
1912 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1913 else
1914 ht_enabled = 0;
1915
1916 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1917 ht40_enabled =
1918 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1919 else
1920 ht40_enabled = 0;
1921
1922 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1923 vht_enabled =
1924 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1925 else
1926 vht_enabled = 0;
1927
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301928 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1929 vht_enabled = 0;
1930 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1931 }
1932
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1934 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1935 } else {
1936 if (ht_enabled && ht40_enabled)
1937 ch_width = 40;
1938 else
1939 ch_width = 20;
1940 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301941
1942 /* this may be possible, when sap_force_11n_for_11ac is set */
1943 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1944 if (ht_enabled && ht40_enabled)
1945 ch_width = 40;
1946 else
1947 ch_width = 20;
1948 }
1949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950 if (ch_width == 80)
1951 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1952 else if (ch_width == 40)
1953 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1954 else
1955 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1956
1957 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1958 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1959 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1960 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1961 * since it contains the frequency values of the channels in
1962 * the channel list.
1963 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1964 * is present
1965 */
1966 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1967 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1968 sap_config->acs_cfg.ch_list_count = nla_len(
1969 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1970 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301971 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 sizeof(uint8_t) *
1973 sap_config->acs_cfg.ch_list_count);
1974 if (sap_config->acs_cfg.ch_list == NULL)
1975 goto out;
1976
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301977 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 sap_config->acs_cfg.ch_list_count);
1979 }
1980 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1981 uint32_t *freq =
1982 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1983 sap_config->acs_cfg.ch_list_count = nla_len(
1984 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1985 sizeof(uint32_t);
1986 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301987 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 sap_config->acs_cfg.ch_list_count);
1989 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001990 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 status = -ENOMEM;
1992 goto out;
1993 }
1994
1995 /* convert frequency to channel */
1996 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1997 sap_config->acs_cfg.ch_list[i] =
1998 ieee80211_frequency_to_channel(freq[i]);
1999 }
2000 }
2001
2002 hdd_debug("get pcl for DO_ACS vendor command");
2003
2004 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002005 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302006 sap_config->acs_cfg.pcl_channels,
2007 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302008 sap_config->acs_cfg.pcl_channels_weight_list,
2009 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302010 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002011 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302014 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2015 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002016 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 vht_enabled = 1;
2018 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2019 sap_config->acs_cfg.ch_width =
2020 hdd_ctx->config->vhtChannelWidth;
2021 /* No VHT80 in 2.4G so perform ACS accordingly */
2022 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302023 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302025 ch_width = 40;
2026 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002027 }
2028
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302029 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2030
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002031 hdd_debug("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 -08002032 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2033 ch_width, ht_enabled, vht_enabled,
2034 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2035
Kapil Gupta8878ad92017-02-13 11:56:04 +05302036 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2037 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002040 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 sap_config->acs_cfg.ch_list_count);
2042 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002043 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044 }
2045 sap_config->acs_cfg.acs_mode = true;
2046 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002047 /* ***Note*** Completion variable usage is not allowed
2048 * here since ACS scan operation may take max 2.2 sec
2049 * for 5G band:
2050 * 9 Active channel X 40 ms active scan time +
2051 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2053 * for this long. So we split up the scanning part.
2054 */
2055 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002056 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002057 status = 0;
2058 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302059 /* Check if vendor specific acs is enabled */
2060 if (hdd_ctx->config->vendor_acs_support) {
2061 sap_config->acs_cfg.hw_mode = hw_mode;
2062 hdd_create_acs_timer(adapter);
2063 hdd_update_acs_timer_reason(adapter,
2064 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2065 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2066 wlan_sap_set_vendor_acs(
2067 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2068 true);
2069 else
2070 wlan_sap_set_vendor_acs(
2071 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2072 false);
2073
2074 } else
2075 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 }
2077
2078out:
2079 if (0 == status) {
2080 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2081 NLMSG_HDRLEN);
2082 if (temp_skbuff != NULL)
2083 return cfg80211_vendor_cmd_reply(temp_skbuff);
2084 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002085 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2087
2088 return status;
2089}
2090
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002091/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2093 * @wiphy: Linux wiphy struct pointer
2094 * @wdev: Linux wireless device struct pointer
2095 * @data: ACS information from hostapd
2096 * @data_len: ACS information len
2097 *
2098 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2099 * and starts ACS procedure.
2100 *
2101 * Return: ACS procedure start status
2102 */
2103
2104static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2105 struct wireless_dev *wdev,
2106 const void *data, int data_len)
2107{
2108 int ret;
2109
2110 cds_ssr_protect(__func__);
2111 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2112 cds_ssr_unprotect(__func__);
2113
2114 return ret;
2115}
2116
2117/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002118 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2119 * @adapter: Pointer to adapter struct
2120 *
2121 * This function handle cleanup of what was done in DO_ACS, including free
2122 * memory.
2123 *
2124 * Return: void
2125 */
2126
2127void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2128{
2129 if (adapter == NULL)
2130 return;
2131 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2132 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2133 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2134 }
2135}
2136
2137/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002138 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2139 * @work: Linux workqueue struct pointer for ACS work
2140 *
2141 * This function starts the ACS procedure which was marked pending when an ACS
2142 * procedure was in progress for a concurrent SAP interface.
2143 *
2144 * Return: None
2145 */
2146
2147static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2148{
2149 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2150 acs_pending_work.work);
2151 wlan_hdd_cfg80211_start_acs(adapter);
2152}
2153
2154/**
2155 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2156 * @adapter: Pointer to SAP adapter struct
2157 * @pri_channel: SAP ACS procedure selected Primary channel
2158 * @sec_channel: SAP ACS procedure selected secondary channel
2159 *
2160 * This is a callback function from SAP module on ACS procedure is completed.
2161 * This function send the ACS selected channel information to hostapd
2162 *
2163 * Return: None
2164 */
2165
2166void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2167{
2168 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2169 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2170 struct sk_buff *vendor_event;
2171 int ret_val;
2172 hdd_adapter_t *con_sap_adapter;
2173 uint16_t ch_width;
2174
2175 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002176 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2178 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2179 GFP_KERNEL);
2180
2181 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002182 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 return;
2184 }
2185
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 ret_val = nla_put_u8(vendor_event,
2187 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2188 sap_cfg->acs_cfg.pri_ch);
2189 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002190 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 kfree_skb(vendor_event);
2192 return;
2193 }
2194
2195 ret_val = nla_put_u8(vendor_event,
2196 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2197 sap_cfg->acs_cfg.ht_sec_ch);
2198 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002199 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200 kfree_skb(vendor_event);
2201 return;
2202 }
2203
2204 ret_val = nla_put_u8(vendor_event,
2205 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2206 sap_cfg->acs_cfg.vht_seg0_center_ch);
2207 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002208 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209 kfree_skb(vendor_event);
2210 return;
2211 }
2212
2213 ret_val = nla_put_u8(vendor_event,
2214 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2215 sap_cfg->acs_cfg.vht_seg1_center_ch);
2216 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002217 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 kfree_skb(vendor_event);
2219 return;
2220 }
2221
2222 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2223 ch_width = 80;
2224 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2225 ch_width = 40;
2226 else
2227 ch_width = 20;
2228
2229 ret_val = nla_put_u16(vendor_event,
2230 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2231 ch_width);
2232 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002233 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 kfree_skb(vendor_event);
2235 return;
2236 }
2237 if (sap_cfg->acs_cfg.pri_ch > 14)
2238 ret_val = nla_put_u8(vendor_event,
2239 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2240 QCA_ACS_MODE_IEEE80211A);
2241 else
2242 ret_val = nla_put_u8(vendor_event,
2243 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2244 QCA_ACS_MODE_IEEE80211G);
2245
2246 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002247 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002248 kfree_skb(vendor_event);
2249 return;
2250 }
2251
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002252 hdd_debug("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 -08002253 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2254 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2255 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2256
2257 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2258 /* ***Note*** As already mentioned Completion variable usage is not
2259 * allowed here since ACS scan operation may take max 2.2 sec.
2260 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2261 * operation.
2262 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2263 * when Primary AP ACS is complete and secondary AP ACS is started here
2264 * immediately, Primary AP start_bss may come inbetween ACS operation
2265 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2266 * delay. This path and below constraint will be removed on sessionizing
2267 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2268 * As per design constraint user space control application must take
2269 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2270 * this code path. Sec AP hostapd should be started after Primary AP
2271 * start beaconing which can be confirmed by getchannel iwpriv command
2272 */
2273
2274 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2275 if (con_sap_adapter &&
2276 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2278 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 /* Lets give 500ms for OBSS + START_BSS to complete */
2280 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2281 msecs_to_jiffies(500));
2282 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2283 }
2284
2285 return;
2286}
2287
2288static int
2289__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2290 struct wireless_dev *wdev,
2291 const void *data,
2292 int data_len)
2293{
2294 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2295 struct sk_buff *skb = NULL;
2296 uint32_t fset = 0;
2297 int ret;
2298
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002299 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302300
Anurag Chouhan6d760662016-02-20 16:05:43 +05302301 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 hdd_err("Command not allowed in FTM mode");
2303 return -EPERM;
2304 }
2305
2306 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302307 if (ret)
2308 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309
2310 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002311 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 fset |= WIFI_FEATURE_INFRA;
2313 }
2314 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002315 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316 fset |= WIFI_FEATURE_INFRA_5G;
2317 }
2318#ifdef WLAN_FEATURE_P2P
2319 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2320 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002321 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002322 fset |= WIFI_FEATURE_P2P;
2323 }
2324#endif
2325 fset |= WIFI_FEATURE_SOFT_AP;
2326
2327 /* HOTSPOT is a supplicant feature, enable it by default */
2328 fset |= WIFI_FEATURE_HOTSPOT;
2329
2330#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302331 if (pHddCtx->config->extscan_enabled &&
2332 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002333 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002334 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2335 }
2336#endif
2337 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002338 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 fset |= WIFI_FEATURE_NAN;
2340 }
2341 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002342 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 fset |= WIFI_FEATURE_D2D_RTT;
2344 fset |= WIFI_FEATURE_D2AP_RTT;
2345 }
2346#ifdef FEATURE_WLAN_SCAN_PNO
2347 if (pHddCtx->config->configPNOScanSupport &&
2348 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002349 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 fset |= WIFI_FEATURE_PNO;
2351 }
2352#endif
2353 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2354#ifdef FEATURE_WLAN_TDLS
2355 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2356 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002357 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002358 fset |= WIFI_FEATURE_TDLS;
2359 }
2360 if (sme_is_feature_supported_by_fw(TDLS) &&
2361 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2362 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002363 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2365 }
2366#endif
2367#ifdef WLAN_AP_STA_CONCURRENCY
2368 fset |= WIFI_FEATURE_AP_STA;
2369#endif
2370 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002371 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372
2373 if (hdd_link_layer_stats_supported())
2374 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2375
2376 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2377 NLMSG_HDRLEN);
2378 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002379 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 return -EINVAL;
2381 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002382 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002384 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 goto nla_put_failure;
2386 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302387 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302388 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389nla_put_failure:
2390 kfree_skb(skb);
2391 return -EINVAL;
2392}
2393
2394/**
2395 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2396 * @wiphy: pointer to wireless wiphy structure.
2397 * @wdev: pointer to wireless_dev structure.
2398 * @data: Pointer to the data to be passed via vendor interface
2399 * @data_len:Length of the data to be passed
2400 *
2401 * Return: Return the Success or Failure code.
2402 */
2403static int
2404wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2405 struct wireless_dev *wdev,
2406 const void *data, int data_len)
2407{
2408 int ret = 0;
2409
2410 cds_ssr_protect(__func__);
2411 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2412 data, data_len);
2413 cds_ssr_unprotect(__func__);
2414
2415 return ret;
2416}
2417
2418/**
2419 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2420 * @wiphy: pointer to wireless wiphy structure.
2421 * @wdev: pointer to wireless_dev structure.
2422 * @data: Pointer to the data to be passed via vendor interface
2423 * @data_len:Length of the data to be passed
2424 *
2425 * Set the MAC address that is to be used for scanning.
2426 *
2427 * Return: Return the Success or Failure code.
2428 */
2429static int
2430__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2431 struct wireless_dev *wdev,
2432 const void *data,
2433 int data_len)
2434{
2435 tpSirScanMacOui pReqMsg = NULL;
2436 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2437 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302438 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 int ret;
2440
Jeff Johnson1f61b612016-02-12 16:28:33 -08002441 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442
Anurag Chouhan6d760662016-02-20 16:05:43 +05302443 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 hdd_err("Command not allowed in FTM mode");
2445 return -EPERM;
2446 }
2447
2448 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302449 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451
2452 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 return -ENOTSUPP;
2455 }
2456
2457 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2458 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002459 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 return -EINVAL;
2461 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302462 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002464 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 return -ENOMEM;
2466 }
2467 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002468 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 goto fail;
2470 }
2471 nla_memcpy(&pReqMsg->oui[0],
2472 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2473 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002474 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 pReqMsg->oui[1], pReqMsg->oui[2]);
2476 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302477 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002478 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 goto fail;
2480 }
2481 return 0;
2482fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302483 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 return -EINVAL;
2485}
2486
2487/**
2488 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2489 * @wiphy: pointer to wireless wiphy structure.
2490 * @wdev: pointer to wireless_dev structure.
2491 * @data: Pointer to the data to be passed via vendor interface
2492 * @data_len:Length of the data to be passed
2493 *
2494 * Set the MAC address that is to be used for scanning. This is an
2495 * SSR-protecting wrapper function.
2496 *
2497 * Return: Return the Success or Failure code.
2498 */
2499static int
2500wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2501 struct wireless_dev *wdev,
2502 const void *data,
2503 int data_len)
2504{
2505 int ret;
2506
2507 cds_ssr_protect(__func__);
2508 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2509 data, data_len);
2510 cds_ssr_unprotect(__func__);
2511
2512 return ret;
2513}
2514
2515/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302516 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2517 * @wiphy: pointer phy adapter
2518 * @wdev: pointer to wireless device structure
2519 * @data: pointer to data buffer
2520 * @data_len: length of data
2521 *
2522 * This routine will give concurrency matrix
2523 *
2524 * Return: int status code
2525 */
2526static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2527 struct wireless_dev *wdev,
2528 const void *data,
2529 int data_len)
2530{
2531 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2532 uint8_t i, feature_sets, max_feature_sets;
2533 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2534 struct sk_buff *reply_skb;
2535 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2536 int ret;
2537
2538 ENTER_DEV(wdev->netdev);
2539
2540 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2541 hdd_err("Command not allowed in FTM mode");
2542 return -EPERM;
2543 }
2544
2545 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302546 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302547 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302548
2549 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2550 data, data_len, NULL)) {
2551 hdd_err("Invalid ATTR");
2552 return -EINVAL;
2553 }
2554
2555 /* Parse and fetch max feature set */
2556 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2557 hdd_err("Attr max feature set size failed");
2558 return -EINVAL;
2559 }
2560 max_feature_sets = nla_get_u32(tb[
2561 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002562 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302563
2564 /* Fill feature combination matrix */
2565 feature_sets = 0;
2566 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002567 WIFI_FEATURE_P2P;
2568 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2569 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302570 /* Add more feature combinations here */
2571
2572 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002573 hdd_debug("Number of feature sets: %d", feature_sets);
2574 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302575 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002576 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302577
2578 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2579 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2580 if (!reply_skb) {
2581 hdd_err("Feature set matrix: buffer alloc fail");
2582 return -ENOMEM;
2583 }
2584
2585 if (nla_put_u32(reply_skb,
2586 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2587 feature_sets) ||
2588 nla_put(reply_skb,
2589 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2590 sizeof(u32) * feature_sets,
2591 feature_set_matrix)) {
2592 hdd_err("nla put fail");
2593 kfree_skb(reply_skb);
2594 return -EINVAL;
2595 }
2596 return cfg80211_vendor_cmd_reply(reply_skb);
2597}
2598
2599/**
2600 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2601 * @wiphy: pointer to wireless wiphy structure.
2602 * @wdev: pointer to wireless_dev structure.
2603 * @data: Pointer to the data to be passed via vendor interface
2604 * @data_len:Length of the data to be passed
2605 *
2606 * Retrieves the concurrency feature set matrix
2607 *
2608 * Return: 0 on success, negative errno on failure
2609 */
2610static int
2611wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2612 struct wireless_dev *wdev,
2613 const void *data,
2614 int data_len)
2615{
2616 int ret;
2617
2618 cds_ssr_protect(__func__);
2619 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2620 data, data_len);
2621 cds_ssr_unprotect(__func__);
2622
2623 return ret;
2624}
2625
2626/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002627 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2628 * @feature_flags: pointer to the byte array of features.
2629 * @feature: Feature to be turned ON in the byte array.
2630 *
2631 * Return: None
2632 *
2633 * This is called to turn ON or SET the feature flag for the requested feature.
2634 **/
2635#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002636static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2637 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638{
2639 uint32_t index;
2640 uint8_t bit_mask;
2641
2642 index = feature / NUM_BITS_IN_BYTE;
2643 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2644 feature_flags[index] |= bit_mask;
2645}
2646
2647/**
2648 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2649 * @wiphy: pointer to wireless wiphy structure.
2650 * @wdev: pointer to wireless_dev structure.
2651 * @data: Pointer to the data to be passed via vendor interface
2652 * @data_len:Length of the data to be passed
2653 *
2654 * This is called when wlan driver needs to send supported feature set to
2655 * supplicant upon a request/query from the supplicant.
2656 *
2657 * Return: Return the Success or Failure code.
2658 **/
2659#define MAX_CONCURRENT_CHAN_ON_24G 2
2660#define MAX_CONCURRENT_CHAN_ON_5G 2
2661static int
2662__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2663 struct wireless_dev *wdev,
2664 const void *data, int data_len)
2665{
2666 struct sk_buff *skb = NULL;
2667 uint32_t dbs_capability = 0;
2668 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302669 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 int ret_val;
2671
2672 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2673 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2674
Jeff Johnson1f61b612016-02-12 16:28:33 -08002675 ENTER_DEV(wdev->netdev);
2676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2678 if (ret_val)
2679 return ret_val;
2680
Anurag Chouhan6d760662016-02-20 16:05:43 +05302681 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 hdd_err("Command not allowed in FTM mode");
2683 return -EPERM;
2684 }
2685
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002686 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002687 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 wlan_hdd_cfg80211_set_feature(feature_flags,
2689 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2690 }
2691
2692 wlan_hdd_cfg80211_set_feature(feature_flags,
2693 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002694 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 wlan_hdd_cfg80211_set_feature(feature_flags,
2696 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002697
2698 if (wma_is_p2p_lo_capable())
2699 wlan_hdd_cfg80211_set_feature(feature_flags,
2700 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2701
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2703 NLMSG_HDRLEN);
2704
2705 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002706 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002707 return -ENOMEM;
2708 }
2709
2710 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2711 sizeof(feature_flags), feature_flags))
2712 goto nla_put_failure;
2713
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002714 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2715 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302716 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717 if (one_by_one_dbs)
2718 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2719
2720 if (two_by_two_dbs)
2721 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2722
2723 if (!one_by_one_dbs && !two_by_two_dbs)
2724 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2725 } else {
2726 hdd_err("wma_get_dbs_hw_mode failed");
2727 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2728 }
2729
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002730 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731
2732 if (nla_put_u32(skb,
2733 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2734 MAX_CONCURRENT_CHAN_ON_24G))
2735 goto nla_put_failure;
2736
2737 if (nla_put_u32(skb,
2738 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2739 MAX_CONCURRENT_CHAN_ON_5G))
2740 goto nla_put_failure;
2741
2742 return cfg80211_vendor_cmd_reply(skb);
2743
2744nla_put_failure:
2745 kfree_skb(skb);
2746 return -EINVAL;
2747}
2748
2749/**
2750 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2751 * @wiphy: pointer to wireless wiphy structure.
2752 * @wdev: pointer to wireless_dev structure.
2753 * @data: Pointer to the data to be passed via vendor interface
2754 * @data_len:Length of the data to be passed
2755 *
2756 * This is called when wlan driver needs to send supported feature set to
2757 * supplicant upon a request/query from the supplicant.
2758 *
2759 * Return: Return the Success or Failure code.
2760 */
2761static int
2762wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2763 struct wireless_dev *wdev,
2764 const void *data, int data_len)
2765{
2766 int ret;
2767
2768 cds_ssr_protect(__func__);
2769 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2770 data, data_len);
2771 cds_ssr_unprotect(__func__);
2772
2773 return ret;
2774}
2775
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302776#define PARAM_NUM_NW \
2777 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2778#define PARAM_SET_BSSID \
2779 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2780#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2781#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782
2783/**
2784 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2785 * @wiphy: The wiphy structure
2786 * @wdev: The wireless device
2787 * @data: Data passed by framework
2788 * @data_len: Parameters to be configured passed as data
2789 *
2790 * The roaming related parameters are configured by the framework
2791 * using this interface.
2792 *
2793 * Return: Return either success or failure code.
2794 */
2795static int
2796__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2797 struct wireless_dev *wdev, const void *data, int data_len)
2798{
2799 struct net_device *dev = wdev->netdev;
2800 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2801 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2802 uint8_t session_id;
2803 struct roam_ext_params roam_params;
2804 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302805 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2807 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2808 int rem, i;
2809 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002810 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 int ret;
2812
Jeff Johnson1f61b612016-02-12 16:28:33 -08002813 ENTER_DEV(dev);
2814
Anurag Chouhan6d760662016-02-20 16:05:43 +05302815 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 hdd_err("Command not allowed in FTM mode");
2817 return -EPERM;
2818 }
2819
2820 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302821 if (ret)
2822 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823
2824 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2825 data, data_len,
2826 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002827 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 return -EINVAL;
2829 }
2830 /* Parse and fetch Command Type*/
2831 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002832 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833 goto fail;
2834 }
2835 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302836 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2838 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002839 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 goto fail;
2841 }
2842 req_id = nla_get_u32(
2843 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002844 hdd_debug("Req Id (%d)", req_id);
2845 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 switch (cmd_type) {
2847 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2848 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302849 if (tb[PARAM_NUM_NW]) {
2850 count = nla_get_u32(
2851 tb[PARAM_NUM_NW]);
2852 } else {
2853 hdd_err("Number of networks is not provided");
2854 goto fail;
2855 }
2856
2857 if (count &&
2858 tb[PRAM_SSID_LIST]) {
2859 nla_for_each_nested(curr_attr,
2860 tb[PRAM_SSID_LIST], rem) {
2861 if (nla_parse(tb2,
2862 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2863 nla_data(curr_attr), nla_len(curr_attr),
2864 NULL)) {
2865 hdd_err("nla_parse failed");
2866 goto fail;
2867 }
2868 /* Parse and Fetch allowed SSID list*/
2869 if (!tb2[PARAM_LIST_SSID]) {
2870 hdd_err("attr allowed ssid failed");
2871 goto fail;
2872 }
2873 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2874 /*
2875 * Upper Layers include a null termination
2876 * character. Check for the actual permissible
2877 * length of SSID and also ensure not to copy
2878 * the NULL termination character to the driver
2879 * buffer.
2880 */
2881 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2882 ((buf_len - 1) <=
2883 SIR_MAC_MAX_SSID_LENGTH)) {
2884 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302886 tb2[PARAM_LIST_SSID], buf_len - 1);
2887 roam_params.ssid_allowed_list[i].length
2888 = buf_len - 1;
2889 hdd_debug("SSID[%d]: %.*s,length = %d",
2890 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 roam_params.ssid_allowed_list[i].length,
2892 roam_params.ssid_allowed_list[i].ssId,
2893 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302894 i++;
2895 } else {
2896 hdd_err("Invalid buffer length");
2897 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 }
2899 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302900 if (i != count) {
2901 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2902 i, count);
2903 goto fail;
2904 }
2905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002907 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 roam_params.num_ssid_allowed_list);
2909 sme_update_roam_params(pHddCtx->hHal, session_id,
2910 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2911 break;
2912 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2913 /* Parse and fetch 5G Boost Threshold */
2914 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002915 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 goto fail;
2917 }
2918 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2919 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002920 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 roam_params.raise_rssi_thresh_5g);
2922 /* Parse and fetch 5G Penalty Threshold */
2923 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002924 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 goto fail;
2926 }
2927 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2928 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002929 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930 roam_params.drop_rssi_thresh_5g);
2931 /* Parse and fetch 5G Boost Factor */
2932 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002933 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 goto fail;
2935 }
2936 roam_params.raise_factor_5g = nla_get_u32(
2937 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002938 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002939 roam_params.raise_factor_5g);
2940 /* Parse and fetch 5G Penalty factor */
2941 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002942 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 goto fail;
2944 }
2945 roam_params.drop_factor_5g = nla_get_u32(
2946 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002947 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 roam_params.drop_factor_5g);
2949 /* Parse and fetch 5G Max Boost */
2950 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 goto fail;
2953 }
2954 roam_params.max_raise_rssi_5g = nla_get_u32(
2955 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002956 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 roam_params.max_raise_rssi_5g);
2958 /* Parse and fetch Rssi Diff */
2959 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002960 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 goto fail;
2962 }
2963 roam_params.rssi_diff = nla_get_s32(
2964 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002965 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966 roam_params.rssi_diff);
2967 /* Parse and fetch Alert Rssi Threshold */
2968 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002969 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002970 goto fail;
2971 }
2972 roam_params.alert_rssi_threshold = nla_get_u32(
2973 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002974 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 roam_params.alert_rssi_threshold);
2976 sme_update_roam_params(pHddCtx->hHal, session_id,
2977 roam_params,
2978 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2979 break;
2980 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2981 /* Parse and fetch Activate Good Rssi Roam */
2982 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002983 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 goto fail;
2985 }
2986 roam_params.good_rssi_roam = nla_get_s32(
2987 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002988 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 roam_params.good_rssi_roam);
2990 sme_update_roam_params(pHddCtx->hHal, session_id,
2991 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2992 break;
2993 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2994 /* Parse and fetch number of preferred BSSID */
2995 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002996 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997 goto fail;
2998 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002999 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003001 if (count > MAX_BSSID_FAVORED) {
3002 hdd_err("Preferred BSSID count %u exceeds max %u",
3003 count, MAX_BSSID_FAVORED);
3004 goto fail;
3005 }
3006 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 i = 0;
3008 nla_for_each_nested(curr_attr,
3009 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3010 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003011
3012 if (i == count) {
3013 hdd_warn("Ignoring excess Preferred BSSID");
3014 break;
3015 }
3016
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 if (nla_parse(tb2,
3018 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3019 nla_data(curr_attr), nla_len(curr_attr),
3020 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003021 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022 goto fail;
3023 }
3024 /* Parse and fetch MAC address */
3025 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003026 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 goto fail;
3028 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003029 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303031 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003032 hdd_debug(MAC_ADDRESS_STR,
3033 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 /* Parse and fetch preference factor*/
3035 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003036 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 goto fail;
3038 }
3039 roam_params.bssid_favored_factor[i] = nla_get_u32(
3040 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003041 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 roam_params.bssid_favored_factor[i]);
3043 i++;
3044 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003045 if (i < count)
3046 hdd_warn("Num Preferred BSSID %u less than expected %u",
3047 i, count);
3048 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 sme_update_roam_params(pHddCtx->hHal, session_id,
3050 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3051 break;
3052 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3053 /* Parse and fetch number of blacklist BSSID */
3054 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003055 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 goto fail;
3057 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003058 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003060 if (count > MAX_BSSID_AVOID_LIST) {
3061 hdd_err("Blacklist BSSID count %u exceeds max %u",
3062 count, MAX_BSSID_AVOID_LIST);
3063 goto fail;
3064 }
3065 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303067
3068 if (count &&
3069 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3070 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003071 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3072 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003073
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303074 if (i == count) {
3075 hdd_warn("Ignoring excess Blacklist BSSID");
3076 break;
3077 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003078
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303079 if (nla_parse(tb2,
3080 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3081 nla_data(curr_attr), nla_len(curr_attr),
3082 NULL)) {
3083 hdd_err("nla_parse failed");
3084 goto fail;
3085 }
3086 /* Parse and fetch MAC address */
3087 if (!tb2[PARAM_SET_BSSID]) {
3088 hdd_err("attr blacklist addr failed");
3089 goto fail;
3090 }
3091 nla_memcpy(
3092 roam_params.bssid_avoid_list[i].bytes,
3093 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3094 hdd_debug(MAC_ADDRESS_STR,
3095 MAC_ADDR_ARRAY(
3096 roam_params.bssid_avoid_list[i].bytes));
3097 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003100 if (i < count)
3101 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3102 i, count);
3103 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 sme_update_roam_params(pHddCtx->hHal, session_id,
3105 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3106 break;
3107 }
3108 return 0;
3109fail:
3110 return -EINVAL;
3111}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303112#undef PARAM_NUM_NW
3113#undef PARAM_SET_BSSID
3114#undef PRAM_SSID_LIST
3115#undef PARAM_LIST_SSID
3116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003117
3118/**
3119 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3120 * @wiphy: pointer to wireless wiphy structure.
3121 * @wdev: pointer to wireless_dev structure.
3122 * @data: Pointer to the data to be passed via vendor interface
3123 * @data_len:Length of the data to be passed
3124 *
3125 * Return: Return the Success or Failure code.
3126 */
3127static int
3128wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3129 struct wireless_dev *wdev,
3130 const void *data,
3131 int data_len)
3132{
3133 int ret;
3134
3135 cds_ssr_protect(__func__);
3136 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3137 data, data_len);
3138 cds_ssr_unprotect(__func__);
3139
3140 return ret;
3141}
3142
3143static const struct nla_policy
3144wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3145 +1] = {
3146 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3147};
3148
3149/**
3150 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3151 * @hdd_ctx: HDD context
3152 * @device_mode: device mode
3153 * Return: bool
3154 */
3155static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003156 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157{
3158 hdd_adapter_t *adapter;
3159 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3160 hdd_ap_ctx_t *ap_ctx;
3161 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303162 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303164 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303167 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 adapter = adapter_node->pAdapter;
3169
3170 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003171 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 ap_ctx =
3173 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3174
3175 /*
3176 * if there is SAP already running on DFS channel,
3177 * do not disable scan on dfs channels. Note that
3178 * with SAP on DFS, there cannot be conurrency on
3179 * single radio. But then we can have multiple
3180 * radios !!
3181 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003182 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3183 hdd_ctx->hdd_pdev,
3184 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003185 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 return true;
3187 }
3188 }
3189
3190 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003191 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 sta_ctx =
3193 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3194
3195 /*
3196 * if STA is already connected on DFS channel,
3197 * do not disable scan on dfs channels
3198 */
3199 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003200 (CHANNEL_STATE_DFS ==
3201 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3202 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003203 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204 return true;
3205 }
3206 }
3207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303208 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209 adapter_node,
3210 &next);
3211 adapter_node = next;
3212 }
3213
3214 return false;
3215}
3216
3217/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003218 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3219 * @hdd_ctx: HDD context within host driver
3220 * @adapter: Adapter pointer
3221 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3222 *
3223 * Loops through devices to see who is operating on DFS channels
3224 * and then disables/enables DFS channels by calling SME API.
3225 * Fails the disable request if any device is active on a DFS channel.
3226 *
3227 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003229
3230int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3231 hdd_adapter_t *adapter,
3232 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303235 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237
3238 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3239 if (no_dfs_flag) {
3240 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003241 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242
3243 if (true == status)
3244 return -EOPNOTSUPP;
3245
3246 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003247 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248
3249 if (true == status)
3250 return -EOPNOTSUPP;
3251 }
3252
3253 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3254
3255 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3256
3257 /*
3258 * call the SME API to tunnel down the new channel list
3259 * to the firmware
3260 */
3261 status = sme_handle_dfs_chan_scan(
3262 h_hal, hdd_ctx->config->enableDFSChnlScan);
3263
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303264 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265 ret_val = 0;
3266
3267 /*
3268 * Clear the SME scan cache also. Note that the
3269 * clearing of scan results is independent of session;
3270 * so no need to iterate over
3271 * all sessions
3272 */
3273 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303274 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003275 ret_val = -EPERM;
3276 }
3277
3278 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003279 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 ret_val = 0;
3281 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003282 return ret_val;
3283}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003285/**
3286 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3287 * @wiphy: corestack handler
3288 * @wdev: wireless device
3289 * @data: data
3290 * @data_len: data length
3291 * Return: success(0) or reason code for failure
3292 */
3293static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3294 struct wireless_dev *wdev,
3295 const void *data,
3296 int data_len)
3297{
3298 struct net_device *dev = wdev->netdev;
3299 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3300 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3301 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3302 int ret_val;
3303 uint32_t no_dfs_flag = 0;
3304
Jeff Johnson1f61b612016-02-12 16:28:33 -08003305 ENTER_DEV(dev);
3306
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003307 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303308 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003309 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003310
3311 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3312 data, data_len,
3313 wlan_hdd_set_no_dfs_flag_config_policy)) {
3314 hdd_err("invalid attr");
3315 return -EINVAL;
3316 }
3317
3318 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3319 hdd_err("attr dfs flag failed");
3320 return -EINVAL;
3321 }
3322
3323 no_dfs_flag = nla_get_u32(
3324 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3325
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003326 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003327
3328 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003329 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003330 return -EINVAL;
3331 }
3332
3333 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3334 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335 return ret_val;
3336}
3337
3338/**
3339 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3340 *
3341 * @wiphy: wiphy device pointer
3342 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003343 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344 * @data_len: Buffer length
3345 *
3346 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3347 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3348 *
3349 * Return: EOK or other error codes.
3350 */
3351
3352static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3353 struct wireless_dev *wdev,
3354 const void *data,
3355 int data_len)
3356{
3357 int ret;
3358
3359 cds_ssr_protect(__func__);
3360 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3361 data, data_len);
3362 cds_ssr_unprotect(__func__);
3363
3364 return ret;
3365}
3366
Manikandan Mohan80dea792016-04-28 16:36:48 -07003367static const struct nla_policy
3368wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3369 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3370};
3371
3372/**
3373 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3374 * @wiphy: wiphy device pointer
3375 * @wdev: wireless device pointer
3376 * @data: Vendor command data buffer
3377 * @data_len: Buffer length
3378 *
3379 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3380 * setup WISA Mode features.
3381 *
3382 * Return: Success(0) or reason code for failure
3383 */
3384static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3385 struct wireless_dev *wdev, const void *data, int data_len)
3386{
3387 struct net_device *dev = wdev->netdev;
3388 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3389 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3390 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3391 struct sir_wisa_params wisa;
3392 int ret_val;
3393 QDF_STATUS status;
3394 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003395 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3396 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003397
3398 ENTER_DEV(dev);
3399 ret_val = wlan_hdd_validate_context(hdd_ctx);
3400 if (ret_val)
3401 goto err;
3402
3403 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3404 hdd_err("Command not allowed in FTM mode");
3405 return -EPERM;
3406 }
3407
3408 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3409 wlan_hdd_wisa_cmd_policy)) {
3410 hdd_err("Invalid WISA cmd attributes");
3411 ret_val = -EINVAL;
3412 goto err;
3413 }
3414 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3415 hdd_err("Invalid WISA mode");
3416 ret_val = -EINVAL;
3417 goto err;
3418 }
3419
3420 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003421 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003422 wisa.mode = wisa_mode;
3423 wisa.vdev_id = adapter->sessionId;
3424 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003425 if (!QDF_IS_STATUS_SUCCESS(status)) {
3426 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003427 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003428 }
3429 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003430 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003431 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3432 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003433 adapter->sessionId),
3434 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003435err:
3436 EXIT();
3437 return ret_val;
3438}
3439
3440/**
3441 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3442 * @wiphy: corestack handler
3443 * @wdev: wireless device
3444 * @data: data
3445 * @data_len: data length
3446 *
3447 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3448 * setup WISA mode features.
3449 *
3450 * Return: Success(0) or reason code for failure
3451 */
3452static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3453 struct wireless_dev *wdev,
3454 const void *data,
3455 int data_len)
3456{
3457 int ret;
3458
3459 cds_ssr_protect(__func__);
3460 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3461 cds_ssr_unprotect(__func__);
3462
3463 return ret;
3464}
3465
Anurag Chouhan96919482016-07-13 16:36:57 +05303466/*
3467 * define short names for the global vendor params
3468 * used by __wlan_hdd_cfg80211_get_station_cmd()
3469 */
3470#define STATION_INVALID \
3471 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3472#define STATION_INFO \
3473 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3474#define STATION_ASSOC_FAIL_REASON \
3475 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3476#define STATION_MAX \
3477 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3478
3479static const struct nla_policy
3480hdd_get_station_policy[STATION_MAX + 1] = {
3481 [STATION_INFO] = {.type = NLA_FLAG},
3482 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3483};
3484
3485/**
3486 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3487 * @hdd_ctx: HDD context within host driver
3488 * @wdev: wireless device
3489 *
3490 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3491 * Validate cmd attributes and send the station info to upper layers.
3492 *
3493 * Return: Success(0) or reason code for failure
3494 */
3495static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3496 hdd_adapter_t *adapter)
3497{
3498 struct sk_buff *skb = NULL;
3499 uint32_t nl_buf_len;
3500 hdd_station_ctx_t *hdd_sta_ctx;
3501
3502 nl_buf_len = NLMSG_HDRLEN;
3503 nl_buf_len += sizeof(uint32_t);
3504 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3505
3506 if (!skb) {
3507 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3508 return -ENOMEM;
3509 }
3510
3511 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3512
3513 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3514 hdd_sta_ctx->conn_info.assoc_status_code)) {
3515 hdd_err("put fail");
3516 goto fail;
3517 }
3518 return cfg80211_vendor_cmd_reply(skb);
3519fail:
3520 if (skb)
3521 kfree_skb(skb);
3522 return -EINVAL;
3523}
3524
3525/**
3526 * hdd_map_auth_type() - transform auth type specific to
3527 * vendor command
3528 * @auth_type: csr auth type
3529 *
3530 * Return: Success(0) or reason code for failure
3531 */
3532static int hdd_convert_auth_type(uint32_t auth_type)
3533{
3534 uint32_t ret_val;
3535
3536 switch (auth_type) {
3537 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3538 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3539 break;
3540 case eCSR_AUTH_TYPE_SHARED_KEY:
3541 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3542 break;
3543 case eCSR_AUTH_TYPE_WPA:
3544 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3545 break;
3546 case eCSR_AUTH_TYPE_WPA_PSK:
3547 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3548 break;
3549 case eCSR_AUTH_TYPE_AUTOSWITCH:
3550 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3551 break;
3552 case eCSR_AUTH_TYPE_WPA_NONE:
3553 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3554 break;
3555 case eCSR_AUTH_TYPE_RSN:
3556 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3557 break;
3558 case eCSR_AUTH_TYPE_RSN_PSK:
3559 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3560 break;
3561 case eCSR_AUTH_TYPE_FT_RSN:
3562 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3563 break;
3564 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3565 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3566 break;
3567 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3568 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3569 break;
3570 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3571 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3572 break;
3573 case eCSR_AUTH_TYPE_CCKM_WPA:
3574 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3575 break;
3576 case eCSR_AUTH_TYPE_CCKM_RSN:
3577 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3578 break;
3579 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3580 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3581 break;
3582 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3583 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3584 break;
3585 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3586 case eCSR_AUTH_TYPE_FAILED:
3587 case eCSR_AUTH_TYPE_NONE:
3588 default:
3589 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3590 break;
3591 }
3592 return ret_val;
3593}
3594
3595/**
3596 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3597 * vendor command
3598 * @dot11mode: dot11mode
3599 *
3600 * Return: Success(0) or reason code for failure
3601 */
3602static int hdd_convert_dot11mode(uint32_t dot11mode)
3603{
3604 uint32_t ret_val;
3605
3606 switch (dot11mode) {
3607 case eCSR_CFG_DOT11_MODE_11A:
3608 ret_val = QCA_WLAN_802_11_MODE_11A;
3609 break;
3610 case eCSR_CFG_DOT11_MODE_11B:
3611 ret_val = QCA_WLAN_802_11_MODE_11B;
3612 break;
3613 case eCSR_CFG_DOT11_MODE_11G:
3614 ret_val = QCA_WLAN_802_11_MODE_11G;
3615 break;
3616 case eCSR_CFG_DOT11_MODE_11N:
3617 ret_val = QCA_WLAN_802_11_MODE_11N;
3618 break;
3619 case eCSR_CFG_DOT11_MODE_11AC:
3620 ret_val = QCA_WLAN_802_11_MODE_11AC;
3621 break;
3622 case eCSR_CFG_DOT11_MODE_AUTO:
3623 case eCSR_CFG_DOT11_MODE_ABG:
3624 default:
3625 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3626 }
3627 return ret_val;
3628}
3629
3630/**
3631 * hdd_add_tx_bitrate() - add tx bitrate attribute
3632 * @skb: pointer to sk buff
3633 * @hdd_sta_ctx: pointer to hdd station context
3634 * @idx: attribute index
3635 *
3636 * Return: Success(0) or reason code for failure
3637 */
3638static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3639 hdd_station_ctx_t *hdd_sta_ctx,
3640 int idx)
3641{
3642 struct nlattr *nla_attr;
3643 uint32_t bitrate, bitrate_compat;
3644
3645 nla_attr = nla_nest_start(skb, idx);
3646 if (!nla_attr)
3647 goto fail;
3648 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3649 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3650
3651 /* report 16-bit bitrate only if we can */
3652 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3653 if (bitrate > 0 &&
3654 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3655 hdd_err("put fail");
3656 goto fail;
3657 }
3658 if (bitrate_compat > 0 &&
3659 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3660 hdd_err("put fail");
3661 goto fail;
3662 }
3663 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3664 hdd_sta_ctx->conn_info.txrate.nss)) {
3665 hdd_err("put fail");
3666 goto fail;
3667 }
3668 nla_nest_end(skb, nla_attr);
3669 return 0;
3670fail:
3671 return -EINVAL;
3672}
3673
3674/**
3675 * hdd_add_sta_info() - add station info attribute
3676 * @skb: pointer to sk buff
3677 * @hdd_sta_ctx: pointer to hdd station context
3678 * @idx: attribute index
3679 *
3680 * Return: Success(0) or reason code for failure
3681 */
3682static int32_t hdd_add_sta_info(struct sk_buff *skb,
3683 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3684{
3685 struct nlattr *nla_attr;
3686
3687 nla_attr = nla_nest_start(skb, idx);
3688 if (!nla_attr)
3689 goto fail;
3690 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3691 (hdd_sta_ctx->conn_info.signal + 100))) {
3692 hdd_err("put fail");
3693 goto fail;
3694 }
3695 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3696 goto fail;
3697 nla_nest_end(skb, nla_attr);
3698 return 0;
3699fail:
3700 return -EINVAL;
3701}
3702
3703/**
3704 * hdd_add_survey_info() - add survey info attribute
3705 * @skb: pointer to sk buff
3706 * @hdd_sta_ctx: pointer to hdd station context
3707 * @idx: attribute index
3708 *
3709 * Return: Success(0) or reason code for failure
3710 */
3711static int32_t hdd_add_survey_info(struct sk_buff *skb,
3712 hdd_station_ctx_t *hdd_sta_ctx,
3713 int idx)
3714{
3715 struct nlattr *nla_attr;
3716
3717 nla_attr = nla_nest_start(skb, idx);
3718 if (!nla_attr)
3719 goto fail;
3720 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3721 hdd_sta_ctx->conn_info.freq) ||
3722 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3723 (hdd_sta_ctx->conn_info.noise + 100))) {
3724 hdd_err("put fail");
3725 goto fail;
3726 }
3727 nla_nest_end(skb, nla_attr);
3728 return 0;
3729fail:
3730 return -EINVAL;
3731}
3732
3733/**
3734 * hdd_add_link_standard_info() - add link info attribute
3735 * @skb: pointer to sk buff
3736 * @hdd_sta_ctx: pointer to hdd station context
3737 * @idx: attribute index
3738 *
3739 * Return: Success(0) or reason code for failure
3740 */
3741static int32_t
3742hdd_add_link_standard_info(struct sk_buff *skb,
3743 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3744{
3745 struct nlattr *nla_attr;
3746
3747 nla_attr = nla_nest_start(skb, idx);
3748 if (!nla_attr)
3749 goto fail;
3750 if (nla_put(skb,
3751 NL80211_ATTR_SSID,
3752 hdd_sta_ctx->conn_info.SSID.SSID.length,
3753 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3754 hdd_err("put fail");
3755 goto fail;
3756 }
3757 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3758 goto fail;
3759 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3760 goto fail;
3761 nla_nest_end(skb, nla_attr);
3762 return 0;
3763fail:
3764 return -EINVAL;
3765}
3766
3767/**
3768 * hdd_add_ap_standard_info() - add ap info attribute
3769 * @skb: pointer to sk buff
3770 * @hdd_sta_ctx: pointer to hdd station context
3771 * @idx: attribute index
3772 *
3773 * Return: Success(0) or reason code for failure
3774 */
3775static int32_t
3776hdd_add_ap_standard_info(struct sk_buff *skb,
3777 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3778{
3779 struct nlattr *nla_attr;
3780
3781 nla_attr = nla_nest_start(skb, idx);
3782 if (!nla_attr)
3783 goto fail;
3784 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3785 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3786 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3787 &hdd_sta_ctx->conn_info.vht_caps)) {
3788 hdd_err("put fail");
3789 goto fail;
3790 }
3791 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3792 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3793 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3794 &hdd_sta_ctx->conn_info.ht_caps)) {
3795 hdd_err("put fail");
3796 goto fail;
3797 }
3798 nla_nest_end(skb, nla_attr);
3799 return 0;
3800fail:
3801 return -EINVAL;
3802}
3803
3804/**
3805 * hdd_get_station_info() - send BSS information to supplicant
3806 * @hdd_ctx: pointer to hdd context
3807 * @adapter: pointer to adapter
3808 *
3809 * Return: 0 if success else error status
3810 */
3811static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3812 hdd_adapter_t *adapter)
3813{
3814 struct sk_buff *skb = NULL;
3815 uint8_t *tmp_hs20 = NULL;
3816 uint32_t nl_buf_len;
3817 hdd_station_ctx_t *hdd_sta_ctx;
3818
3819 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3820
3821 nl_buf_len = NLMSG_HDRLEN;
3822 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3823 sizeof(hdd_sta_ctx->conn_info.freq) +
3824 sizeof(hdd_sta_ctx->conn_info.noise) +
3825 sizeof(hdd_sta_ctx->conn_info.signal) +
3826 (sizeof(uint32_t) * 2) +
3827 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3828 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3829 sizeof(hdd_sta_ctx->conn_info.authType) +
3830 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3831 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3832 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3833 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3834 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3835 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3836 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3837 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3838 1);
3839 }
3840 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3841 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3842 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3843 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3844
3845
3846 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3847 if (!skb) {
3848 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3849 return -ENOMEM;
3850 }
3851
3852 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3853 LINK_INFO_STANDARD_NL80211_ATTR)) {
3854 hdd_err("put fail");
3855 goto fail;
3856 }
3857 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3858 AP_INFO_STANDARD_NL80211_ATTR)) {
3859 hdd_err("put fail");
3860 goto fail;
3861 }
3862 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3863 hdd_sta_ctx->conn_info.roam_count) ||
3864 nla_put_u32(skb, INFO_AKM,
3865 hdd_convert_auth_type(
3866 hdd_sta_ctx->conn_info.authType)) ||
3867 nla_put_u32(skb, WLAN802_11_MODE,
3868 hdd_convert_dot11mode(
3869 hdd_sta_ctx->conn_info.dot11Mode))) {
3870 hdd_err("put fail");
3871 goto fail;
3872 }
3873 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3874 if (nla_put(skb, HT_OPERATION,
3875 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3876 &hdd_sta_ctx->conn_info.ht_operation)) {
3877 hdd_err("put fail");
3878 goto fail;
3879 }
3880 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3881 if (nla_put(skb, VHT_OPERATION,
3882 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3883 &hdd_sta_ctx->conn_info.vht_operation)) {
3884 hdd_err("put fail");
3885 goto fail;
3886 }
3887 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3888 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3889 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3890 tmp_hs20 + 1)) {
3891 hdd_err("put fail");
3892 goto fail;
3893 }
3894
3895 return cfg80211_vendor_cmd_reply(skb);
3896fail:
3897 if (skb)
3898 kfree_skb(skb);
3899 return -EINVAL;
3900}
3901
3902/**
3903 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3904 * @wiphy: corestack handler
3905 * @wdev: wireless device
3906 * @data: data
3907 * @data_len: data length
3908 *
3909 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3910 * Validate cmd attributes and send the station info to upper layers.
3911 *
3912 * Return: Success(0) or reason code for failure
3913 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303914static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303915__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3916 struct wireless_dev *wdev,
3917 const void *data,
3918 int data_len)
3919{
3920 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3921 struct net_device *dev = wdev->netdev;
3922 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3923 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3924 int32_t status;
3925
3926 ENTER_DEV(dev);
3927 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3928 hdd_err("Command not allowed in FTM mode");
3929 status = -EPERM;
3930 goto out;
3931 }
3932
3933 status = wlan_hdd_validate_context(hdd_ctx);
3934 if (0 != status)
3935 goto out;
3936
3937
3938 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3939 data, data_len, NULL);
3940 if (status) {
3941 hdd_err("Invalid ATTR");
3942 goto out;
3943 }
3944
3945 /* Parse and fetch Command Type*/
3946 if (tb[STATION_INFO]) {
3947 status = hdd_get_station_info(hdd_ctx, adapter);
3948 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3949 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3950 } else {
3951 hdd_err("get station info cmd type failed");
3952 status = -EINVAL;
3953 goto out;
3954 }
3955 EXIT();
3956out:
3957 return status;
3958}
3959
3960/**
3961 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3962 * @wiphy: corestack handler
3963 * @wdev: wireless device
3964 * @data: data
3965 * @data_len: data length
3966 *
3967 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3968 * Validate cmd attributes and send the station info to upper layers.
3969 *
3970 * Return: Success(0) or reason code for failure
3971 */
3972static int32_t
3973hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3974 struct wireless_dev *wdev,
3975 const void *data,
3976 int data_len)
3977{
3978 int ret;
3979
3980 cds_ssr_protect(__func__);
3981 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3982 cds_ssr_unprotect(__func__);
3983
3984 return ret;
3985}
3986
3987/*
3988 * undef short names defined for get station command
3989 * used by __wlan_hdd_cfg80211_get_station_cmd()
3990 */
3991#undef STATION_INVALID
3992#undef STATION_INFO
3993#undef STATION_ASSOC_FAIL_REASON
3994#undef STATION_MAX
3995
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003996#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3997/**
3998 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3999 * @wiphy: pointer to wireless wiphy structure.
4000 * @wdev: pointer to wireless_dev structure.
4001 * @data: Pointer to the Key data
4002 * @data_len:Length of the data passed
4003 *
4004 * This is called when wlan driver needs to save the keys received via
4005 * vendor specific command.
4006 *
4007 * Return: Return the Success or Failure code.
4008 */
4009static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4010 struct wireless_dev *wdev,
4011 const void *data, int data_len)
4012{
4013 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4014 struct net_device *dev = wdev->netdev;
4015 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4016 hdd_context_t *hdd_ctx_ptr;
4017 int status;
4018
Jeff Johnson1f61b612016-02-12 16:28:33 -08004019 ENTER_DEV(dev);
4020
Anurag Chouhan6d760662016-02-20 16:05:43 +05304021 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 hdd_err("Command not allowed in FTM mode");
4023 return -EPERM;
4024 }
4025
4026 if ((data == NULL) || (data_len == 0) ||
4027 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004028 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029 return -EINVAL;
4030 }
4031
4032 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4033 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004034 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035 return -EINVAL;
4036 }
4037
4038 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304039 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4042 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004043 true,
4044 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304045 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4046 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004047 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4048 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4049 return 0;
4050}
4051
4052/**
4053 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4054 * @wiphy: pointer to wireless wiphy structure.
4055 * @wdev: pointer to wireless_dev structure.
4056 * @data: Pointer to the Key data
4057 * @data_len:Length of the data passed
4058 *
4059 * This is called when wlan driver needs to save the keys received via
4060 * vendor specific command.
4061 *
4062 * Return: Return the Success or Failure code.
4063 */
4064static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4065 struct wireless_dev *wdev,
4066 const void *data, int data_len)
4067{
4068 int ret;
4069
4070 cds_ssr_protect(__func__);
4071 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4072 cds_ssr_unprotect(__func__);
4073
4074 return ret;
4075}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004076#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077
4078static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4079 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4080 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4081 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004082 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083};
4084
4085/**
4086 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4087 * @wiphy: pointer to wireless wiphy structure.
4088 * @wdev: pointer to wireless_dev structure.
4089 * @data: Pointer to the data to be passed via vendor interface
4090 * @data_len:Length of the data to be passed
4091 *
4092 * This is called when wlan driver needs to send wifi driver related info
4093 * (driver/fw version) to the user space application upon request.
4094 *
4095 * Return: Return the Success or Failure code.
4096 */
4097static int
4098__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4099 struct wireless_dev *wdev,
4100 const void *data, int data_len)
4101{
4102 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4103 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004104 tSirVersionString driver_version;
4105 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004108 struct sk_buff *reply_skb;
4109 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004110
Jeff Johnson1f61b612016-02-12 16:28:33 -08004111 ENTER_DEV(wdev->netdev);
4112
Anurag Chouhan6d760662016-02-20 16:05:43 +05304113 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 hdd_err("Command not allowed in FTM mode");
4115 return -EPERM;
4116 }
4117
4118 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304119 if (status)
4120 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121
4122 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4123 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004124 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004125 return -EINVAL;
4126 }
4127
4128 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004129 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004130 strlcpy(driver_version, QWLAN_VERSIONSTR,
4131 sizeof(driver_version));
4132 skb_len += strlen(driver_version) + 1;
4133 count++;
4134 }
4135
4136 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004137 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4139 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004140 snprintf(firmware_version, sizeof(firmware_version),
4141 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4142 skb_len += strlen(firmware_version) + 1;
4143 count++;
4144 }
4145
4146 if (count == 0) {
4147 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004148 return -EINVAL;
4149 }
4150
Ryan Hsu7ac88852016-04-28 10:20:34 -07004151 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4152 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004154 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004155 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 return -ENOMEM;
4157 }
4158
Ryan Hsu7ac88852016-04-28 10:20:34 -07004159 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4160 if (nla_put_string(reply_skb,
4161 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4162 driver_version))
4163 goto error_nla_fail;
4164 }
4165
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304166 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004167 if (nla_put_string(reply_skb,
4168 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4169 firmware_version))
4170 goto error_nla_fail;
4171 }
4172
4173 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4174 if (nla_put_u32(reply_skb,
4175 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4176 hdd_ctx->radio_index))
4177 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178 }
4179
4180 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004181
4182error_nla_fail:
4183 hdd_err("nla put fail");
4184 kfree_skb(reply_skb);
4185 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004186}
4187
4188/**
4189 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4190 * @wiphy: pointer to wireless wiphy structure.
4191 * @wdev: pointer to wireless_dev structure.
4192 * @data: Pointer to the data to be passed via vendor interface
4193 * @data_len:Length of the data to be passed
4194 *
4195 * This is called when wlan driver needs to send wifi driver related info
4196 * (driver/fw version) to the user space application upon request.
4197 *
4198 * Return: Return the Success or Failure code.
4199 */
4200static int
4201wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4202 struct wireless_dev *wdev,
4203 const void *data, int data_len)
4204{
4205 int ret;
4206
4207 cds_ssr_protect(__func__);
4208 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4209 cds_ssr_unprotect(__func__);
4210
4211 return ret;
4212}
4213
4214/**
4215 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4216 * @wiphy: pointer to wireless wiphy structure.
4217 * @wdev: pointer to wireless_dev structure.
4218 * @data: Pointer to the data to be passed via vendor interface
4219 * @data_len:Length of the data to be passed
4220 *
4221 * This is called by userspace to know the supported logger features
4222 *
4223 * Return: Return the Success or Failure code.
4224 */
4225static int
4226__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4227 struct wireless_dev *wdev,
4228 const void *data, int data_len)
4229{
4230 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4231 int status;
4232 uint32_t features;
4233 struct sk_buff *reply_skb = NULL;
4234
Jeff Johnson1f61b612016-02-12 16:28:33 -08004235 ENTER_DEV(wdev->netdev);
4236
Anurag Chouhan6d760662016-02-20 16:05:43 +05304237 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004238 hdd_err("Command not allowed in FTM mode");
4239 return -EPERM;
4240 }
4241
4242 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304243 if (status)
4244 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245
4246 features = 0;
4247
4248 if (hdd_is_memdump_supported())
4249 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4250 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4251 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4252 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4253
4254 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4255 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4256 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004257 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004258 return -ENOMEM;
4259 }
4260
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004261 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4263 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004264 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004265 kfree_skb(reply_skb);
4266 return -EINVAL;
4267 }
4268
4269 return cfg80211_vendor_cmd_reply(reply_skb);
4270}
4271
4272/**
4273 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4274 * @wiphy: pointer to wireless wiphy structure.
4275 * @wdev: pointer to wireless_dev structure.
4276 * @data: Pointer to the data to be passed via vendor interface
4277 * @data_len:Length of the data to be passed
4278 *
4279 * This is called by userspace to know the supported logger features
4280 *
4281 * Return: Return the Success or Failure code.
4282 */
4283static int
4284wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4285 struct wireless_dev *wdev,
4286 const void *data, int data_len)
4287{
4288 int ret;
4289
4290 cds_ssr_protect(__func__);
4291 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4292 data, data_len);
4293 cds_ssr_unprotect(__func__);
4294
4295 return ret;
4296}
4297
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004298#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299/**
4300 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304301 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302 * @bssid: pointer to bssid of roamed AP.
4303 * @req_rsn_ie: Pointer to request RSN IE
4304 * @req_rsn_len: Length of the request RSN IE
4305 * @rsp_rsn_ie: Pointer to response RSN IE
4306 * @rsp_rsn_len: Length of the response RSN IE
4307 * @roam_info_ptr: Pointer to the roaming related information
4308 *
4309 * This is called when wlan driver needs to send the roaming and
4310 * authorization information after roaming.
4311 *
4312 * The information that would be sent is the request RSN IE, response
4313 * RSN IE and BSSID of the newly roamed AP.
4314 *
4315 * If the Authorized status is authenticated, then additional parameters
4316 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4317 * supplicant.
4318 *
4319 * The supplicant upon receiving this event would ignore the legacy
4320 * cfg80211_roamed call and use the entire information from this event.
4321 * The cfg80211_roamed should still co-exist since the kernel will
4322 * make use of the parameters even if the supplicant ignores it.
4323 *
4324 * Return: Return the Success or Failure code.
4325 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304326int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004327 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4328 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4329{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304330 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004332 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333 ENTER();
4334
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304335 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004337
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004338 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004339 !roam_info_ptr->roamSynchInProgress)
4340 return 0;
4341
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004342 /*
4343 * The user space has issued a disconnect when roaming is in
4344 * progress. The disconnect should be honored gracefully.
4345 * If the roaming is complete and the roam event is sent
4346 * back to the user space, it will get confused as it is
4347 * expecting a disconnect event. So, do not send the event
4348 * and handle the disconnect later.
4349 */
4350 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004351 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004352 return 0;
4353 }
4354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304356 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4358 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4359 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004360 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4362 GFP_KERNEL);
4363
4364 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004365 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366 return -EINVAL;
4367 }
4368
4369 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4370 ETH_ALEN, bssid) ||
4371 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4372 req_rsn_len, req_rsn_ie) ||
4373 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4374 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004375 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376 goto nla_put_failure;
4377 }
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)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004396 hdd_err("non FT/non CCKM connection");
4397 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004398 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
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304418 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4419 roam_info_ptr->synchAuthStatus,
4420 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004421
4422 /*
4423 * Add subnet change status if subnet has changed
4424 * 0 = unchanged
4425 * 1 = changed
4426 * 2 = unknown
4427 */
4428 if (roam_info_ptr->subnet_change_status) {
4429 if (nla_put_u8(skb,
4430 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4431 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004432 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004433 goto nla_put_failure;
4434 }
4435 }
4436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004437 cfg80211_vendor_event(skb, GFP_KERNEL);
4438 return 0;
4439
4440nla_put_failure:
4441 kfree_skb(skb);
4442 return -EINVAL;
4443}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004444#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004445
4446static const struct nla_policy
4447wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4448
4449 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4450 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4451 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304452 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304453 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4454 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004455 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4456 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4457 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4458 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4459 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304460 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004461};
4462
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304464 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4465 *
4466 * @adapter: Pointer to HDD adapter
4467 * @ie_data: Pointer to Scan IEs buffer
4468 * @ie_len: Length of Scan IEs
4469 *
4470 * Return: 0 on success; error number otherwise
4471 */
4472static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4473 uint8_t *ie_data, uint8_t ie_len)
4474{
4475 hdd_scaninfo_t *scan_info = NULL;
4476 scan_info = &adapter->scan_info;
4477
4478 if (scan_info->default_scan_ies) {
4479 qdf_mem_free(scan_info->default_scan_ies);
4480 scan_info->default_scan_ies = NULL;
4481 }
4482
4483 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4484 if (!scan_info->default_scan_ies)
4485 return -ENOMEM;
4486
4487 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4488 scan_info->default_scan_ies_len = ie_len;
4489 return 0;
4490}
4491
4492/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4494 * vendor command
4495 *
4496 * @wiphy: wiphy device pointer
4497 * @wdev: wireless device pointer
4498 * @data: Vendor command data buffer
4499 * @data_len: Buffer length
4500 *
4501 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4502 *
4503 * Return: Error code.
4504 */
4505static int
4506__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4507 struct wireless_dev *wdev,
4508 const void *data,
4509 int data_len)
4510{
4511 struct net_device *dev = wdev->netdev;
4512 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4513 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4514 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4515 int ret_val = 0;
4516 u32 modulated_dtim;
4517 u16 stats_avg_factor;
4518 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304519 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004520 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004521 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304522 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304523 int attr_len;
4524 int access_policy = 0;
4525 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4526 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304527 uint16_t scan_ie_len = 0;
4528 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304529 struct sir_set_tx_rx_aggregation_size request;
4530 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004531 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004532 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004533 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304534 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304535
Jeff Johnson1f61b612016-02-12 16:28:33 -08004536 ENTER_DEV(dev);
4537
Anurag Chouhan6d760662016-02-20 16:05:43 +05304538 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004539 hdd_err("Command not allowed in FTM mode");
4540 return -EPERM;
4541 }
4542
4543 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304544 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004545 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546
4547 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4548 data, data_len,
4549 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004550 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 return -EINVAL;
4552 }
4553
Krunal Sonie3531942016-04-12 17:43:53 -07004554 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4555 ftm_capab = nla_get_u32(tb[
4556 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4557 hdd_ctx->config->fine_time_meas_cap =
4558 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4559 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304560 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004561 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004562 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4563 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004564 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004565 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4566 hdd_ctx->config->fine_time_meas_cap);
4567 }
4568
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004569 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4570 modulated_dtim = nla_get_u32(
4571 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4572
4573 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4574 adapter->sessionId,
4575 modulated_dtim);
4576
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304577 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 ret_val = -EPERM;
4579 }
4580
Kapil Gupta6213c012016-09-02 19:39:09 +05304581 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4582 qpower = nla_get_u8(
4583 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4584 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4585 ret_val = -EINVAL;
4586 }
4587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4589 stats_avg_factor = nla_get_u16(
4590 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4591 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4592 adapter->sessionId,
4593 stats_avg_factor);
4594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304595 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004596 ret_val = -EPERM;
4597 }
4598
4599
4600 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4601 guard_time = nla_get_u32(
4602 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4603 status = sme_configure_guard_time(hdd_ctx->hHal,
4604 adapter->sessionId,
4605 guard_time);
4606
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304607 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 ret_val = -EPERM;
4609 }
4610
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304611 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4612 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4613 attr_len = nla_len(
4614 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4615 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004616 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304617 attr_len);
4618 return -EINVAL;
4619 }
4620
4621 nla_memcpy(&vendor_ie,
4622 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4623 attr_len);
4624 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004625 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304626 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304627 }
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)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004635 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304636 access_policy);
4637 return -EINVAL;
4638 }
4639 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004640 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304641 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;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004690 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004691 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4692 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004693 abs_delay, PDEV_CMD);
4694 }
4695
4696 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4697 abs_delay = nla_get_u8(tb[
4698 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4699 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4700 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4701 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004702 }
4703
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304704 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4705 tx_fail_count = nla_get_u32(
4706 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4707 if (tx_fail_count) {
4708 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4709 adapter->sessionId, tx_fail_count);
4710 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004711 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304712 status);
4713 return -EINVAL;
4714 }
4715 }
4716 }
4717
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304718 if (vendor_ie_present && access_policy_present) {
4719 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4720 access_policy =
4721 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304722 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304723 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304724 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304725
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004726 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304727 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4728 adapter->sessionId, &vendor_ie[0],
4729 access_policy);
4730 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004731 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304732 return -EINVAL;
4733 }
4734 }
4735
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304736 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4737 set_value = nla_get_u8(
4738 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004739 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304740 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4741 }
4742
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304743 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4744 scan_ie_len = nla_len(
4745 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004746 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304747 scan_ie_len, adapter->sessionId,
4748 adapter->device_mode);
4749 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4750 scan_ie = (uint8_t *) nla_data(tb
4751 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304752
4753 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4754 scan_ie_len))
4755 hdd_err("Failed to save default scan IEs");
4756
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304757 if (adapter->device_mode == QDF_STA_MODE) {
4758 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4759 adapter->sessionId, scan_ie,
4760 scan_ie_len);
4761 if (QDF_STATUS_SUCCESS != status)
4762 ret_val = -EPERM;
4763 }
4764 } else
4765 ret_val = -EPERM;
4766 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304767
4768 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4769 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4770 /* if one is specified, both must be specified */
4771 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4772 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4773 hdd_err("Both TX and RX MPDU Aggregation required");
4774 return -EINVAL;
4775 }
4776
4777 request.tx_aggregation_size = nla_get_u8(
4778 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4779 request.rx_aggregation_size = nla_get_u8(
4780 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4781 request.vdev_id = adapter->sessionId;
4782
4783 if (request.tx_aggregation_size >=
4784 CFG_TX_AGGREGATION_SIZE_MIN &&
4785 request.tx_aggregation_size <=
4786 CFG_TX_AGGREGATION_SIZE_MAX &&
4787 request.rx_aggregation_size >=
4788 CFG_RX_AGGREGATION_SIZE_MIN &&
4789 request.rx_aggregation_size <=
4790 CFG_RX_AGGREGATION_SIZE_MAX) {
4791 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4792 if (qdf_status != QDF_STATUS_SUCCESS) {
4793 hdd_err("failed to set aggr sizes err %d",
4794 qdf_status);
4795 ret_val = -EPERM;
4796 }
4797 } else {
4798 hdd_err("TX %d RX %d MPDU aggr size not in range",
4799 request.tx_aggregation_size,
4800 request.rx_aggregation_size);
4801 ret_val = -EINVAL;
4802 }
4803 }
4804
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304805 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4806 uint8_t ignore_assoc_disallowed;
4807
4808 ignore_assoc_disallowed
4809 = nla_get_u8(tb[
4810 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004811 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304812 ignore_assoc_disallowed);
4813 if ((ignore_assoc_disallowed <
4814 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4815 (ignore_assoc_disallowed >
4816 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4817 return -EPERM;
4818
4819 sme_update_session_param(hdd_ctx->hHal,
4820 adapter->sessionId,
4821 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4822 ignore_assoc_disallowed);
4823 }
4824
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825 return ret_val;
4826}
4827
4828/**
4829 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4830 * vendor command
4831 *
4832 * @wiphy: wiphy device pointer
4833 * @wdev: wireless device pointer
4834 * @data: Vendor command data buffer
4835 * @data_len: Buffer length
4836 *
4837 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4838 *
4839 * Return: EOK or other error codes.
4840 */
4841static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4842 struct wireless_dev *wdev,
4843 const void *data,
4844 int data_len)
4845{
4846 int ret;
4847
4848 cds_ssr_protect(__func__);
4849 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4850 data, data_len);
4851 cds_ssr_unprotect(__func__);
4852
4853 return ret;
4854}
4855
4856static const struct
4857nla_policy
4858qca_wlan_vendor_wifi_logger_start_policy
4859[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4860 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4861 = {.type = NLA_U32 },
4862 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4863 = {.type = NLA_U32 },
4864 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4865 = {.type = NLA_U32 },
4866};
4867
4868/**
4869 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4870 * or disable the collection of packet statistics from the firmware
4871 * @wiphy: WIPHY structure pointer
4872 * @wdev: Wireless device structure pointer
4873 * @data: Pointer to the data received
4874 * @data_len: Length of the data received
4875 *
4876 * This function enables or disables the collection of packet statistics from
4877 * the firmware
4878 *
4879 * Return: 0 on success and errno on failure
4880 */
4881static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4882 struct wireless_dev *wdev,
4883 const void *data,
4884 int data_len)
4885{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304886 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4888 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4889 struct sir_wifi_start_log start_log;
4890
Jeff Johnson1f61b612016-02-12 16:28:33 -08004891 ENTER_DEV(wdev->netdev);
4892
Anurag Chouhan6d760662016-02-20 16:05:43 +05304893 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004894 hdd_err("Command not allowed in FTM mode");
4895 return -EPERM;
4896 }
4897
4898 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304899 if (status)
4900 return status;
4901
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304902 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4903 hdd_err("Driver Modules are closed, can not start logger");
4904 return -EINVAL;
4905 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906
4907 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4908 data, data_len,
4909 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
4913
4914 /* Parse and fetch ring id */
4915 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004916 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 return -EINVAL;
4918 }
4919 start_log.ring_id = nla_get_u32(
4920 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004921 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922
4923 /* Parse and fetch verbose level */
4924 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004925 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926 return -EINVAL;
4927 }
4928 start_log.verbose_level = nla_get_u32(
4929 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004930 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931
4932 /* Parse and fetch flag */
4933 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004934 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 return -EINVAL;
4936 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304937 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004939 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304941 /* size is buff size which can be set using iwpriv command*/
4942 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304943 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304944
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4946
4947 if (start_log.ring_id == RING_ID_WAKELOCK) {
4948 /* Start/stop wakelock events */
4949 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4950 cds_set_wakelock_logging(true);
4951 else
4952 cds_set_wakelock_logging(false);
4953 return 0;
4954 }
4955
4956 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304957 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004958 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 status);
4960 return -EINVAL;
4961 }
4962 return 0;
4963}
4964
4965/**
4966 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4967 * or disable the collection of packet statistics from the firmware
4968 * @wiphy: WIPHY structure pointer
4969 * @wdev: Wireless device structure pointer
4970 * @data: Pointer to the data received
4971 * @data_len: Length of the data received
4972 *
4973 * This function is used to enable or disable the collection of packet
4974 * statistics from the firmware
4975 *
4976 * Return: 0 on success and errno on failure
4977 */
4978static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4979 struct wireless_dev *wdev,
4980 const void *data,
4981 int data_len)
4982{
4983 int ret = 0;
4984
4985 cds_ssr_protect(__func__);
4986 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4987 wdev, data, data_len);
4988 cds_ssr_unprotect(__func__);
4989
4990 return ret;
4991}
4992
4993static const struct
4994nla_policy
4995qca_wlan_vendor_wifi_logger_get_ring_data_policy
4996[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4997 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4998 = {.type = NLA_U32 },
4999};
5000
5001/**
5002 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5003 * @wiphy: WIPHY structure pointer
5004 * @wdev: Wireless device structure pointer
5005 * @data: Pointer to the data received
5006 * @data_len: Length of the data received
5007 *
5008 * This function is used to flush or retrieve the per packet statistics from
5009 * the driver
5010 *
5011 * Return: 0 on success and errno on failure
5012 */
5013static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5014 struct wireless_dev *wdev,
5015 const void *data,
5016 int data_len)
5017{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305018 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005019 uint32_t ring_id;
5020 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5021 struct nlattr *tb
5022 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5023
Jeff Johnson1f61b612016-02-12 16:28:33 -08005024 ENTER_DEV(wdev->netdev);
5025
Anurag Chouhan6d760662016-02-20 16:05:43 +05305026 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 hdd_err("Command not allowed in FTM mode");
5028 return -EPERM;
5029 }
5030
5031 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305032 if (status)
5033 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005034
5035 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5036 data, data_len,
5037 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005038 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039 return -EINVAL;
5040 }
5041
5042 /* Parse and fetch ring id */
5043 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005044 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 return -EINVAL;
5046 }
5047
5048 ring_id = nla_get_u32(
5049 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5050
5051 if (ring_id == RING_ID_PER_PACKET_STATS) {
5052 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005053 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305054 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5055 /*
5056 * As part of DRIVER ring ID, flush both driver and fw logs.
5057 * For other Ring ID's driver doesn't have any rings to flush
5058 */
5059 hdd_notice("Bug report triggered by framework");
5060
5061 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5062 WLAN_LOG_INDICATOR_FRAMEWORK,
5063 WLAN_LOG_REASON_CODE_UNUSED,
5064 true, false);
5065 if (QDF_STATUS_SUCCESS != status) {
5066 hdd_err("Failed to trigger bug report");
5067 return -EINVAL;
5068 }
5069 } else {
5070 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5071 WLAN_LOG_INDICATOR_FRAMEWORK,
5072 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005073 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074 return 0;
5075}
5076
5077/**
5078 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5079 * @wiphy: WIPHY structure pointer
5080 * @wdev: Wireless device structure pointer
5081 * @data: Pointer to the data received
5082 * @data_len: Length of the data received
5083 *
5084 * This function is used to flush or retrieve the per packet statistics from
5085 * the driver
5086 *
5087 * Return: 0 on success and errno on failure
5088 */
5089static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5090 struct wireless_dev *wdev,
5091 const void *data,
5092 int data_len)
5093{
5094 int ret = 0;
5095
5096 cds_ssr_protect(__func__);
5097 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5098 wdev, data, data_len);
5099 cds_ssr_unprotect(__func__);
5100
5101 return ret;
5102}
5103
5104#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5105/**
5106 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5107 * @hdd_ctx: HDD context
5108 * @request_id: [input] request id
5109 * @pattern_id: [output] pattern id
5110 *
5111 * This function loops through request id to pattern id array
5112 * if the slot is available, store the request id and return pattern id
5113 * if entry exists, return the pattern id
5114 *
5115 * Return: 0 on success and errno on failure
5116 */
5117static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5118 uint32_t request_id,
5119 uint8_t *pattern_id)
5120{
5121 uint32_t i;
5122
5123 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5124 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5125 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5126 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5127 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5128 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5129 return 0;
5130 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5131 request_id) {
5132 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5133 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5134 return 0;
5135 }
5136 }
5137 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5138 return -EINVAL;
5139}
5140
5141/**
5142 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5143 * @hdd_ctx: HDD context
5144 * @request_id: [input] request id
5145 * @pattern_id: [output] pattern id
5146 *
5147 * This function loops through request id to pattern id array
5148 * reset request id to 0 (slot available again) and
5149 * return pattern id
5150 *
5151 * Return: 0 on success and errno on failure
5152 */
5153static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5154 uint32_t request_id,
5155 uint8_t *pattern_id)
5156{
5157 uint32_t i;
5158
5159 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5160 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5161 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5162 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5163 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5164 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5165 return 0;
5166 }
5167 }
5168 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5169 return -EINVAL;
5170}
5171
5172
5173/*
5174 * define short names for the global vendor params
5175 * used by __wlan_hdd_cfg80211_offloaded_packets()
5176 */
5177#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5178#define PARAM_REQUEST_ID \
5179 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5180#define PARAM_CONTROL \
5181 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5182#define PARAM_IP_PACKET \
5183 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5184#define PARAM_SRC_MAC_ADDR \
5185 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5186#define PARAM_DST_MAC_ADDR \
5187 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5188#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5189
5190/**
5191 * wlan_hdd_add_tx_ptrn() - add tx pattern
5192 * @adapter: adapter pointer
5193 * @hdd_ctx: hdd context
5194 * @tb: nl attributes
5195 *
5196 * This function reads the NL attributes and forms a AddTxPtrn message
5197 * posts it to SME.
5198 *
5199 */
5200static int
5201wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5202 struct nlattr **tb)
5203{
5204 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305205 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206 uint32_t request_id, ret, len;
5207 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305208 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209 uint16_t eth_type = htons(ETH_P_IP);
5210
5211 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005212 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005213 return -ENOTSUPP;
5214 }
5215
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305216 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005218 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219 return -ENOMEM;
5220 }
5221
5222 /* Parse and fetch request Id */
5223 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005224 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225 goto fail;
5226 }
5227
5228 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5229 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005230 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 return -EINVAL;
5232 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005233 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234
5235 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005236 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237 goto fail;
5238 }
5239 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005240 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005242 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243 goto fail;
5244 }
5245
5246 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005247 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248 goto fail;
5249 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005250 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305251 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005252 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005253 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005254
Anurag Chouhanc5548422016-02-24 18:33:27 +05305255 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005256 &adapter->macAddressCurrent)) {
5257 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005258 goto fail;
5259 }
5260
5261 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005262 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263 goto fail;
5264 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305265 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005266 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005267 MAC_ADDR_ARRAY(dst_addr.bytes));
5268
5269 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005270 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005271 goto fail;
5272 }
5273 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005274 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275
5276 if (add_req->ucPtrnSize < 0 ||
5277 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5278 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005279 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 add_req->ucPtrnSize);
5281 goto fail;
5282 }
5283
5284 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305285 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305286 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305287 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305288 QDF_MAC_ADDR_SIZE);
5289 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305290 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291 len += 2;
5292
5293 /*
5294 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5295 * ------------------------------------------------------------
5296 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5297 * ------------------------------------------------------------
5298 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305299 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 nla_data(tb[PARAM_IP_PACKET]),
5301 add_req->ucPtrnSize);
5302 add_req->ucPtrnSize += len;
5303
5304 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5305 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005306 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 goto fail;
5308 }
5309 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005310 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005311
5312 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305313 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005314 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005315 goto fail;
5316 }
5317
5318 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305319 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320 return 0;
5321
5322fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305323 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324 return -EINVAL;
5325}
5326
5327/**
5328 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5329 * @adapter: adapter pointer
5330 * @hdd_ctx: hdd context
5331 * @tb: nl attributes
5332 *
5333 * This function reads the NL attributes and forms a DelTxPtrn message
5334 * posts it to SME.
5335 *
5336 */
5337static int
5338wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5339 struct nlattr **tb)
5340{
5341 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305342 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 uint32_t request_id, ret;
5344 uint8_t pattern_id = 0;
5345
5346 /* Parse and fetch request Id */
5347 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005348 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 return -EINVAL;
5350 }
5351 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5352 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005353 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 return -EINVAL;
5355 }
5356
5357 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5358 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005359 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005360 return -EINVAL;
5361 }
5362
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305363 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005365 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 return -ENOMEM;
5367 }
5368
Anurag Chouhanc5548422016-02-24 18:33:27 +05305369 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005370 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005372 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 request_id, del_req->ucPtrnId);
5374
5375 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305376 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005377 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378 goto fail;
5379 }
5380
5381 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305382 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 return 0;
5384
5385fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305386 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 return -EINVAL;
5388}
5389
5390
5391/**
5392 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5393 * @wiphy: Pointer to wireless phy
5394 * @wdev: Pointer to wireless device
5395 * @data: Pointer to data
5396 * @data_len: Data length
5397 *
5398 * Return: 0 on success, negative errno on failure
5399 */
5400static int
5401__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5402 struct wireless_dev *wdev,
5403 const void *data,
5404 int data_len)
5405{
5406 struct net_device *dev = wdev->netdev;
5407 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5408 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5409 struct nlattr *tb[PARAM_MAX + 1];
5410 uint8_t control;
5411 int ret;
5412 static const struct nla_policy policy[PARAM_MAX + 1] = {
5413 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5414 [PARAM_CONTROL] = { .type = NLA_U32 },
5415 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305416 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305418 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005419 [PARAM_PERIOD] = { .type = NLA_U32 },
5420 };
5421
Jeff Johnson1f61b612016-02-12 16:28:33 -08005422 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423
Anurag Chouhan6d760662016-02-20 16:05:43 +05305424 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 hdd_err("Command not allowed in FTM mode");
5426 return -EPERM;
5427 }
5428
5429 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305430 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432
5433 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005434 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435 return -ENOTSUPP;
5436 }
5437
5438 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005439 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440 return -EINVAL;
5441 }
5442
5443 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005444 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445 return -EINVAL;
5446 }
5447 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005448 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449
5450 if (control == WLAN_START_OFFLOADED_PACKETS)
5451 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005452 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005453 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005454
5455 hdd_err("Invalid control: %d", control);
5456
5457 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458}
5459
5460/*
5461 * done with short names for the global vendor params
5462 * used by __wlan_hdd_cfg80211_offloaded_packets()
5463 */
5464#undef PARAM_MAX
5465#undef PARAM_REQUEST_ID
5466#undef PARAM_CONTROL
5467#undef PARAM_IP_PACKET
5468#undef PARAM_SRC_MAC_ADDR
5469#undef PARAM_DST_MAC_ADDR
5470#undef PARAM_PERIOD
5471
5472/**
5473 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5474 * @wiphy: wiphy structure pointer
5475 * @wdev: Wireless device structure pointer
5476 * @data: Pointer to the data received
5477 * @data_len: Length of @data
5478 *
5479 * Return: 0 on success; errno on failure
5480 */
5481static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5482 struct wireless_dev *wdev,
5483 const void *data,
5484 int data_len)
5485{
5486 int ret = 0;
5487
5488 cds_ssr_protect(__func__);
5489 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5490 wdev, data, data_len);
5491 cds_ssr_unprotect(__func__);
5492
5493 return ret;
5494}
5495#endif
5496
5497/*
5498 * define short names for the global vendor params
5499 * used by __wlan_hdd_cfg80211_monitor_rssi()
5500 */
5501#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5502#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5503#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5504#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5505#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5506
5507/**
5508 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5509 * @wiphy: Pointer to wireless phy
5510 * @wdev: Pointer to wireless device
5511 * @data: Pointer to data
5512 * @data_len: Data length
5513 *
5514 * Return: 0 on success, negative errno on failure
5515 */
5516static int
5517__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5518 struct wireless_dev *wdev,
5519 const void *data,
5520 int data_len)
5521{
5522 struct net_device *dev = wdev->netdev;
5523 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5524 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5525 struct nlattr *tb[PARAM_MAX + 1];
5526 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305527 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 int ret;
5529 uint32_t control;
5530 static const struct nla_policy policy[PARAM_MAX + 1] = {
5531 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5532 [PARAM_CONTROL] = { .type = NLA_U32 },
5533 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5534 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5535 };
5536
Jeff Johnson1f61b612016-02-12 16:28:33 -08005537 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305539 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5540 hdd_err("invalid session id: %d", adapter->sessionId);
5541 return -EINVAL;
5542 }
5543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305545 if (ret)
5546 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005547
5548 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005549 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 return -ENOTSUPP;
5551 }
5552
5553 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005554 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555 return -EINVAL;
5556 }
5557
5558 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005559 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560 return -EINVAL;
5561 }
5562
5563 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005564 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565 return -EINVAL;
5566 }
5567
5568 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5569 req.session_id = adapter->sessionId;
5570 control = nla_get_u32(tb[PARAM_CONTROL]);
5571
5572 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5573 req.control = true;
5574 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005575 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005576 return -EINVAL;
5577 }
5578
5579 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005580 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005581 return -EINVAL;
5582 }
5583
5584 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5585 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5586
5587 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005588 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 req.min_rssi, req.max_rssi);
5590 return -EINVAL;
5591 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005592 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 req.min_rssi, req.max_rssi);
5594
5595 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5596 req.control = false;
5597 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005598 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005599 return -EINVAL;
5600 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005601 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 req.request_id, req.session_id, req.control);
5603
5604 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305605 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005606 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005607 return -EINVAL;
5608 }
5609
5610 return 0;
5611}
5612
5613/*
5614 * done with short names for the global vendor params
5615 * used by __wlan_hdd_cfg80211_monitor_rssi()
5616 */
5617#undef PARAM_MAX
5618#undef PARAM_CONTROL
5619#undef PARAM_REQUEST_ID
5620#undef PARAM_MAX_RSSI
5621#undef PARAM_MIN_RSSI
5622
5623/**
5624 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5625 * @wiphy: wiphy structure pointer
5626 * @wdev: Wireless device structure pointer
5627 * @data: Pointer to the data received
5628 * @data_len: Length of @data
5629 *
5630 * Return: 0 on success; errno on failure
5631 */
5632static int
5633wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5634 const void *data, int data_len)
5635{
5636 int ret;
5637
5638 cds_ssr_protect(__func__);
5639 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5640 cds_ssr_unprotect(__func__);
5641
5642 return ret;
5643}
5644
5645/**
5646 * hdd_rssi_threshold_breached() - rssi breached NL event
5647 * @hddctx: HDD context
5648 * @data: rssi breached event data
5649 *
5650 * This function reads the rssi breached event %data and fill in the skb with
5651 * NL attributes and send up the NL event.
5652 *
5653 * Return: none
5654 */
5655void hdd_rssi_threshold_breached(void *hddctx,
5656 struct rssi_breach_event *data)
5657{
5658 hdd_context_t *hdd_ctx = hddctx;
5659 struct sk_buff *skb;
5660
5661 ENTER();
5662
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305663 if (wlan_hdd_validate_context(hdd_ctx))
5664 return;
5665 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005666 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667 return;
5668 }
5669
5670 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5671 NULL,
5672 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5673 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5674 GFP_KERNEL);
5675
5676 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005677 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 return;
5679 }
5680
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005681 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005683 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5685
5686 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5687 data->request_id) ||
5688 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5689 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5690 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5691 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005692 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005693 goto fail;
5694 }
5695
5696 cfg80211_vendor_event(skb, GFP_KERNEL);
5697 return;
5698
5699fail:
5700 kfree_skb(skb);
5701 return;
5702}
5703
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305704static const struct nla_policy
5705ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5706 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5707};
5708
5709/**
5710 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5711 * @wiphy: Pointer to wireless phy
5712 * @wdev: Pointer to wireless device
5713 * @data: Pointer to data
5714 * @data_len: Length of @data
5715 *
5716 * Return: 0 on success, negative errno on failure
5717 */
5718static int
5719__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5720 struct wireless_dev *wdev,
5721 const void *data, int data_len)
5722{
5723 int status;
5724 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5725 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005726 struct net_device *dev = wdev->netdev;
5727 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305728
5729 ENTER_DEV(wdev->netdev);
5730
5731 status = wlan_hdd_validate_context(pHddCtx);
5732 if (0 != status)
5733 return status;
5734 if (!pHddCtx->config->fhostNSOffload) {
5735 hdd_err("ND Offload not supported");
5736 return -EINVAL;
5737 }
5738
5739 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5740 (struct nlattr *)data,
5741 data_len, ns_offload_set_policy)) {
5742 hdd_err("nla_parse failed");
5743 return -EINVAL;
5744 }
5745
5746 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5747 hdd_err("ND Offload flag attribute not present");
5748 return -EINVAL;
5749 }
5750
5751 pHddCtx->ns_offload_enable =
5752 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5753
Dustin Brownd8279d22016-09-07 14:52:57 -07005754 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305755 if (pHddCtx->ns_offload_enable)
5756 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5757 else
5758 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005759
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305760 return 0;
5761}
5762
5763/**
5764 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5765 * @wiphy: pointer to wireless wiphy structure.
5766 * @wdev: pointer to wireless_dev structure.
5767 * @data: Pointer to the data to be passed via vendor interface
5768 * @data_len:Length of the data to be passed
5769 *
5770 * Return: Return the Success or Failure code.
5771 */
5772static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5773 struct wireless_dev *wdev,
5774 const void *data, int data_len)
5775{
5776 int ret;
5777
5778 cds_ssr_protect(__func__);
5779 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5780 cds_ssr_unprotect(__func__);
5781
5782 return ret;
5783}
5784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005785/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5786 * @wiphy: Pointer to wireless phy
5787 * @wdev: Pointer to wireless device
5788 * @data: Pointer to data
5789 * @data_len: Data length
5790 *
5791 * This function return the preferred frequency list generated by the policy
5792 * manager.
5793 *
5794 * Return: success or failure code
5795 */
5796static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5797 struct wireless_dev
5798 *wdev, const void *data,
5799 int data_len)
5800{
5801 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5802 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305803 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305804 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005805 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305806 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005807 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005808 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5809 struct sk_buff *reply_skb;
5810
Jeff Johnson1f61b612016-02-12 16:28:33 -08005811 ENTER_DEV(wdev->netdev);
5812
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005813 ret = wlan_hdd_validate_context(hdd_ctx);
5814 if (ret)
5815 return -EINVAL;
5816
5817 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5818 data, data_len, NULL)) {
5819 hdd_err("Invalid ATTR");
5820 return -EINVAL;
5821 }
5822
5823 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5824 hdd_err("attr interface type failed");
5825 return -EINVAL;
5826 }
5827
5828 intf_mode = nla_get_u32(tb
5829 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5830
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005831 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832 hdd_err("Invalid interface type");
5833 return -EINVAL;
5834 }
5835
5836 hdd_debug("Userspace requested pref freq list");
5837
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005838 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5839 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305840 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305841 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842 hdd_err("Get pcl failed");
5843 return -EINVAL;
5844 }
5845
5846 /* convert channel number to frequency */
5847 for (i = 0; i < pcl_len; i++) {
5848 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5849 freq_list[i] =
5850 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005851 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005852 else
5853 freq_list[i] =
5854 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005855 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856 }
5857
5858 /* send the freq_list back to supplicant */
5859 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5860 sizeof(u32) *
5861 pcl_len +
5862 NLMSG_HDRLEN);
5863
5864 if (!reply_skb) {
5865 hdd_err("Allocate reply_skb failed");
5866 return -EINVAL;
5867 }
5868
5869 if (nla_put_u32(reply_skb,
5870 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5871 intf_mode) ||
5872 nla_put(reply_skb,
5873 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5874 sizeof(uint32_t) * pcl_len,
5875 freq_list)) {
5876 hdd_err("nla put fail");
5877 kfree_skb(reply_skb);
5878 return -EINVAL;
5879 }
5880
5881 return cfg80211_vendor_cmd_reply(reply_skb);
5882}
5883
5884/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5885 * @wiphy: Pointer to wireless phy
5886 * @wdev: Pointer to wireless device
5887 * @data: Pointer to data
5888 * @data_len: Data length
5889 *
5890 * This function return the preferred frequency list generated by the policy
5891 * manager.
5892 *
5893 * Return: success or failure code
5894 */
5895static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5896 struct wireless_dev
5897 *wdev, const void *data,
5898 int data_len)
5899{
5900 int ret = 0;
5901
5902 cds_ssr_protect(__func__);
5903 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5904 data, data_len);
5905 cds_ssr_unprotect(__func__);
5906
5907 return ret;
5908}
5909
5910/**
5911 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5912 * @wiphy: Pointer to wireless phy
5913 * @wdev: Pointer to wireless device
5914 * @data: Pointer to data
5915 * @data_len: Data length
5916 *
5917 * Return: 0 on success, negative errno on failure
5918 */
5919static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5920 struct wireless_dev *wdev,
5921 const void *data,
5922 int data_len)
5923{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305924 struct net_device *ndev = wdev->netdev;
5925 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5927 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005928 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5930 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931
Jeff Johnson1f61b612016-02-12 16:28:33 -08005932 ENTER_DEV(ndev);
5933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934 ret = wlan_hdd_validate_context(hdd_ctx);
5935 if (ret)
5936 return ret;
5937
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5939 data, data_len, NULL)) {
5940 hdd_err("Invalid ATTR");
5941 return -EINVAL;
5942 }
5943
5944 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5945 hdd_err("attr interface type failed");
5946 return -EINVAL;
5947 }
5948
5949 intf_mode = nla_get_u32(tb
5950 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5951
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005952 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953 hdd_err("Invalid interface type");
5954 return -EINVAL;
5955 }
5956
5957 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5958 hdd_err("attr probable freq failed");
5959 return -EINVAL;
5960 }
5961
5962 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5963 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5964
5965 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005966 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967 channel_hint, HW_MODE_20_MHZ)) {
5968 hdd_err("Set channel hint failed due to concurrency check");
5969 return -EINVAL;
5970 }
5971
Krunal Soni09e55032016-06-07 10:06:55 -07005972 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5973 hdd_warn("Remain On Channel Pending");
5974
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005975 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005976 if (!QDF_IS_STATUS_SUCCESS(ret))
5977 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005979 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5980 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005981 SIR_UPDATE_REASON_SET_OPER_CHAN);
5982 if (QDF_STATUS_E_FAILURE == ret) {
5983 /* return in the failure case */
5984 hdd_err("ERROR: connections update failed!!");
5985 return -EINVAL;
5986 }
5987
5988 if (QDF_STATUS_SUCCESS == ret) {
5989 /*
5990 * Success is the only case for which we expect hw mode
5991 * change to take place, hence we need to wait.
5992 * For any other return value it should be a pass
5993 * through
5994 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005995 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005996 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5997 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005998 return -EINVAL;
5999 }
6000
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006001 }
6002
6003 return 0;
6004}
6005
6006/**
6007 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6008 * @wiphy: Pointer to wireless phy
6009 * @wdev: Pointer to wireless device
6010 * @data: Pointer to data
6011 * @data_len: Data length
6012 *
6013 * Return: 0 on success, negative errno on failure
6014 */
6015static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6016 struct wireless_dev *wdev,
6017 const void *data,
6018 int data_len)
6019{
6020 int ret = 0;
6021
6022 cds_ssr_protect(__func__);
6023 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6024 data, data_len);
6025 cds_ssr_unprotect(__func__);
6026
6027 return ret;
6028}
6029
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306030static const struct
6031nla_policy
6032qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6033 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6034};
6035
6036/**
6037 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6038 * @wiphy: WIPHY structure pointer
6039 * @wdev: Wireless device structure pointer
6040 * @data: Pointer to the data received
6041 * @data_len: Length of the data received
6042 *
6043 * This function is used to get link properties like nss, rate flags and
6044 * operating frequency for the active connection with the given peer.
6045 *
6046 * Return: 0 on success and errno on failure
6047 */
6048static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6049 struct wireless_dev *wdev,
6050 const void *data,
6051 int data_len)
6052{
6053 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6054 struct net_device *dev = wdev->netdev;
6055 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6056 hdd_station_ctx_t *hdd_sta_ctx;
6057 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306058 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306059 uint32_t sta_id;
6060 struct sk_buff *reply_skb;
6061 uint32_t rate_flags = 0;
6062 uint8_t nss;
6063 uint8_t final_rate_flags = 0;
6064 uint32_t freq;
6065
Jeff Johnson1f61b612016-02-12 16:28:33 -08006066 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306067
Anurag Chouhan6d760662016-02-20 16:05:43 +05306068 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306069 hdd_err("Command not allowed in FTM mode");
6070 return -EPERM;
6071 }
6072
6073 if (0 != wlan_hdd_validate_context(hdd_ctx))
6074 return -EINVAL;
6075
6076 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6077 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006078 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306079 return -EINVAL;
6080 }
6081
6082 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006083 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306084 adapter->device_mode);
6085 return -EINVAL;
6086 }
6087
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306088 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306089 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006090 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306091 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6092
Krunal Sonib4326f22016-03-10 13:05:51 -08006093 if (adapter->device_mode == QDF_STA_MODE ||
6094 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306095 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6096 if ((hdd_sta_ctx->conn_info.connState !=
6097 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306098 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306099 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006100 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306101 MAC_ADDR_ARRAY(peer_mac));
6102 return -EINVAL;
6103 }
6104
6105 nss = hdd_sta_ctx->conn_info.nss;
6106 freq = cds_chan_to_freq(
6107 hdd_sta_ctx->conn_info.operationChannel);
6108 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006109 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6110 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306111
6112 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6113 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306114 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306115 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306116 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306117 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306118 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306119 break;
6120 }
6121
6122 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006123 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306124 MAC_ADDR_ARRAY(peer_mac));
6125 return -EINVAL;
6126 }
6127
6128 nss = adapter->aStaInfo[sta_id].nss;
6129 freq = cds_chan_to_freq(
6130 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6131 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6132 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006133 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306134 MAC_ADDR_ARRAY(peer_mac));
6135 return -EINVAL;
6136 }
6137
6138 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6139 if (rate_flags & eHAL_TX_RATE_VHT80) {
6140 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006141#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306142 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006143#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306144 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6145 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006146#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306147 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006148#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306149 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6150 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6151 } else if (rate_flags &
6152 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6153 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006154#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306155 if (rate_flags & eHAL_TX_RATE_HT40)
6156 final_rate_flags |=
6157 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006158#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306159 }
6160
6161 if (rate_flags & eHAL_TX_RATE_SGI) {
6162 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6163 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6164 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6165 }
6166 }
6167
6168 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6169 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6170
6171 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006172 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306173 return -EINVAL;
6174 }
6175
6176 if (nla_put_u8(reply_skb,
6177 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6178 nss) ||
6179 nla_put_u8(reply_skb,
6180 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6181 final_rate_flags) ||
6182 nla_put_u32(reply_skb,
6183 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6184 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006185 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306186 kfree_skb(reply_skb);
6187 return -EINVAL;
6188 }
6189
6190 return cfg80211_vendor_cmd_reply(reply_skb);
6191}
6192
6193/**
6194 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6195 * properties.
6196 * @wiphy: WIPHY structure pointer
6197 * @wdev: Wireless device structure pointer
6198 * @data: Pointer to the data received
6199 * @data_len: Length of the data received
6200 *
6201 * This function is used to get link properties like nss, rate flags and
6202 * operating frequency for the active connection with the given peer.
6203 *
6204 * Return: 0 on success and errno on failure
6205 */
6206static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6207 struct wireless_dev *wdev,
6208 const void *data,
6209 int data_len)
6210{
6211 int ret = 0;
6212
6213 cds_ssr_protect(__func__);
6214 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6215 wdev, data, data_len);
6216 cds_ssr_unprotect(__func__);
6217
6218 return ret;
6219}
6220
Peng Xu278d0122015-09-24 16:34:17 -07006221static const struct
6222nla_policy
6223qca_wlan_vendor_ota_test_policy
6224[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6225 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6226};
6227
6228/**
6229 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6230 * @wiphy: Pointer to wireless phy
6231 * @wdev: Pointer to wireless device
6232 * @data: Pointer to data
6233 * @data_len: Data length
6234 *
6235 * Return: 0 on success, negative errno on failure
6236 */
6237static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6238 struct wireless_dev *wdev,
6239 const void *data,
6240 int data_len)
6241{
6242 struct net_device *dev = wdev->netdev;
6243 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6244 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6245 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6246 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6247 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306248 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006249 uint32_t current_roam_state;
6250
Jeff Johnson1f61b612016-02-12 16:28:33 -08006251 ENTER_DEV(dev);
6252
Anurag Chouhan6d760662016-02-20 16:05:43 +05306253 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006254 hdd_err("Command not allowed in FTM mode");
6255 return -EPERM;
6256 }
6257
6258 if (0 != wlan_hdd_validate_context(hdd_ctx))
6259 return -EINVAL;
6260
6261 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6262 data, data_len,
6263 qca_wlan_vendor_ota_test_policy)) {
6264 hdd_err("invalid attr");
6265 return -EINVAL;
6266 }
6267
6268 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6269 hdd_err("attr ota test failed");
6270 return -EINVAL;
6271 }
6272
6273 ota_enable = nla_get_u8(
6274 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6275
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006276 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006277 if (ota_enable != 1) {
6278 hdd_err("Invalid value, only enable test mode is supported!");
6279 return -EINVAL;
6280 }
6281
6282 current_roam_state =
6283 sme_get_current_roam_state(hal, adapter->sessionId);
6284 status = sme_stop_roaming(hal, adapter->sessionId,
6285 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306286 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006287 hdd_err("Enable/Disable roaming failed");
6288 return -EINVAL;
6289 }
6290
6291 status = sme_ps_enable_disable(hal, adapter->sessionId,
6292 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306293 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006294 hdd_err("Enable/Disable power save failed");
6295 /* restore previous roaming setting */
6296 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6297 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6298 status = sme_start_roaming(hal, adapter->sessionId,
6299 eCsrHddIssued);
6300 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6301 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6302 status = sme_stop_roaming(hal, adapter->sessionId,
6303 eCsrHddIssued);
6304
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306305 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006306 hdd_err("Restoring roaming state failed");
6307
6308 return -EINVAL;
6309 }
6310
6311
6312 return 0;
6313}
6314
6315/**
6316 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6317 * @wiphy: Pointer to wireless phy
6318 * @wdev: Pointer to wireless device
6319 * @data: Pointer to data
6320 * @data_len: Data length
6321 *
6322 * Return: 0 on success, negative errno on failure
6323 */
6324static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6325 struct wireless_dev *wdev,
6326 const void *data,
6327 int data_len)
6328{
6329 int ret = 0;
6330
6331 cds_ssr_protect(__func__);
6332 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6333 cds_ssr_unprotect(__func__);
6334
6335 return ret;
6336}
6337
Peng Xu4d67c8f2015-10-16 16:02:26 -07006338/**
6339 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6340 * @wiphy: Pointer to wireless phy
6341 * @wdev: Pointer to wireless device
6342 * @data: Pointer to data
6343 * @data_len: Data length
6344 *
6345 * Return: 0 on success, negative errno on failure
6346 */
6347static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6348 struct wireless_dev *wdev,
6349 const void *data,
6350 int data_len)
6351{
6352 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6353 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006354 hdd_adapter_t *adapter;
6355 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006356 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6357 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006358 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006359
Jeff Johnson1f61b612016-02-12 16:28:33 -08006360 ENTER_DEV(dev);
6361
Peng Xu4d67c8f2015-10-16 16:02:26 -07006362 ret = wlan_hdd_validate_context(hdd_ctx);
6363 if (ret)
6364 return ret;
6365
6366 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6367
6368 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6369 data, data_len, NULL)) {
6370 hdd_err("Invalid ATTR");
6371 return -EINVAL;
6372 }
6373
6374 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6375 hdd_err("attr tx power scale failed");
6376 return -EINVAL;
6377 }
6378
6379 scale_value = nla_get_u8(tb
6380 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6381
6382 if (scale_value > MAX_TXPOWER_SCALE) {
6383 hdd_err("Invalid tx power scale level");
6384 return -EINVAL;
6385 }
6386
Peng Xu62c8c432016-05-09 15:23:02 -07006387 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006388
Peng Xu62c8c432016-05-09 15:23:02 -07006389 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006390 hdd_err("Set tx power scale failed");
6391 return -EINVAL;
6392 }
6393
6394 return 0;
6395}
6396
6397/**
6398 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6399 * @wiphy: Pointer to wireless phy
6400 * @wdev: Pointer to wireless device
6401 * @data: Pointer to data
6402 * @data_len: Data length
6403 *
6404 * Return: 0 on success, negative errno on failure
6405 */
6406static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6407 struct wireless_dev *wdev,
6408 const void *data,
6409 int data_len)
6410{
Peng Xu62c8c432016-05-09 15:23:02 -07006411 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006412
6413 cds_ssr_protect(__func__);
6414 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6415 data, data_len);
6416 cds_ssr_unprotect(__func__);
6417
6418 return ret;
6419}
6420
6421/**
6422 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6423 * @wiphy: Pointer to wireless phy
6424 * @wdev: Pointer to wireless device
6425 * @data: Pointer to data
6426 * @data_len: Data length
6427 *
6428 * Return: 0 on success, negative errno on failure
6429 */
6430static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6431 struct wireless_dev *wdev,
6432 const void *data,
6433 int data_len)
6434{
6435 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6436 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006437 hdd_adapter_t *adapter;
6438 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006439 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6440 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006441 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006442
Jeff Johnson1f61b612016-02-12 16:28:33 -08006443 ENTER_DEV(dev);
6444
Peng Xu4d67c8f2015-10-16 16:02:26 -07006445 ret = wlan_hdd_validate_context(hdd_ctx);
6446 if (ret)
6447 return ret;
6448
6449 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6450
6451 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6452 data, data_len, NULL)) {
6453 hdd_err("Invalid ATTR");
6454 return -EINVAL;
6455 }
6456
6457 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6458 hdd_err("attr tx power decrease db value failed");
6459 return -EINVAL;
6460 }
6461
6462 scale_value = nla_get_u8(tb
6463 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6464
Peng Xu62c8c432016-05-09 15:23:02 -07006465 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6466 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006467
Peng Xu62c8c432016-05-09 15:23:02 -07006468 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006469 hdd_err("Set tx power decrease db failed");
6470 return -EINVAL;
6471 }
6472
6473 return 0;
6474}
6475
6476/**
6477 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6478 * @wiphy: Pointer to wireless phy
6479 * @wdev: Pointer to wireless device
6480 * @data: Pointer to data
6481 * @data_len: Data length
6482 *
6483 * Return: 0 on success, negative errno on failure
6484 */
6485static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6486 struct wireless_dev *wdev,
6487 const void *data,
6488 int data_len)
6489{
Peng Xu62c8c432016-05-09 15:23:02 -07006490 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006491
6492 cds_ssr_protect(__func__);
6493 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6494 data, data_len);
6495 cds_ssr_unprotect(__func__);
6496
6497 return ret;
6498}
Peng Xu8fdaa492016-06-22 10:20:47 -07006499
6500/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306501 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6502 * @wiphy: Pointer to wireless phy
6503 * @wdev: Pointer to wireless device
6504 * @data: Pointer to data
6505 * @data_len: Data length
6506 *
6507 * Processes the conditional channel switch request and invokes the helper
6508 * APIs to process the channel switch request.
6509 *
6510 * Return: 0 on success, negative errno on failure
6511 */
6512static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6513 struct wireless_dev *wdev,
6514 const void *data,
6515 int data_len)
6516{
6517 int ret;
6518 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6519 struct net_device *dev = wdev->netdev;
6520 hdd_adapter_t *adapter;
6521 struct nlattr
6522 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6523 uint32_t freq_len, i;
6524 uint32_t *freq;
6525 uint8_t chans[QDF_MAX_NUM_CHAN];
6526
6527 ENTER_DEV(dev);
6528
6529 ret = wlan_hdd_validate_context(hdd_ctx);
6530 if (ret)
6531 return ret;
6532
6533 if (!hdd_ctx->config->enableDFSMasterCap) {
6534 hdd_err("DFS master capability is not present in the driver");
6535 return -EINVAL;
6536 }
6537
6538 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6539 hdd_err("Command not allowed in FTM mode");
6540 return -EPERM;
6541 }
6542
6543 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6544 if (adapter->device_mode != QDF_SAP_MODE) {
6545 hdd_err("Invalid device mode %d", adapter->device_mode);
6546 return -EINVAL;
6547 }
6548
6549 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6550 data, data_len, NULL)) {
6551 hdd_err("Invalid ATTR");
6552 return -EINVAL;
6553 }
6554
6555 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6556 hdd_err("Frequency list is missing");
6557 return -EINVAL;
6558 }
6559
6560 freq_len = nla_len(
6561 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6562 sizeof(uint32_t);
6563
6564 if (freq_len > QDF_MAX_NUM_CHAN) {
6565 hdd_err("insufficient space to hold channels");
6566 return -ENOMEM;
6567 }
6568
6569 hdd_debug("freq_len=%d", freq_len);
6570
6571 freq = nla_data(
6572 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6573
6574
6575 for (i = 0; i < freq_len; i++) {
6576 if (freq[i] == 0)
6577 chans[i] = 0;
6578 else
6579 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6580
6581 hdd_debug("freq[%d]=%d", i, freq[i]);
6582 }
6583
6584 /*
6585 * The input frequency list from user space is designed to be a
6586 * priority based frequency list. This is only to accommodate any
6587 * future request. But, current requirement is only to perform CAC
6588 * on a single channel. So, the first entry from the list is picked.
6589 *
6590 * If channel is zero, any channel in the available outdoor regulatory
6591 * domain will be selected.
6592 */
6593 ret = wlan_hdd_request_pre_cac(chans[0]);
6594 if (ret) {
6595 hdd_err("pre cac request failed with reason:%d", ret);
6596 return ret;
6597 }
6598
6599 return 0;
6600}
6601
6602/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006603 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6604 * @wiphy: Pointer to wireless phy
6605 * @wdev: Pointer to wireless device
6606 * @data: Pointer to data
6607 * @data_len: Data length
6608 *
6609 * This function is to process the p2p listen offload start vendor
6610 * command. It parses the input parameters and invoke WMA API to
6611 * send the command to firmware.
6612 *
6613 * Return: 0 on success, negative errno on failure
6614 */
6615static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6616 struct wireless_dev *wdev,
6617 const void *data,
6618 int data_len)
6619{
6620 int ret;
6621 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6622 struct net_device *dev = wdev->netdev;
6623 hdd_adapter_t *adapter;
6624 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6625 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006626
6627 ENTER_DEV(dev);
6628
6629 ret = wlan_hdd_validate_context(hdd_ctx);
6630 if (ret)
6631 return ret;
6632
6633 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6634 hdd_err("Command not allowed in FTM mode");
6635 return -EPERM;
6636 }
6637
6638 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6639 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6640 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6641 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6642 hdd_err("Invalid device mode %d", adapter->device_mode);
6643 return -EINVAL;
6644 }
6645
6646 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6647 data, data_len, NULL)) {
6648 hdd_err("Invalid ATTR");
6649 return -EINVAL;
6650 }
6651
6652 memset(&params, 0, sizeof(params));
6653
6654 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6655 params.ctl_flags = 1; /* set to default value */
6656 else
6657 params.ctl_flags = nla_get_u32(tb
6658 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6659
6660 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6661 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6662 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6663 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6664 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6665 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6666 hdd_err("Attribute parsing failed");
6667 return -EINVAL;
6668 }
6669
6670 params.vdev_id = adapter->sessionId;
6671 params.freq = nla_get_u32(tb
6672 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6673 if ((params.freq != 2412) && (params.freq != 2437) &&
6674 (params.freq != 2462)) {
6675 hdd_err("Invalid listening channel: %d", params.freq);
6676 return -EINVAL;
6677 }
6678
6679 params.period = nla_get_u32(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6681 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6682 hdd_err("Invalid period: %d", params.period);
6683 return -EINVAL;
6684 }
6685
6686 params.interval = nla_get_u32(tb
6687 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6688 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6689 hdd_err("Invalid interval: %d", params.interval);
6690 return -EINVAL;
6691 }
6692
6693 params.count = nla_get_u32(tb
6694 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006695 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006696 hdd_err("Invalid count: %d", params.count);
6697 return -EINVAL;
6698 }
6699
6700 params.device_types = nla_data(tb
6701 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6702 if (params.device_types == NULL) {
6703 hdd_err("Invalid device types");
6704 return -EINVAL;
6705 }
6706
6707 params.dev_types_len = nla_len(tb
6708 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6709 if (params.dev_types_len < 8) {
6710 hdd_err("Invalid device type length: %d", params.dev_types_len);
6711 return -EINVAL;
6712 }
6713
6714 params.probe_resp_tmplt = nla_data(tb
6715 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6716 if (params.probe_resp_tmplt == NULL) {
6717 hdd_err("Invalid probe response template");
6718 return -EINVAL;
6719 }
6720
6721 params.probe_resp_len = nla_len(tb
6722 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6723 if (params.probe_resp_len == 0) {
6724 hdd_err("Invalid probe resp template length: %d",
6725 params.probe_resp_len);
6726 return -EINVAL;
6727 }
6728
6729 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6730 params.freq, params.period, params.interval, params.count);
6731
Wu Gao9a704f42017-03-10 18:42:11 +08006732 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006733}
6734
6735
6736/**
6737 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6738 * @wiphy: Pointer to wireless phy
6739 * @wdev: Pointer to wireless device
6740 * @data: Pointer to data
6741 * @data_len: Data length
6742 *
6743 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6744 * to process p2p listen offload start vendor command.
6745 *
6746 * Return: 0 on success, negative errno on failure
6747 */
6748static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6749 struct wireless_dev *wdev,
6750 const void *data,
6751 int data_len)
6752{
6753 int ret = 0;
6754
6755 cds_ssr_protect(__func__);
6756 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6757 data, data_len);
6758 cds_ssr_unprotect(__func__);
6759
6760 return ret;
6761}
6762
6763/**
6764 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6765 * @wiphy: Pointer to wireless phy
6766 * @wdev: Pointer to wireless device
6767 * @data: Pointer to data
6768 * @data_len: Data length
6769 *
6770 * This function is to process the p2p listen offload stop vendor
6771 * command. It invokes WMA API to send command to firmware.
6772 *
6773 * Return: 0 on success, negative errno on failure
6774 */
6775static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6776 struct wireless_dev *wdev,
6777 const void *data,
6778 int data_len)
6779{
Peng Xu8fdaa492016-06-22 10:20:47 -07006780 hdd_adapter_t *adapter;
6781 struct net_device *dev = wdev->netdev;
6782
6783 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6784 hdd_err("Command not allowed in FTM mode");
6785 return -EPERM;
6786 }
6787
6788 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6789 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6790 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6791 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6792 hdd_err("Invalid device mode");
6793 return -EINVAL;
6794 }
6795
Wu Gao9a704f42017-03-10 18:42:11 +08006796 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006797}
6798
6799/**
6800 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6801 * @wiphy: Pointer to wireless phy
6802 * @wdev: Pointer to wireless device
6803 * @data: Pointer to data
6804 * @data_len: Data length
6805 *
6806 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6807 * to process p2p listen offload stop vendor command.
6808 *
6809 * Return: 0 on success, negative errno on failure
6810 */
6811static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6812 struct wireless_dev *wdev,
6813 const void *data,
6814 int data_len)
6815{
6816 int ret = 0;
6817
6818 cds_ssr_protect(__func__);
6819 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6820 data, data_len);
6821 cds_ssr_unprotect(__func__);
6822
6823 return ret;
6824}
6825
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306826/**
6827 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6828 * @wiphy: Pointer to wireless phy
6829 * @wdev: Pointer to wireless device
6830 * @data: Pointer to data
6831 * @data_len: Data length
6832 *
6833 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6834 * to process the conditional channel switch request.
6835 *
6836 * Return: 0 on success, negative errno on failure
6837 */
6838static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6839 struct wireless_dev *wdev,
6840 const void *data,
6841 int data_len)
6842{
6843 int ret;
6844
6845 cds_ssr_protect(__func__);
6846 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6847 data, data_len);
6848 cds_ssr_unprotect(__func__);
6849
6850 return ret;
6851}
6852
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306853/*
6854 * define short names for the global vendor params
6855 * used by __wlan_hdd_cfg80211_bpf_offload()
6856 */
6857#define BPF_INVALID \
6858 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6859#define BPF_SET_RESET \
6860 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6861#define BPF_VERSION \
6862 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6863#define BPF_FILTER_ID \
6864 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6865#define BPF_PACKET_SIZE \
6866 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6867#define BPF_CURRENT_OFFSET \
6868 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6869#define BPF_PROGRAM \
6870 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6871#define BPF_MAX \
6872 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006873
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306874static const struct nla_policy
6875wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6876 [BPF_SET_RESET] = {.type = NLA_U32},
6877 [BPF_VERSION] = {.type = NLA_U32},
6878 [BPF_FILTER_ID] = {.type = NLA_U32},
6879 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6880 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6881 [BPF_PROGRAM] = {.type = NLA_U8},
6882};
6883
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006884struct bpf_offload_priv {
6885 struct sir_bpf_get_offload bpf_get_offload;
6886};
6887
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306888/**
6889 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006890 * @context: opaque context originally passed to SME. HDD always passes
6891 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306892 * @bpf_get_offload: struct for get offload
6893 *
6894 * This function receives the response/data from the lower layer and
6895 * checks to see if the thread is still waiting then post the results to
6896 * upper layer, if the request has timed out then ignore.
6897 *
6898 * Return: None
6899 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006900static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006901 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306902{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006903 struct hdd_request *request;
6904 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306905
6906 ENTER();
6907
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006908 request = hdd_request_get(context);
6909 if (!request) {
6910 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306911 return;
6912 }
6913
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006914 priv = hdd_request_priv(request);
6915 priv->bpf_get_offload = *data;
6916 hdd_request_complete(request);
6917 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306918}
6919
6920/**
6921 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6922 * @hdd_context: hdd_context
6923 * @bpf_get_offload: struct for get offload
6924 *
6925 * Return: 0 on success, error number otherwise.
6926 */
6927static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6928 struct sir_bpf_get_offload *bpf_get_offload)
6929{
6930 struct sk_buff *skb;
6931 uint32_t nl_buf_len;
6932
6933 ENTER();
6934
6935 nl_buf_len = NLMSG_HDRLEN;
6936 nl_buf_len +=
6937 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6938 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6939
6940 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6941 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006942 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306943 return -ENOMEM;
6944 }
6945
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006946 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306947 bpf_get_offload->bpf_version,
6948 bpf_get_offload->max_bytes_for_bpf_inst);
6949
6950 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6951 bpf_get_offload->max_bytes_for_bpf_inst) ||
6952 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006953 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306954 goto nla_put_failure;
6955 }
6956
6957 cfg80211_vendor_cmd_reply(skb);
6958 EXIT();
6959 return 0;
6960
6961nla_put_failure:
6962 kfree_skb(skb);
6963 return -EINVAL;
6964}
6965
6966/**
6967 * hdd_get_bpf_offload - Get BPF offload Capabilities
6968 * @hdd_ctx: Hdd context
6969 *
6970 * Return: 0 on success, errno on failure
6971 */
6972static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6973{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306974 QDF_STATUS status;
6975 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006976 void *cookie;
6977 struct hdd_request *request;
6978 struct bpf_offload_priv *priv;
6979 static const struct hdd_request_params params = {
6980 .priv_size = sizeof(*priv),
6981 .timeout_ms = WLAN_WAIT_TIME_BPF,
6982 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983
6984 ENTER();
6985
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006986 request = hdd_request_alloc(&params);
6987 if (!request) {
6988 hdd_err("Unable to allocate request");
6989 return -EINVAL;
6990 }
6991 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306992
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006993 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6994 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006995 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306996 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006997 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006998 ret = qdf_status_to_os_return(status);
6999 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007001 ret = hdd_request_wait_for_response(request);
7002 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007003 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007004 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307005 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007006 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307007 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007008 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307009 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007010 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307011
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007012cleanup:
7013 /*
7014 * either we never sent a request to SME, we sent a request to
7015 * SME and timed out, or we sent a request to SME, received a
7016 * response from SME, and posted the response to userspace.
7017 * regardless we are done with the request.
7018 */
7019 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307020 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007021
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307022 return ret;
7023}
7024
7025/**
7026 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7027 * @hdd_ctx: Hdd context
7028 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307029 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307030 *
7031 * Return: 0 on success; errno on failure
7032 */
7033static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7034 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307035 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307036{
7037 struct sir_bpf_set_offload *bpf_set_offload;
7038 QDF_STATUS status;
7039 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307040 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307041
7042 ENTER();
7043
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307044 if (adapter->device_mode == QDF_STA_MODE ||
7045 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7046 if (!hdd_conn_is_connected(
7047 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7048 hdd_err("Not in Connected state!");
7049 return -ENOTSUPP;
7050 }
7051 }
7052
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307053 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7054 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007055 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307056 return -ENOMEM;
7057 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307058
7059 /* Parse and fetch bpf packet size */
7060 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007061 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307062 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307063 goto fail;
7064 }
7065 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7066
7067 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007068 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307069 goto post_sme;
7070 }
7071
7072 /* Parse and fetch bpf program */
7073 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007074 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307075 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076 goto fail;
7077 }
7078
7079 prog_len = nla_len(tb[BPF_PROGRAM]);
7080 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307081
7082 if (bpf_set_offload->program == NULL) {
7083 hdd_err("qdf_mem_malloc failed for bpf offload program");
7084 ret = -ENOMEM;
7085 goto fail;
7086 }
7087
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307088 bpf_set_offload->current_length = prog_len;
7089 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307090 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307091
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007092 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007093 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307094 bpf_set_offload->program, prog_len);
7095
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307096 /* Parse and fetch filter Id */
7097 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007098 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307099 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307100 goto fail;
7101 }
7102 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7103
7104 /* Parse and fetch current offset */
7105 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007106 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307107 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108 goto fail;
7109 }
7110 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7111
7112post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007113 hdd_debug("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 +05307114 bpf_set_offload->session_id,
7115 bpf_set_offload->version,
7116 bpf_set_offload->filter_id,
7117 bpf_set_offload->total_length,
7118 bpf_set_offload->current_length,
7119 bpf_set_offload->current_offset);
7120
7121 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7122 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007123 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307124 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307125 goto fail;
7126 }
7127 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307128
7129fail:
7130 if (bpf_set_offload->current_length)
7131 qdf_mem_free(bpf_set_offload->program);
7132 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307133 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307134}
7135
7136/**
7137 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7138 * @wiphy: wiphy structure pointer
7139 * @wdev: Wireless device structure pointer
7140 * @data: Pointer to the data received
7141 * @data_len: Length of @data
7142 *
7143 * Return: 0 on success; errno on failure
7144 */
7145static int
7146__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7147 struct wireless_dev *wdev,
7148 const void *data, int data_len)
7149{
7150 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7151 struct net_device *dev = wdev->netdev;
7152 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7153 struct nlattr *tb[BPF_MAX + 1];
7154 int ret_val, packet_filter_subcmd;
7155
7156 ENTER();
7157
7158 ret_val = wlan_hdd_validate_context(hdd_ctx);
7159 if (ret_val)
7160 return ret_val;
7161
7162 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007163 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307164 return -EINVAL;
7165 }
7166
7167 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007168 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307169 return -ENOTSUPP;
7170 }
7171
7172 if (nla_parse(tb, BPF_MAX, data, data_len,
7173 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007174 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307175 return -EINVAL;
7176 }
7177
7178 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007179 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307180 return -EINVAL;
7181 }
7182
7183 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7184
7185 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7186 return hdd_get_bpf_offload(hdd_ctx);
7187 else
7188 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307189 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307190}
7191
7192/**
7193 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7194 * @wiphy: wiphy structure pointer
7195 * @wdev: Wireless device structure pointer
7196 * @data: Pointer to the data received
7197 * @data_len: Length of @data
7198 *
7199 * Return: 0 on success; errno on failure
7200 */
7201
7202static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7203 struct wireless_dev *wdev,
7204 const void *data, int data_len)
7205{
7206 int ret;
7207
7208 cds_ssr_protect(__func__);
7209 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7210 cds_ssr_unprotect(__func__);
7211
7212 return ret;
7213}
7214
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307215/**
7216 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7217 * @pre_cac_adapter: AP adapter used for pre cac
7218 * @status: Status (true or false)
7219 * @handle: Global handle
7220 *
7221 * Sets the status of pre cac i.e., whether the pre cac is active or not
7222 *
7223 * Return: Zero on success, non-zero on failure
7224 */
7225static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7226 bool status, tHalHandle handle)
7227{
7228 QDF_STATUS ret;
7229
7230 ret = wlan_sap_set_pre_cac_status(
7231 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7232 if (QDF_IS_STATUS_ERROR(ret))
7233 return -EINVAL;
7234
7235 return 0;
7236}
7237
7238/**
7239 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7240 * @ap_adapter: AP adapter
7241 * @chan_before_pre_cac: Channel
7242 *
7243 * Saves the channel which the AP was beaconing on before moving to the pre
7244 * cac channel. If radar is detected on the pre cac channel, this saved
7245 * channel will be used for AP operations.
7246 *
7247 * Return: Zero on success, non-zero on failure
7248 */
7249static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7250 uint8_t chan_before_pre_cac)
7251{
7252 QDF_STATUS ret;
7253
7254 ret = wlan_sap_set_chan_before_pre_cac(
7255 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7256 if (QDF_IS_STATUS_ERROR(ret))
7257 return -EINVAL;
7258
7259 return 0;
7260}
7261
7262/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307263 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7264 * are in nol list from provided channel list
7265 * @adapter: AP adapter
7266 * @channel_count: channel count
7267 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307268 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307269 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307270 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307271static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7272 uint32_t *channel_count,
7273 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307274{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307275 uint8_t i, j;
7276 uint32_t nol_len = 0;
7277 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7278 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7279 uint32_t chan_count;
7280 bool found;
7281 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307282
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307283 if (!hdd_ctx) {
7284 hdd_err("hdd ctx not found");
7285 *channel_count = 0;
7286 return;
7287 }
7288
7289 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7290 hdd_err("invalid channel count %d", *channel_count);
7291 return;
7292 }
7293
7294 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7295 if (nol_len == 0)
7296 return;
7297
7298 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7299 chan_count = *channel_count;
7300 qdf_mem_zero(channel_list, chan_count);
7301 *channel_count = 0;
7302
7303 for (i = 0 ; i < chan_count; i++) {
7304 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7305 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7306 continue;
7307 found = false;
7308 for (j = 0; j < nol_len; j++) {
7309 if (tmp_chan_list[i] == nol[j]) {
7310 found = true;
7311 hdd_notice("skipped channel %d due to nol",
7312 nol[j]);
7313 break;
7314 }
7315 }
7316 if (!found) {
7317 channel_list[*channel_count] = tmp_chan_list[i];
7318 *channel_count = *channel_count + 1;
7319 }
7320 }
7321}
7322
7323int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7324 uint32_t *channel_count,
7325 uint8_t *channel_list)
7326{
7327 tsap_Config_t *sap_config;
7328
7329 sap_config = &adapter->sessionCtx.ap.sapConfig;
7330
7331 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7332 sap_config->acs_cfg.ch_list_count);
7333 *channel_count = sap_config->acs_cfg.ch_list_count;
7334 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7335
7336 if (*channel_count == 0) {
7337 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307338 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307339 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307340
7341 return 0;
7342}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307343
7344/**
7345 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7346 * @hdd_ctx: HDD context
7347 * @ap_adapter: AP adapter
7348 * @channel: Channel requested by userspace
7349 * @pre_cac_chan: Pointer to the pre CAC channel
7350 *
7351 * Validates the channel provided by userspace. If user provided channel 0,
7352 * a valid outdoor channel must be selected from the regulatory channel.
7353 *
7354 * Return: Zero on success and non zero value on error
7355 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007356static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7357 hdd_adapter_t *ap_adapter,
7358 uint8_t channel,
7359 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307360{
7361 uint32_t i, j;
7362 QDF_STATUS status;
7363 int ret;
7364 uint8_t nol[QDF_MAX_NUM_CHAN];
7365 uint32_t nol_len = 0, weight_len = 0;
7366 bool found;
7367 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7368 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7369 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7370
7371 if (0 == channel) {
7372 /* Channel is not obtained from PCL because PCL may not have
7373 * the entire channel list. For example: if SAP is up on
7374 * channel 6 and PCL is queried for the next SAP interface,
7375 * if SCC is preferred, the PCL will contain only the channel
7376 * 6. But, we are in need of a DFS channel. So, going with the
7377 * first channel from the valid channel list.
7378 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007379 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7380 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307381 if (QDF_IS_STATUS_ERROR(status)) {
7382 hdd_err("Failed to get channel list");
7383 return -EINVAL;
7384 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007385 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307386 pcl_weights, weight_len);
7387 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7388 for (i = 0; i < len; i++) {
7389 found = false;
7390 for (j = 0; j < nol_len; j++) {
7391 if (channel_list[i] == nol[j]) {
7392 found = true;
7393 break;
7394 }
7395 }
7396 if (found)
7397 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007398 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7399 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307400 *pre_cac_chan = channel_list[i];
7401 break;
7402 }
7403 }
7404 if (*pre_cac_chan == 0) {
7405 hdd_err("unable to find outdoor channel");
7406 return -EINVAL;
7407 }
7408 } else {
7409 /* Only when driver selects a channel, check is done for
7410 * unnsafe and NOL channels. When user provides a fixed channel
7411 * the user is expected to take care of this.
7412 */
7413 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007414 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307415 hdd_err("Invalid channel for pre cac:%d", channel);
7416 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307417 }
Jeff Johnson68755312017-02-10 11:46:55 -08007418
7419 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307420 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007421 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307422 return 0;
7423}
7424
7425/**
7426 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7427 * @channel: Channel option provided by userspace
7428 *
7429 * Sets the driver to the required hardware mode and start an adapater for
7430 * pre CAC which will mimic an AP.
7431 *
7432 * Return: Zero on success, non-zero value on error
7433 */
7434int wlan_hdd_request_pre_cac(uint8_t channel)
7435{
Krunal Sonib37bb352016-12-20 14:12:21 -08007436 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307437 hdd_context_t *hdd_ctx;
7438 int ret;
7439 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7440 hdd_ap_ctx_t *hdd_ap_ctx;
7441 QDF_STATUS status;
7442 struct wiphy *wiphy;
7443 struct net_device *dev;
7444 struct cfg80211_chan_def chandef;
7445 enum nl80211_channel_type channel_type;
7446 uint32_t freq;
7447 struct ieee80211_channel *chan;
7448 tHalHandle handle;
7449 bool val;
7450
7451 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7452 if (0 != wlan_hdd_validate_context(hdd_ctx))
7453 return -EINVAL;
7454
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007455 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307456 hdd_err("pre cac not allowed in concurrency");
7457 return -EINVAL;
7458 }
7459
7460 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7461 if (!ap_adapter) {
7462 hdd_err("unable to get SAP adapter");
7463 return -EINVAL;
7464 }
7465
7466 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7467 if (!handle) {
7468 hdd_err("Invalid handle");
7469 return -EINVAL;
7470 }
7471
7472 val = wlan_sap_is_pre_cac_active(handle);
7473 if (val) {
7474 hdd_err("pre cac is already in progress");
7475 return -EINVAL;
7476 }
7477
7478 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7479 if (!hdd_ap_ctx) {
7480 hdd_err("SAP context is NULL");
7481 return -EINVAL;
7482 }
7483
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007484 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7485 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307486 hdd_err("SAP is already on DFS channel:%d",
7487 hdd_ap_ctx->operatingChannel);
7488 return -EINVAL;
7489 }
7490
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007491 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307492 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7493 hdd_ap_ctx->operatingChannel);
7494 return -EINVAL;
7495 }
7496
Krunal Sonib37bb352016-12-20 14:12:21 -08007497 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7498 if (!mac_addr) {
7499 hdd_err("can't add virtual intf: Not getting valid mac addr");
7500 return -EINVAL;
7501 }
7502
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007503 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307504
7505 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7506 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007507 if (ret != 0) {
7508 hdd_err("can't validate pre-cac channel");
7509 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307510 }
7511
7512 hdd_debug("starting pre cac SAP adapter");
7513
7514 /* Starting a SAP adapter:
7515 * Instead of opening an adapter, we could just do a SME open session
7516 * for AP type. But, start BSS would still need an adapter.
7517 * So, this option is not taken.
7518 *
7519 * hdd open adapter is going to register this precac interface with
7520 * user space. This interface though exposed to user space will be in
7521 * DOWN state. Consideration was done to avoid this registration to the
7522 * user space. But, as part of SAP operations multiple events are sent
7523 * to user space. Some of these events received from unregistered
7524 * interface was causing crashes. So, retaining the registration.
7525 *
7526 * So, this interface would remain registered and will remain in DOWN
7527 * state for the CAC duration. We will add notes in the feature
7528 * announcement to not use this temporary interface for any activity
7529 * from user space.
7530 */
7531 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007532 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307533 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307534 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007535 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307536 }
7537
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307538 /*
7539 * This interface is internally created by the driver. So, no interface
7540 * up comes for this interface from user space and hence starting
7541 * the adapter internally.
7542 */
7543 if (hdd_start_adapter(pre_cac_adapter)) {
7544 hdd_err("error starting the pre cac adapter");
7545 goto close_pre_cac_adapter;
7546 }
7547
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307548 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7549
7550 wiphy = hdd_ctx->wiphy;
7551 dev = pre_cac_adapter->dev;
7552
7553 /* Since this is only a dummy interface lets us use the IEs from the
7554 * other active SAP interface. In regular scenarios, these IEs would
7555 * come from the user space entity
7556 */
7557 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7558 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7559 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7560 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307561 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307562 }
7563 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7564 ap_adapter->sessionCtx.ap.beacon,
7565 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7566 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7567 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7568 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7569 ap_adapter->sessionCtx.ap.sapConfig.authType;
7570
7571 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7572 * to operate on the same bandwidth as that of the 2.4GHz operations.
7573 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7574 */
7575 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7576 case CH_WIDTH_20MHZ:
7577 channel_type = NL80211_CHAN_HT20;
7578 break;
7579 case CH_WIDTH_40MHZ:
7580 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7581 ap_adapter->sessionCtx.ap.sapConfig.channel)
7582 channel_type = NL80211_CHAN_HT40PLUS;
7583 else
7584 channel_type = NL80211_CHAN_HT40MINUS;
7585 break;
7586 default:
7587 channel_type = NL80211_CHAN_NO_HT;
7588 break;
7589 }
7590
7591 freq = cds_chan_to_freq(pre_cac_chan);
7592 chan = __ieee80211_get_channel(wiphy, freq);
7593 if (!chan) {
7594 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307595 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307596 }
7597
7598 cfg80211_chandef_create(&chandef, chan, channel_type);
7599
7600 hdd_debug("orig width:%d channel_type:%d freq:%d",
7601 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7602 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007603 /*
7604 * Doing update after opening and starting pre-cac adapter will make
7605 * sure that driver won't do hardware mode change if there are any
7606 * initial hick-ups or issues in pre-cac adapter's configuration.
7607 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7608 * connection update should result in DBS mode
7609 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007610 status = policy_mgr_update_and_wait_for_connection_update(
7611 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007612 ap_adapter->sessionId,
7613 pre_cac_chan,
7614 SIR_UPDATE_REASON_PRE_CAC);
7615 if (QDF_IS_STATUS_ERROR(status)) {
7616 hdd_err("error in moving to DBS mode");
7617 goto stop_close_pre_cac_adapter;
7618 }
7619
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307620
7621 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7622 if (0 != ret) {
7623 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307624 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307625 }
7626
7627 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7628 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007629 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307630 if (QDF_IS_STATUS_ERROR(status)) {
7631 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307632 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307633 }
7634
7635 /*
7636 * The pre cac status is set here. But, it would not be reset explicitly
7637 * anywhere, since after the pre cac success/failure, the pre cac
7638 * adapter itself would be removed.
7639 */
7640 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7641 if (0 != ret) {
7642 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307643 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307644 }
7645
7646 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7647 hdd_ap_ctx->operatingChannel);
7648 if (0 != ret) {
7649 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307650 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307651 }
7652
7653 ap_adapter->pre_cac_chan = pre_cac_chan;
7654
7655 return 0;
7656
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307657stop_close_pre_cac_adapter:
7658 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307659 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7660 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307661close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307662 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007663release_intf_addr_and_return_failure:
7664 /*
7665 * Release the interface address as the adapter
7666 * failed to start, if you don't release then next
7667 * adapter which is trying to come wouldn't get valid
7668 * mac address. Remember we have limited pool of mac addresses
7669 */
7670 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307671 return -EINVAL;
7672}
7673
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307674static const struct nla_policy
7675wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7676 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7677};
7678
Agrawal Ashish65634612016-08-18 13:24:32 +05307679static const struct nla_policy
7680wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7681 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7682 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7683};
7684
7685/**
7686 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7687 * @wiphy: Pointer to wireless phy
7688 * @wdev: Pointer to wireless device
7689 * @data: Pointer to data
7690 * @data_len: Length of @data
7691 *
7692 * This function parses the incoming NL vendor command data attributes and
7693 * updates the SAP context about channel_hint and DFS mode.
7694 * If channel_hint is set, SAP will choose that channel
7695 * as operating channel.
7696 *
7697 * If DFS mode is enabled, driver will include DFS channels
7698 * in ACS else driver will skip DFS channels.
7699 *
7700 * Return: 0 on success, negative errno on failure
7701 */
7702static int
7703__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7704 struct wireless_dev *wdev,
7705 const void *data, int data_len)
7706{
7707 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7708 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7709 int ret;
7710 struct acs_dfs_policy *acs_policy;
7711 int mode = DFS_MODE_NONE;
7712 int channel_hint = 0;
7713
7714 ENTER_DEV(wdev->netdev);
7715
7716 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7717 hdd_err("Command not allowed in FTM mode");
7718 return -EINVAL;
7719 }
7720
7721 ret = wlan_hdd_validate_context(hdd_ctx);
7722 if (0 != ret)
7723 return ret;
7724
7725 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7726 data, data_len,
7727 wlan_hdd_set_acs_dfs_config_policy)) {
7728 hdd_err("invalid attr");
7729 return -EINVAL;
7730 }
7731
7732 acs_policy = &hdd_ctx->acs_policy;
7733 /*
7734 * SCM sends this attribute to restrict SAP from choosing
7735 * DFS channels from ACS.
7736 */
7737 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7738 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7739
7740 if (!IS_DFS_MODE_VALID(mode)) {
7741 hdd_err("attr acs dfs mode is not valid");
7742 return -EINVAL;
7743 }
7744 acs_policy->acs_dfs_mode = mode;
7745
7746 /*
7747 * SCM sends this attribute to provide an active channel,
7748 * to skip redundant ACS between drivers, and save driver start up time
7749 */
7750 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7751 channel_hint = nla_get_u8(
7752 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7753
7754 if (!IS_CHANNEL_VALID(channel_hint)) {
7755 hdd_err("acs channel is not valid");
7756 return -EINVAL;
7757 }
7758 acs_policy->acs_channel = channel_hint;
7759
7760 return 0;
7761}
7762
7763/**
7764 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7765 * @wiphy: wiphy structure pointer
7766 * @wdev: Wireless device structure pointer
7767 * @data: Pointer to the data received
7768 * @data_len: Length of @data
7769 *
7770 * This function parses the incoming NL vendor command data attributes and
7771 * updates the SAP context about channel_hint and DFS mode.
7772 *
7773 * Return: 0 on success; errno on failure
7774 */
7775static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7776 struct wireless_dev *wdev,
7777 const void *data, int data_len)
7778{
7779 int ret;
7780
7781 cds_ssr_protect(__func__);
7782 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7783 cds_ssr_unprotect(__func__);
7784
7785 return ret;
7786}
7787
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307788/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307789 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7790 * @mode : cfg80211 dfs mode
7791 *
7792 * Return: return csr sta roam dfs mode else return NONE
7793 */
7794static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7795 enum dfs_mode mode)
7796{
7797 switch (mode) {
7798 case DFS_MODE_ENABLE:
7799 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7800 break;
7801 case DFS_MODE_DISABLE:
7802 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7803 break;
7804 case DFS_MODE_DEPRIORITIZE:
7805 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7806 break;
7807 default:
7808 hdd_err("STA Roam policy dfs mode is NONE");
7809 return CSR_STA_ROAM_POLICY_NONE;
7810 }
7811}
7812
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307813/*
7814 * hdd_get_sap_operating_band: Get current operating channel
7815 * for sap.
7816 * @hdd_ctx: hdd context
7817 *
7818 * Return : Corresponding band for SAP operating channel
7819 */
7820uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7821{
7822 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7823 QDF_STATUS status;
7824 hdd_adapter_t *adapter;
7825 uint8_t operating_channel = 0;
7826 uint8_t sap_operating_band = 0;
7827 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7828 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7829 adapter = adapter_node->pAdapter;
7830
7831 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7832 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7833 &next);
7834 adapter_node = next;
7835 continue;
7836 }
7837 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7838 if (IS_24G_CH(operating_channel))
7839 sap_operating_band = eCSR_BAND_24;
7840 else if (IS_5G_CH(operating_channel))
7841 sap_operating_band = eCSR_BAND_5G;
7842 else
7843 sap_operating_band = eCSR_BAND_ALL;
7844 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7845 &next);
bings373b99b2017-01-23 10:35:08 +08007846 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307847 }
7848 return sap_operating_band;
7849}
7850
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307851static const struct nla_policy
7852wlan_hdd_set_sta_roam_config_policy[
7853QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7854 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7855 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7856};
7857
7858/**
7859 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7860 * for station connection or roaming.
7861 * @wiphy: Pointer to wireless phy
7862 * @wdev: Pointer to wireless device
7863 * @data: Pointer to data
7864 * @data_len: Length of @data
7865 *
7866 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7867 * channels needs to be skipped in scanning or not.
7868 * If dfs_mode is disabled, driver will not scan DFS channels.
7869 * If skip_unsafe_channels is set, driver will skip unsafe channels
7870 * in Scanning.
7871 *
7872 * Return: 0 on success, negative errno on failure
7873 */
7874static int
7875__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7876 struct wireless_dev *wdev,
7877 const void *data, int data_len)
7878{
7879 struct net_device *dev = wdev->netdev;
7880 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7881 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7882 struct nlattr *tb[
7883 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7884 int ret;
7885 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7886 enum dfs_mode mode = DFS_MODE_NONE;
7887 bool skip_unsafe_channels = false;
7888 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307889 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307890
7891 ENTER_DEV(dev);
7892
7893 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7894 hdd_err("Command not allowed in FTM mode");
7895 return -EINVAL;
7896 }
7897
7898 ret = wlan_hdd_validate_context(hdd_ctx);
7899 if (0 != ret)
7900 return ret;
7901 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7902 data, data_len,
7903 wlan_hdd_set_sta_roam_config_policy)) {
7904 hdd_err("invalid attr");
7905 return -EINVAL;
7906 }
7907 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7908 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7909 if (!IS_DFS_MODE_VALID(mode)) {
7910 hdd_err("attr sta roam dfs mode policy is not valid");
7911 return -EINVAL;
7912 }
7913
7914 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7915
7916 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7917 skip_unsafe_channels = nla_get_u8(
7918 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307919 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307920 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307921 skip_unsafe_channels, adapter->sessionId,
7922 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307923
7924 if (!QDF_IS_STATUS_SUCCESS(status)) {
7925 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7926 return -EINVAL;
7927 }
7928 return 0;
7929}
7930
7931/**
7932 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7933 * connection and roaming for station.
7934 * @wiphy: wiphy structure pointer
7935 * @wdev: Wireless device structure pointer
7936 * @data: Pointer to the data received
7937 * @data_len: Length of @data
7938 *
7939 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7940 * channels needs to be skipped in scanning or not.
7941 * If dfs_mode is disabled, driver will not scan DFS channels.
7942 * If skip_unsafe_channels is set, driver will skip unsafe channels
7943 * in Scanning.
7944 * Return: 0 on success; errno on failure
7945 */
7946static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7947 struct wireless_dev *wdev,
7948 const void *data, int data_len)
7949{
7950 int ret;
7951
7952 cds_ssr_protect(__func__);
7953 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7954 cds_ssr_unprotect(__func__);
7955
7956 return ret;
7957}
7958
Agrawal Ashish467dde42016-09-08 18:44:22 +05307959#ifdef FEATURE_WLAN_CH_AVOID
7960/**
7961 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7962 * is on unsafe channel.
7963 * @wiphy: wiphy structure pointer
7964 * @wdev: Wireless device structure pointer
7965 * @data: Pointer to the data received
7966 * @data_len: Length of @data
7967 *
7968 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7969 * on any of unsafe channels.
7970 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7971 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7972 *
7973 * Return: 0 on success; errno on failure
7974 */
7975static int
7976__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7977 struct wireless_dev *wdev,
7978 const void *data, int data_len)
7979{
7980 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7981 int ret;
7982 uint16_t unsafe_channel_count;
7983 int unsafe_channel_index;
7984 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7985
7986 ENTER_DEV(wdev->netdev);
7987
7988 if (!qdf_ctx) {
7989 cds_err("qdf_ctx is NULL");
7990 return -EINVAL;
7991 }
7992
7993 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7994 hdd_err("Command not allowed in FTM mode");
7995 return -EINVAL;
7996 }
7997
7998 ret = wlan_hdd_validate_context(hdd_ctx);
7999 if (0 != ret)
8000 return ret;
8001 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8002 &(hdd_ctx->unsafe_channel_count),
8003 sizeof(hdd_ctx->unsafe_channel_list));
8004
8005 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8006 (uint16_t)NUM_CHANNELS);
8007 for (unsafe_channel_index = 0;
8008 unsafe_channel_index < unsafe_channel_count;
8009 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008010 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308011 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8012 }
8013 hdd_unsafe_channel_restart_sap(hdd_ctx);
8014 return 0;
8015}
8016
8017/**
8018 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8019 * is on unsafe channel.
8020 * @wiphy: wiphy structure pointer
8021 * @wdev: Wireless device structure pointer
8022 * @data: Pointer to the data received
8023 * @data_len: Length of @data
8024 *
8025 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8026 * on any of unsafe channels.
8027 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8028 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8029 *
8030 * Return: 0 on success; errno on failure
8031 */
8032static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8033 struct wireless_dev *wdev,
8034 const void *data, int data_len)
8035{
8036 int ret;
8037
8038 cds_ssr_protect(__func__);
8039 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8040 cds_ssr_unprotect(__func__);
8041
8042 return ret;
8043}
8044
8045#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308046/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308047 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8048 * SAP is on unsafe channel.
8049 * @wiphy: wiphy structure pointer
8050 * @wdev: Wireless device structure pointer
8051 * @data: Pointer to the data received
8052 * @data_len: Length of @data
8053 *
8054 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8055 * driver.
8056 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8057 * will initiate restart of sap.
8058 *
8059 * Return: 0 on success; errno on failure
8060 */
8061static int
8062__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8063 struct wireless_dev *wdev,
8064 const void *data, int data_len)
8065{
8066 struct net_device *ndev = wdev->netdev;
8067 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8068 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8069 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8070 uint8_t config_channel = 0;
8071 hdd_ap_ctx_t *ap_ctx;
8072 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308073 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308074
8075 ENTER();
8076
8077 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008078 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308079 return -EINVAL;
8080 }
8081
8082 ret = wlan_hdd_validate_context(hdd_ctx);
8083 if (0 != ret)
8084 return -EINVAL;
8085
8086 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8087 data, data_len,
8088 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008089 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308090 return -EINVAL;
8091 }
8092
8093 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8094 if (!test_bit(SOFTAP_BSS_STARTED,
8095 &hostapd_adapter->event_flags)) {
8096 hdd_err("SAP is not started yet. Restart sap will be invalid");
8097 return -EINVAL;
8098 }
8099
8100 config_channel =
8101 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8102
8103 if (!((IS_24G_CH(config_channel)) ||
8104 (IS_5G_CH(config_channel)))) {
8105 hdd_err("Channel %d is not valid to restart SAP",
8106 config_channel);
8107 return -ENOTSUPP;
8108 }
8109
8110 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8111 ap_ctx->sapConfig.channel = config_channel;
8112 ap_ctx->sapConfig.ch_params.ch_width =
8113 ap_ctx->sapConfig.ch_width_orig;
8114
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008115 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8116 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308117 ap_ctx->sapConfig.sec_ch,
8118 &ap_ctx->sapConfig.ch_params);
8119
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008120 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308121 }
8122
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308123 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8124 uint32_t freq_len, i;
8125 uint32_t *freq;
8126 uint8_t chans[QDF_MAX_NUM_CHAN];
8127
8128 hdd_debug("setting mandatory freq/chan list");
8129
8130 freq_len = nla_len(
8131 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8132 sizeof(uint32_t);
8133
8134 if (freq_len > QDF_MAX_NUM_CHAN) {
8135 hdd_err("insufficient space to hold channels");
8136 return -ENOMEM;
8137 }
8138
8139 freq = nla_data(
8140 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8141
8142 hdd_debug("freq_len=%d", freq_len);
8143
8144 for (i = 0; i < freq_len; i++) {
8145 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8146 hdd_debug("freq[%d]=%d", i, freq[i]);
8147 }
8148
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008149 status = policy_mgr_set_sap_mandatory_channels(
8150 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308151 if (QDF_IS_STATUS_ERROR(status))
8152 return -EINVAL;
8153 }
8154
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308155 return 0;
8156}
8157
8158/**
8159 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8160 * @wiphy: wiphy structure pointer
8161 * @wdev: Wireless device structure pointer
8162 * @data: Pointer to the data received
8163 * @data_len: Length of @data
8164 *
8165 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8166 * driver.
8167 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8168 * will initiate restart of sap.
8169 *
8170 * Return: 0 on success; errno on failure
8171 */
8172static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8173 struct wireless_dev *wdev,
8174 const void *data, int data_len)
8175{
8176 int ret;
8177
8178 cds_ssr_protect(__func__);
8179 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8180 wdev, data, data_len);
8181 cds_ssr_unprotect(__func__);
8182
8183 return ret;
8184}
8185
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308186#undef BPF_INVALID
8187#undef BPF_SET_RESET
8188#undef BPF_VERSION
8189#undef BPF_ID
8190#undef BPF_PACKET_SIZE
8191#undef BPF_CURRENT_OFFSET
8192#undef BPF_PROGRAM
8193#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308194
8195/**
8196 * define short names for the global vendor params
8197 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8198 */
8199#define PARAM_TOTAL_CMD_EVENT_WAKE \
8200 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8201#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8202 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8203#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8204 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8205#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8206 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8207#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8208 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8209#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8210 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8211#define PARAM_TOTAL_RX_DATA_WAKE \
8212 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8213#define PARAM_RX_UNICAST_CNT \
8214 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8215#define PARAM_RX_MULTICAST_CNT \
8216 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8217#define PARAM_RX_BROADCAST_CNT \
8218 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8219#define PARAM_ICMP_PKT \
8220 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8221#define PARAM_ICMP6_PKT \
8222 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8223#define PARAM_ICMP6_RA \
8224 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8225#define PARAM_ICMP6_NA \
8226 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8227#define PARAM_ICMP6_NS \
8228 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8229#define PARAM_ICMP4_RX_MULTICAST_CNT \
8230 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8231#define PARAM_ICMP6_RX_MULTICAST_CNT \
8232 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8233#define PARAM_OTHER_RX_MULTICAST_CNT \
8234 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308235#define PARAM_RSSI_BREACH_CNT \
8236 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8237#define PARAM_LOW_RSSI_CNT \
8238 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8239#define PARAM_GSCAN_CNT \
8240 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8241#define PARAM_PNO_COMPLETE_CNT \
8242 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8243#define PARAM_PNO_MATCH_CNT \
8244 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8245
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308246
8247
8248/**
8249 * hdd_send_wakelock_stats() - API to send wakelock stats
8250 * @ctx: context to be passed to callback
8251 * @data: data passed to callback
8252 *
8253 * This function is used to send wake lock stats to HAL layer
8254 *
8255 * Return: 0 on success, error number otherwise.
8256 */
8257static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8258 const struct sir_wake_lock_stats *data)
8259{
8260 struct sk_buff *skb;
8261 uint32_t nl_buf_len;
8262 uint32_t total_rx_data_wake, rx_multicast_cnt;
8263 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308264 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308265
8266 ENTER();
8267
8268 nl_buf_len = NLMSG_HDRLEN;
8269 nl_buf_len +=
8270 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8271 (NLMSG_HDRLEN + sizeof(uint32_t));
8272
8273 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8274
8275 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008276 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308277 return -ENOMEM;
8278 }
8279
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008280 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308281 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008282 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308283 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008284 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308285 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008286 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008288 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308289 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008290 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308291 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008292 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308293 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008294 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8295 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308296 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008297 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308298 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008299 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308300 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008301 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308302 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008303 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308304 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008305 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308306 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308307
8308 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308309 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308310
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308311 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308312 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308313
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308314 rx_multicast_cnt =
8315 data->wow_ipv4_mcast_wake_up_count +
8316 ipv6_rx_multicast_addr_cnt;
8317
8318 total_rx_data_wake =
8319 data->wow_ucast_wake_up_count +
8320 data->wow_bcast_wake_up_count +
8321 rx_multicast_cnt;
8322
8323 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8324 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8325 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8326 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8327 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8328 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8329 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8330 total_rx_data_wake) ||
8331 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8332 data->wow_ucast_wake_up_count) ||
8333 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8334 rx_multicast_cnt) ||
8335 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8336 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308337 nla_put_u32(skb, PARAM_ICMP_PKT,
8338 data->wow_icmpv4_count) ||
8339 nla_put_u32(skb, PARAM_ICMP6_PKT,
8340 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308341 nla_put_u32(skb, PARAM_ICMP6_RA,
8342 data->wow_ipv6_mcast_ra_stats) ||
8343 nla_put_u32(skb, PARAM_ICMP6_NA,
8344 data->wow_ipv6_mcast_na_stats) ||
8345 nla_put_u32(skb, PARAM_ICMP6_NS,
8346 data->wow_ipv6_mcast_ns_stats) ||
8347 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8348 data->wow_ipv4_mcast_wake_up_count) ||
8349 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8350 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308351 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8352 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8353 data->wow_rssi_breach_wake_up_count) ||
8354 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8355 data->wow_low_rssi_wake_up_count) ||
8356 nla_put_u32(skb, PARAM_GSCAN_CNT,
8357 data->wow_gscan_wake_up_count) ||
8358 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8359 data->wow_pno_complete_wake_up_count) ||
8360 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8361 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008362 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308363 goto nla_put_failure;
8364 }
8365
8366 cfg80211_vendor_cmd_reply(skb);
8367
8368 EXIT();
8369 return 0;
8370
8371nla_put_failure:
8372 kfree_skb(skb);
8373 return -EINVAL;
8374}
8375
8376/**
8377 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8378 * @wiphy: wiphy pointer
8379 * @wdev: pointer to struct wireless_dev
8380 * @data: pointer to incoming NL vendor data
8381 * @data_len: length of @data
8382 *
8383 * This function parses the incoming NL vendor command data attributes and
8384 * invokes the SME Api and blocks on a completion variable.
8385 * WMA copies required data and invokes callback
8386 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8387 *
8388 * Return: 0 on success; error number otherwise.
8389 */
8390static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8391 struct wireless_dev *wdev,
8392 const void *data,
8393 int data_len)
8394{
8395 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8396 int status, ret;
8397 struct sir_wake_lock_stats wake_lock_stats;
8398 QDF_STATUS qdf_status;
8399
8400 ENTER();
8401
8402 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008403 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308404 return -EINVAL;
8405 }
8406
8407 status = wlan_hdd_validate_context(hdd_ctx);
8408 if (0 != status)
8409 return -EINVAL;
8410
8411 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8412 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008413 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308414 return -EINVAL;
8415 }
8416
8417 ret = hdd_send_wakelock_stats(hdd_ctx,
8418 &wake_lock_stats);
8419 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008420 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308421
8422 EXIT();
8423 return ret;
8424}
8425
8426/**
8427 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8428 * @wiphy: wiphy pointer
8429 * @wdev: pointer to struct wireless_dev
8430 * @data: pointer to incoming NL vendor data
8431 * @data_len: length of @data
8432 *
8433 * This function parses the incoming NL vendor command data attributes and
8434 * invokes the SME Api and blocks on a completion variable.
8435 * WMA copies required data and invokes callback
8436 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8437 *
8438 * Return: 0 on success; error number otherwise.
8439 */
8440static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8441 struct wireless_dev *wdev,
8442 const void *data, int data_len)
8443{
8444 int ret;
8445
8446 cds_ssr_protect(__func__);
8447 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8448 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008449 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308450
8451 return ret;
8452}
8453
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308454/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308455 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8456 * @wiphy: wiphy structure pointer
8457 * @wdev: Wireless device structure pointer
8458 * @data: Pointer to the data received
8459 * @data_len: Length of @data
8460 *
8461 * This function reads wmi max bus size and fill in the skb with
8462 * NL attributes and send up the NL event.
8463 * Return: 0 on success; errno on failure
8464 */
8465static int
8466__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8467 struct wireless_dev *wdev,
8468 const void *data, int data_len)
8469{
8470 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8471 int ret_val;
8472 struct sk_buff *skb;
8473 uint32_t nl_buf_len;
8474
8475 ENTER();
8476
8477 ret_val = wlan_hdd_validate_context(hdd_ctx);
8478 if (ret_val)
8479 return ret_val;
8480
8481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8482 hdd_err("Command not allowed in FTM mode");
8483 return -EINVAL;
8484 }
8485
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008486 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308487
8488 nl_buf_len = NLMSG_HDRLEN;
8489 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8490
8491 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8492 if (!skb) {
8493 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8494 return -ENOMEM;
8495 }
8496
8497 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8498 hdd_ctx->wmi_max_len)) {
8499 hdd_err("nla put failure");
8500 goto nla_put_failure;
8501 }
8502
8503 cfg80211_vendor_cmd_reply(skb);
8504
8505 EXIT();
8506
8507 return 0;
8508
8509nla_put_failure:
8510 kfree_skb(skb);
8511 return -EINVAL;
8512}
8513
8514/**
8515 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8516 * @wiphy: wiphy structure pointer
8517 * @wdev: Wireless device structure pointer
8518 * @data: Pointer to the data received
8519 * @data_len: Length of @data
8520 *
8521 * Return: 0 on success; errno on failure
8522 */
8523static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8524 struct wireless_dev *wdev,
8525 const void *data, int data_len)
8526{
8527 int ret;
8528
8529 cds_ssr_protect(__func__);
8530 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8531 cds_ssr_unprotect(__func__);
8532
8533 return ret;
8534}
8535
8536/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308537 *__wlan_hdd_cfg80211_setband() - set band
8538 * @wiphy: Pointer to wireless phy
8539 * @wdev: Pointer to wireless device
8540 * @data: Pointer to data
8541 * @data_len: Length of @data
8542 *
8543 * Return: 0 on success, negative errno on failure
8544 */
8545static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8546 struct wireless_dev *wdev,
8547 const void *data, int data_len)
8548{
8549 struct net_device *dev = wdev->netdev;
8550 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8551 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8552 int ret;
8553 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8554 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8555
8556 ENTER();
8557
8558 ret = wlan_hdd_validate_context(hdd_ctx);
8559 if (ret)
8560 return ret;
8561
8562 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8563 hdd_err(FL("Invalid ATTR"));
8564 return -EINVAL;
8565 }
8566
8567 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8568 hdd_err(FL("attr SETBAND_VALUE failed"));
8569 return -EINVAL;
8570 }
8571
8572 ret = hdd_set_band(dev,
8573 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8574
8575 EXIT();
8576 return ret;
8577}
8578
8579/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308580 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8581 * @adapter: hdd adapter
8582 * @channel: channel number
8583 *
8584 * return: QDF status based on success or failure
8585 */
8586static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8587 int channel, int chan_bw)
8588{
8589 if (QDF_STATUS_SUCCESS !=
8590 wlan_hdd_validate_operation_channel(adapter, channel))
8591 return QDF_STATUS_E_FAILURE;
8592 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8593 channel,
8594 PHY_SINGLE_CHANNEL_CENTERED))) {
8595 hdd_notice("channel %d is in nol", channel);
8596 return -EINVAL;
8597 }
8598
8599 if ((wlansap_is_channel_leaking_in_nol(
8600 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8601 channel, chan_bw))) {
8602 hdd_notice("channel %d is leaking in nol", channel);
8603 return -EINVAL;
8604 }
8605
8606 return 0;
8607
8608}
8609
Kapil Gupta8878ad92017-02-13 11:56:04 +05308610static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8611 tsap_Config_t *sap_config,
8612 struct hdd_vendor_chan_info *channel_list)
8613{
8614 sap_config->channel = channel_list->pri_ch;
8615
8616 sap_config->ch_params.center_freq_seg0 =
8617 channel_list->vht_seg0_center_ch;
8618 sap_config->ch_params.center_freq_seg1 =
8619 channel_list->vht_seg1_center_ch;
8620
8621 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8622 sap_config->ch_params.ch_width = channel_list->chan_width;
8623 if (sap_config->channel >= 36)
8624 sap_config->ch_width_orig =
8625 hdd_ctx->config->vhtChannelWidth;
8626 else
8627 sap_config->ch_width_orig =
8628 hdd_ctx->config->nChannelBondingMode24GHz ?
8629 eHT_CHANNEL_WIDTH_40MHZ :
8630 eHT_CHANNEL_WIDTH_20MHZ;
8631
8632 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8633 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8634 sap_config->acs_cfg.vht_seg0_center_ch =
8635 channel_list->vht_seg0_center_ch;
8636 sap_config->acs_cfg.vht_seg1_center_ch =
8637 channel_list->vht_seg1_center_ch;
8638 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8639}
8640
8641static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8642 uint8_t channel_cnt,
8643 struct hdd_vendor_chan_info *channel_list)
8644{
8645 tsap_Config_t *sap_config;
8646 hdd_ap_ctx_t *hdd_ap_ctx;
8647 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8648 QDF_STATUS status = QDF_STATUS_SUCCESS;
8649
8650 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8651 sap_config = &adapter->sessionCtx.ap.sapConfig;
8652
8653 if (QDF_TIMER_STATE_RUNNING ==
8654 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8655 ap.vendor_acs_timer)) {
8656 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8657 }
8658
8659 if (channel_list && channel_list->pri_ch == 0) {
8660 /* Check mode, set default channel */
8661 channel_list->pri_ch = 6;
8662 /*
8663 * sap_select_default_oper_chan(hdd_ctx->hHal,
8664 * sap_config->acs_cfg.hw_mode);
8665 */
8666 }
8667
8668 switch (reason) {
8669 /* SAP init case */
8670 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8671 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8672 /* Update Hostapd */
8673 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8674 break;
8675
8676 /* DFS detected on current channel */
8677 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8678 wlan_sap_update_next_channel(
8679 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8680 channel_list->pri_ch,
8681 channel_list->chan_width);
8682 status = sme_update_new_channel_event(
8683 WLAN_HDD_GET_HAL_CTX(adapter),
8684 adapter->sessionId);
8685 break;
8686
8687 /* LTE coex event on current channel */
8688 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8689 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8690 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8691 hdd_ap_ctx->sapConfig.ch_width_orig =
8692 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008693 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308694 break;
8695
8696 default:
8697 hdd_info("invalid reason for timer invoke");
8698 }
8699 qdf_mem_free(channel_list);
8700 EXIT();
8701 return status;
8702}
8703
8704/**
8705 * Define short name for vendor channel set config
8706 */
8707#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8708#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8709#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8710#define SET_CHAN_PRIMARY_CHANNEL \
8711 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8712#define SET_CHAN_SECONDARY_CHANNEL \
8713 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8714#define SET_CHAN_SEG0_CENTER_CHANNEL \
8715 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8716#define SET_CHAN_SEG1_CENTER_CHANNEL \
8717 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8718#define SET_CHAN_CHANNEL_WIDTH \
8719 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8720#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8721
8722/**
8723 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8724 * @channel_list: pointer to hdd_vendor_chan_info
8725 * @reason: channel change reason
8726 * @channel_cnt: channel count
8727 * @data: data
8728 * @data_len: data len
8729 *
8730 * Return: 0 on success, negative errno on failure
8731 */
8732static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8733 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8734 const void *data, int data_len)
8735{
8736 int rem, i = 0;
8737 struct nlattr *tb[SET_CHAN_MAX + 1];
8738 struct nlattr *tb2[SET_CHAN_MAX + 1];
8739 struct nlattr *curr_attr;
8740 struct hdd_vendor_chan_info *channel_list;
8741
8742 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8743 hdd_err("Invalid ATTR");
8744 return -EINVAL;
8745 }
8746
8747 if (tb[SET_CHAN_REASON])
8748 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8749
8750 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8751 *channel_cnt = nla_get_u8(tb[
8752 SET_CHAN_CHANNEL_COUNT]);
8753 hdd_info("channel count %d", *channel_cnt);
8754 }
8755
8756 if (!(*channel_cnt)) {
8757 hdd_err("channel count is %d", *channel_cnt);
8758 return -EINVAL;
8759 }
8760
8761 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8762 (*channel_cnt));
8763
8764 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8765 if (nla_parse(tb2,
8766 SET_CHAN_MAX,
8767 nla_data(curr_attr), nla_len(curr_attr),
8768 NULL)) {
8769 hdd_err("nla_parse failed");
8770 return -EINVAL;
8771 }
8772 /* Parse and Fetch allowed SSID list*/
8773 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8774 channel_list[i].pri_ch =
8775 nla_get_u8(
8776 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8777 }
8778 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8779 channel_list[i].ht_sec_ch =
8780 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8781 }
8782 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8783 channel_list[i].vht_seg0_center_ch =
8784 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8785 }
8786 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8787 channel_list[i].vht_seg1_center_ch =
8788 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8789 }
8790 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8791 channel_list[i].chan_width =
8792 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8793 }
8794 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8795 i, channel_list[i].pri_ch,
8796 channel_list[i].ht_sec_ch,
8797 channel_list[i].vht_seg0_center_ch,
8798 channel_list[i].vht_seg1_center_ch,
8799 channel_list[i].chan_width);
8800 i++;
8801 if (i > *channel_cnt)
8802 break;
8803 }
8804 *chan_list_ptr = channel_list;
8805
8806 return 0;
8807}
8808
8809/**
8810 * Undef short names for vendor set channel configuration
8811 */
8812#undef SET_CHAN_REASON
8813#undef SET_CHAN_CHANNEL_COUNT
8814#undef SET_CHAN_CHAN_LIST
8815#undef SET_CHAN_PRIMARY_CHANNEL
8816#undef SET_CHAN_SECONDARY_CHANNEL
8817#undef SET_CHAN_SEG0_CENTER_CHANNEL
8818#undef SET_CHAN_SEG1_CENTER_CHANNEL
8819#undef SET_CHAN_CHANNEL_WIDTH
8820#undef SET_CHAN_MAX
8821
8822/**
8823 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8824 * @wiphy: Pointer to wireless phy
8825 * @wdev: Pointer to wireless device
8826 * @data: Pointer to data
8827 * @data_len: Length of @data
8828 *
8829 * Return: 0 on success, negative errno on failure
8830 */
8831static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8832 struct wireless_dev *wdev,
8833 const void *data, int data_len)
8834{
8835 int ret_val;
8836 QDF_STATUS qdf_status;
8837 uint8_t channel_cnt = 0, reason = -1;
8838 struct hdd_vendor_chan_info *channel_list = NULL;
8839 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8840 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8841
8842 ENTER();
8843
8844 ret_val = wlan_hdd_validate_context(hdd_ctx);
8845 if (ret_val)
8846 return ret_val;
8847
8848 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8849 hdd_err("Command not allowed in FTM mode");
8850 return -EINVAL;
8851 }
8852
8853 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8854 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8855 else {
8856 hdd_err("already timeout happened for acs");
8857 return -EINVAL;
8858 }
8859
8860 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8861 &channel_cnt, data, data_len);
8862 if (ret_val)
8863 return ret_val;
8864
8865 /* Validate channel to be set */
8866 while (channel_cnt && channel_list) {
8867 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8868 channel_list->pri_ch,
8869 channel_list->chan_width);
8870 if (qdf_status == QDF_STATUS_SUCCESS)
8871 break;
8872 channel_cnt--;
8873 channel_list++;
8874 }
8875 if ((channel_cnt <= 0) || !channel_list) {
8876 hdd_err("no available channel/chanlist %p", channel_list);
8877 return -EINVAL;
8878 }
8879
8880 qdf_status = hdd_update_acs_channel(adapter, reason,
8881 channel_cnt, channel_list);
8882 return qdf_status_to_os_return(qdf_status);
8883}
8884
8885/**
8886 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8887 * @wiphy: Pointer to wireless phy
8888 * @wdev: Pointer to wireless device
8889 * @data: Pointer to data
8890 * @data_len: Length of @data
8891 *
8892 * Return: 0 on success, negative errno on failure
8893 */
8894static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8895 struct wireless_dev *wdev,
8896 const void *data, int data_len)
8897{
8898 int ret;
8899
8900 cds_ssr_protect(__func__);
8901 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8902 data_len);
8903 cds_ssr_protect(__func__);
8904
8905 return ret;
8906}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308907
8908/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308909 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8910 * @wiphy: wiphy structure pointer
8911 * @wdev: Wireless device structure pointer
8912 * @data: Pointer to the data received
8913 * @data_len: Length of @data
8914 *
8915 * Return: 0 on success; errno on failure
8916 */
8917static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8918 struct wireless_dev *wdev,
8919 const void *data, int data_len)
8920{
8921 int ret;
8922
8923 cds_ssr_protect(__func__);
8924 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8925 cds_ssr_unprotect(__func__);
8926
8927 return ret;
8928}
8929
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008930/**
8931 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8932 * @nl80211_value: Vendor command attribute value
8933 * @wmi_value: Pointer to return converted WMI return value
8934 *
8935 * Convert NL80211 vendor command value for SAR limit set to WMI value
8936 * Return: 0 on success, -1 on invalid value
8937 */
8938static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8939 u32 *wmi_value)
8940{
8941 int ret = 0;
8942
8943 switch (nl80211_value) {
8944 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8945 *wmi_value = WMI_SAR_FEATURE_OFF;
8946 break;
8947 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8948 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8949 break;
8950 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8951 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8952 break;
8953 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8954 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8955 break;
8956 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8957 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8958 break;
8959 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8960 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8961 break;
8962 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8963 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8964 break;
8965 default:
8966 ret = -1;
8967 }
8968 return ret;
8969}
8970
8971/**
8972 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8973 * @nl80211_value: Vendor command attribute value
8974 * @wmi_value: Pointer to return converted WMI return value
8975 *
8976 * Convert NL80211 vendor command value for SAR BAND to WMI value
8977 * Return: 0 on success, -1 on invalid value
8978 */
8979static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8980{
8981 int ret = 0;
8982
8983 switch (nl80211_value) {
8984 case NL80211_BAND_2GHZ:
8985 *wmi_value = WMI_SAR_2G_ID;
8986 break;
8987 case NL80211_BAND_5GHZ:
8988 *wmi_value = WMI_SAR_5G_ID;
8989 break;
8990 default:
8991 ret = -1;
8992 }
8993 return ret;
8994}
8995
8996/**
8997 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8998 * @nl80211_value: Vendor command attribute value
8999 * @wmi_value: Pointer to return converted WMI return value
9000 *
9001 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9002 * Return: 0 on success, -1 on invalid value
9003 */
9004static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9005 u32 *wmi_value)
9006{
9007 int ret = 0;
9008
9009 switch (nl80211_value) {
9010 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9011 *wmi_value = WMI_SAR_MOD_CCK;
9012 break;
9013 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9014 *wmi_value = WMI_SAR_MOD_OFDM;
9015 break;
9016 default:
9017 ret = -1;
9018 }
9019 return ret;
9020}
9021
9022
9023/**
9024 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9025 * @wiphy: Pointer to wireless phy
9026 * @wdev: Pointer to wireless device
9027 * @data: Pointer to data
9028 * @data_len: Length of @data
9029 *
9030 * This function is used to setup Specific Absorption Rate limit specs.
9031 *
9032 * Return: 0 on success, negative errno on failure
9033 */
9034static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9035 struct wireless_dev *wdev,
9036 const void *data, int data_len)
9037{
9038 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9039 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9040 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9041 *sar_spec_list;
9042 struct sar_limit_cmd_params sar_limit_cmd = {0};
9043 int ret = -EINVAL, i = 0, rem = 0;
9044
9045 ENTER();
9046
9047 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9048 hdd_err("Command not allowed in FTM mode");
9049 return -EPERM;
9050 }
9051
9052 if (wlan_hdd_validate_context(hdd_ctx))
9053 return -EINVAL;
9054
9055 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9056 data, data_len, NULL)) {
9057 hdd_err("Invalid SAR attributes");
9058 return -EINVAL;
9059 }
9060
9061 /* Vendor command manadates all SAR Specs in single call */
9062 sar_limit_cmd.commit_limits = 1;
9063 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9064 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9065 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9066 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9067 &sar_limit_cmd.sar_enable) < 0) {
9068 hdd_err("Invalid SAR Enable attr");
9069 goto fail;
9070 }
9071 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009072 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009073
9074 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9075 sar_limit_cmd.num_limit_rows = nla_get_u32(
9076 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009077 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009078 sar_limit_cmd.num_limit_rows);
9079 }
9080 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9081 hdd_err("SAR Spec list exceed supported size");
9082 goto fail;
9083 }
9084 if (sar_limit_cmd.num_limit_rows == 0)
9085 goto send_sar_limits;
9086 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9087 struct sar_limit_cmd_row) *
9088 sar_limit_cmd.num_limit_rows);
9089 if (!sar_limit_cmd.sar_limit_row_list) {
9090 ret = -ENOMEM;
9091 goto fail;
9092 }
9093 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9094 hdd_err("Invalid SAR SPECs list");
9095 goto fail;
9096 }
9097
9098 nla_for_each_nested(sar_spec_list,
9099 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9100 if (i == sar_limit_cmd.num_limit_rows) {
9101 hdd_warn("SAR Cmd has excess SPECs in list");
9102 break;
9103 }
9104
9105 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9106 nla_data(sar_spec_list), nla_len(sar_spec_list),
9107 NULL)) {
9108 hdd_err("nla_parse failed for SAR Spec list");
9109 goto fail;
9110 }
9111 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9112 if (sar_spec[
9113 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9114 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9115 nla_get_u32(sar_spec[
9116 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9117 } else {
9118 hdd_err("SAR Spec does not have power limit value");
9119 goto fail;
9120 }
9121
9122 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9123 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9124 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9125 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9126 < 0) {
9127 hdd_err("Invalid SAR Band attr");
9128 goto fail;
9129 }
9130 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9131 WMI_SAR_BAND_ID_VALID_MASK;
9132 }
9133 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9134 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9135 nla_get_u32(sar_spec[
9136 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9137 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9138 WMI_SAR_CHAIN_ID_VALID_MASK;
9139 }
9140 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9141 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9142 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9143 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9144 < 0) {
9145 hdd_err("Invalid SAR Modulation attr");
9146 goto fail;
9147 }
9148 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9149 WMI_SAR_MOD_ID_VALID_MASK;
9150 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009151 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009152 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9153 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9154 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9155 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9156 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9157 i++;
9158 }
9159
9160 if (i < sar_limit_cmd.num_limit_rows) {
9161 hdd_warn("SAR Cmd has less SPECs in list");
9162 sar_limit_cmd.num_limit_rows = i;
9163 }
9164
9165send_sar_limits:
9166 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9167 QDF_STATUS_SUCCESS)
9168 ret = 0;
9169fail:
9170 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9171 return ret;
9172}
9173
9174/**
9175 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9176 * @wiphy: Pointer to wireless phy
9177 * @wdev: Pointer to wireless device
9178 * @data: Pointer to data
9179 * @data_len: Length of @data
9180 *
9181 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9182 *
9183 * Return: 0 on success, negative errno on failure
9184 */
9185static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9186 struct wireless_dev *wdev,
9187 const void *data,
9188 int data_len)
9189{
9190 int ret;
9191
9192 cds_ssr_protect(__func__);
9193 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9194 data_len);
9195 cds_ssr_unprotect(__func__);
9196
9197 return ret;
9198}
9199
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309200static const struct
9201nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9202 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9203 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9204 .len = QDF_MAC_ADDR_SIZE},
9205};
9206
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309207void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9208{
9209 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9210 hdd_adapter_t *adapter;
9211
9212 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9213 if (!adapter) {
9214 hdd_err("adapter NULL");
9215 return;
9216 }
9217
9218 adapter->lfr_fw_status.is_disabled = rso_status->status;
9219 complete(&adapter->lfr_fw_status.disable_lfr_event);
9220}
9221
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309222/**
9223 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9224 * @wiphy: Pointer to wireless phy
9225 * @wdev: Pointer to wireless device
9226 * @data: Pointer to data
9227 * @data_len: Length of @data
9228 *
9229 * This function is used to enable/disable roaming using vendor commands
9230 *
9231 * Return: 0 on success, negative errno on failure
9232 */
9233static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9234 struct wireless_dev *wdev,
9235 const void *data, int data_len)
9236{
9237 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9238 struct net_device *dev = wdev->netdev;
9239 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9240 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309241 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309242 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309243 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309244 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309245
9246 ENTER_DEV(dev);
9247
9248 ret = wlan_hdd_validate_context(hdd_ctx);
9249 if (0 != ret)
9250 return ret;
9251
9252 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9253 hdd_err("Command not allowed in FTM mode");
9254 return -EINVAL;
9255 }
9256
9257 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9258 qca_wlan_vendor_attr);
9259 if (ret) {
9260 hdd_err("Invalid ATTR");
9261 return -EINVAL;
9262 }
9263
9264 /* Parse and fetch Enable flag */
9265 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9266 hdd_err("attr enable failed");
9267 return -EINVAL;
9268 }
9269
9270 is_fast_roam_enabled = nla_get_u32(
9271 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009272 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009273 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309274
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009275 if (!adapter->fast_roaming_allowed) {
9276 hdd_err("fast roaming not allowed on %s interface",
9277 adapter->dev->name);
9278 return -EINVAL;
9279 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309280 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309281 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309282 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309283 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309284 if (qdf_status != QDF_STATUS_SUCCESS)
9285 hdd_err("sme_config_fast_roaming failed with status=%d",
9286 qdf_status);
9287 ret = qdf_status_to_os_return(qdf_status);
9288
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309289 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9290 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9291 /*
9292 * wait only for LFR disable in fw as LFR enable
9293 * is always success
9294 */
9295 rc = wait_for_completion_timeout(
9296 &adapter->lfr_fw_status.disable_lfr_event,
9297 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9298 if (!rc) {
9299 hdd_err("Timed out waiting for RSO CMD status");
9300 return -ETIMEDOUT;
9301 }
9302
9303 if (!adapter->lfr_fw_status.is_disabled) {
9304 hdd_err("Roam disable attempt in FW fails");
9305 return -EBUSY;
9306 }
9307 }
9308
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309309 EXIT();
9310 return ret;
9311}
9312
9313/**
9314 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9315 * @wiphy: Pointer to wireless phy
9316 * @wdev: Pointer to wireless device
9317 * @data: Pointer to data
9318 * @data_len: Length of @data
9319 *
9320 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9321 *
9322 * Return: 0 on success, negative errno on failure
9323 */
9324static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9325 struct wireless_dev *wdev,
9326 const void *data, int data_len)
9327{
9328 int ret;
9329
9330 cds_ssr_protect(__func__);
9331 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9332 cds_ssr_unprotect(__func__);
9333
9334 return ret;
9335}
9336
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309337static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9338 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9339 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9340 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9341 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9342};
9343
9344/**
9345 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9346 * @wiphy: Pointer to wireless phy
9347 * @wdev: Pointer to wireless device
9348 * @data: Pointer to data
9349 * @data_len: Length of @data
9350 *
9351 * Return: 0 on success, negative errno on failure
9352 */
9353static int
9354__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9355 struct wireless_dev *wdev,
9356 const void *data,
9357 int data_len)
9358{
9359 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9360 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9361 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9362 struct nlattr *apth;
9363 int rem;
9364 int ret = 1;
9365 int print_idx = -1;
9366 int module_id = -1;
9367 int bit_mask = -1;
9368 int status;
9369
9370 ENTER();
9371
9372 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9373 hdd_err("Command not allowed in FTM mode");
9374 return -EINVAL;
9375 }
9376
9377 ret = wlan_hdd_validate_context(hdd_ctx);
9378 if (ret != 0)
9379 return -EINVAL;
9380
9381 print_idx = qdf_get_pidx();
9382 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9383 hdd_err("Invalid print controle object index");
9384 return -EINVAL;
9385 }
9386
9387 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9388 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9389 hdd_err("Invalid attr");
9390 return -EINVAL;
9391 }
9392
9393 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9394 hdd_err("attr trace level param failed");
9395 return -EINVAL;
9396 }
9397
9398 nla_for_each_nested(apth,
9399 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9400 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9401 nla_data(apth), nla_len(apth), NULL)) {
9402 hdd_err("Invalid attr");
9403 return -EINVAL;
9404 }
9405
9406 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9407 hdd_err("attr Module ID failed");
9408 return -EINVAL;
9409 }
9410 module_id = nla_get_u32
9411 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9412
9413 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9414 hdd_err("attr Verbose mask failed");
9415 return -EINVAL;
9416 }
9417 bit_mask = nla_get_u32
9418 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9419
9420 status = hdd_qdf_trace_enable(module_id, bit_mask);
9421
9422 if (status != 0)
9423 hdd_err("can not set verbose mask %d for the category %d",
9424 bit_mask, module_id);
9425 }
9426
9427 EXIT();
9428 return ret;
9429}
9430
9431/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309432 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9433 * @wiphy: Pointer to wireless phy
9434 * @wdev: Pointer to wireless device
9435 * @data: Pointer to data
9436 * @data_len: Length of @data
9437 *
9438 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9439 *
9440 * Return: 0 on success, negative errno on failure
9441 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309442
9443static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9444 struct wireless_dev *wdev,
9445 const void *data,
9446 int data_len)
9447{
9448 int ret;
9449
9450 cds_ssr_protect(__func__);
9451 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9452 cds_ssr_unprotect(__func__);
9453
9454 return ret;
9455}
9456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009457const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9458 {
9459 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9460 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9461 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309462 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009463 .doit = is_driver_dfs_capable
9464 },
9465
9466#ifdef WLAN_FEATURE_NAN
9467 {
9468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9471 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9472 .doit = wlan_hdd_cfg80211_nan_request
9473 },
9474#endif
9475
9476#ifdef WLAN_FEATURE_STATS_EXT
9477 {
9478 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9479 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9480 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9481 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9482 .doit = wlan_hdd_cfg80211_stats_ext_request
9483 },
9484#endif
9485#ifdef FEATURE_WLAN_EXTSCAN
9486 {
9487 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9488 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9489 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9490 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9491 .doit = wlan_hdd_cfg80211_extscan_start
9492 },
9493 {
9494 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9495 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9496 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9497 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9498 .doit = wlan_hdd_cfg80211_extscan_stop
9499 },
9500 {
9501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9504 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9505 },
9506 {
9507 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9508 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9509 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9510 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9511 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9512 },
9513 {
9514 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9515 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9516 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9517 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9518 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9519 },
9520 {
9521 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9522 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9523 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9524 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9525 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9526 },
9527 {
9528 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9529 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9530 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9531 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9532 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9533 },
9534 {
9535 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9536 .info.subcmd =
9537 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9538 .flags =
9539 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9540 WIPHY_VENDOR_CMD_NEED_RUNNING,
9541 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9542 },
9543 {
9544 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9545 .info.subcmd =
9546 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9547 .flags =
9548 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9549 WIPHY_VENDOR_CMD_NEED_RUNNING,
9550 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9551 },
9552 {
9553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9556 WIPHY_VENDOR_CMD_NEED_NETDEV |
9557 WIPHY_VENDOR_CMD_NEED_RUNNING,
9558 .doit = wlan_hdd_cfg80211_set_epno_list
9559 },
9560#endif /* FEATURE_WLAN_EXTSCAN */
9561
9562#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9563 {
9564 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9565 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9566 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9567 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9568 .doit = wlan_hdd_cfg80211_ll_stats_clear
9569 },
9570
9571 {
9572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9575 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9576 .doit = wlan_hdd_cfg80211_ll_stats_set
9577 },
9578
9579 {
9580 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9581 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9582 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9583 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9584 .doit = wlan_hdd_cfg80211_ll_stats_get
9585 },
9586#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9587#ifdef FEATURE_WLAN_TDLS
9588 {
9589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9592 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9593 .doit = wlan_hdd_cfg80211_exttdls_enable
9594 },
9595 {
9596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9599 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9600 .doit = wlan_hdd_cfg80211_exttdls_disable
9601 },
9602 {
9603 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9604 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9605 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9606 .doit = wlan_hdd_cfg80211_exttdls_get_status
9607 },
9608#endif
9609 {
9610 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9611 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9612 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9613 .doit = wlan_hdd_cfg80211_get_supported_features
9614 },
9615 {
9616 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9617 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9618 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9619 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9620 },
9621 {
9622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309625 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009626 },
9627 {
9628 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9629 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9630 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9631 WIPHY_VENDOR_CMD_NEED_NETDEV,
9632 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9633 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009634 {
9635 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9636 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9637 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9638 WIPHY_VENDOR_CMD_NEED_NETDEV,
9639 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9640 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009641 {
9642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309643 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9644 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9645 WIPHY_VENDOR_CMD_NEED_NETDEV |
9646 WIPHY_VENDOR_CMD_NEED_RUNNING,
9647 .doit = hdd_cfg80211_get_station_cmd
9648 },
9649 {
9650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009651 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9652 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9653 WIPHY_VENDOR_CMD_NEED_NETDEV |
9654 WIPHY_VENDOR_CMD_NEED_RUNNING,
9655 .doit = wlan_hdd_cfg80211_do_acs
9656 },
9657
9658 {
9659 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9660 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9661 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9662 WIPHY_VENDOR_CMD_NEED_NETDEV,
9663 .doit = wlan_hdd_cfg80211_get_features
9664 },
9665#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9666 {
9667 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9668 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9669 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9670 WIPHY_VENDOR_CMD_NEED_NETDEV |
9671 WIPHY_VENDOR_CMD_NEED_RUNNING,
9672 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9673 },
9674#endif
9675#ifdef FEATURE_WLAN_EXTSCAN
9676 {
9677 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9678 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9680 WIPHY_VENDOR_CMD_NEED_NETDEV |
9681 WIPHY_VENDOR_CMD_NEED_RUNNING,
9682 .doit = wlan_hdd_cfg80211_set_passpoint_list
9683 },
9684 {
9685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9688 WIPHY_VENDOR_CMD_NEED_NETDEV |
9689 WIPHY_VENDOR_CMD_NEED_RUNNING,
9690 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9691 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009692#endif /* FEATURE_WLAN_EXTSCAN */
9693 {
9694 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9695 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9696 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9697 WIPHY_VENDOR_CMD_NEED_NETDEV,
9698 .doit = wlan_hdd_cfg80211_get_wifi_info
9699 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009700#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701 {
9702 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9703 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9704 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9705 WIPHY_VENDOR_CMD_NEED_NETDEV |
9706 WIPHY_VENDOR_CMD_NEED_RUNNING,
9707 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9708 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009709#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009710 {
9711 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9712 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9713 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9714 WIPHY_VENDOR_CMD_NEED_NETDEV,
9715 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9716 },
9717 {
9718 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9719 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9720 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9721 WIPHY_VENDOR_CMD_NEED_NETDEV,
9722 .doit = wlan_hdd_cfg80211_wifi_logger_start
9723 },
9724 {
9725 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9726 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9727 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9728 WIPHY_VENDOR_CMD_NEED_NETDEV,
9729 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9730 },
9731 {
9732 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9733 .info.subcmd =
9734 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9735 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9736 WIPHY_VENDOR_CMD_NEED_NETDEV |
9737 WIPHY_VENDOR_CMD_NEED_RUNNING,
9738 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9739 },
9740 {
9741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9742 .info.subcmd =
9743 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9744 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9745 WIPHY_VENDOR_CMD_NEED_NETDEV |
9746 WIPHY_VENDOR_CMD_NEED_RUNNING,
9747 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9748 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009749#ifdef WLAN_FEATURE_TSF
9750 {
9751 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9752 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9753 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9754 WIPHY_VENDOR_CMD_NEED_NETDEV |
9755 WIPHY_VENDOR_CMD_NEED_RUNNING,
9756 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9757 },
9758#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009759#ifdef FEATURE_WLAN_TDLS
9760 {
9761 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9762 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9763 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9764 WIPHY_VENDOR_CMD_NEED_NETDEV |
9765 WIPHY_VENDOR_CMD_NEED_RUNNING,
9766 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9767 },
9768#endif
9769#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9770 {
9771 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9772 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9773 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9774 WIPHY_VENDOR_CMD_NEED_NETDEV |
9775 WIPHY_VENDOR_CMD_NEED_RUNNING,
9776 .doit = wlan_hdd_cfg80211_offloaded_packets
9777 },
9778#endif
9779 {
9780 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9781 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9782 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9783 WIPHY_VENDOR_CMD_NEED_NETDEV |
9784 WIPHY_VENDOR_CMD_NEED_RUNNING,
9785 .doit = wlan_hdd_cfg80211_monitor_rssi
9786 },
9787 {
9788 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309789 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9791 WIPHY_VENDOR_CMD_NEED_NETDEV |
9792 WIPHY_VENDOR_CMD_NEED_RUNNING,
9793 .doit = wlan_hdd_cfg80211_set_ns_offload
9794 },
9795 {
9796 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009797 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9798 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9799 WIPHY_VENDOR_CMD_NEED_NETDEV |
9800 WIPHY_VENDOR_CMD_NEED_RUNNING,
9801 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9802 },
9803#ifdef WLAN_FEATURE_MEMDUMP
9804 {
9805 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9806 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9807 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9808 WIPHY_VENDOR_CMD_NEED_NETDEV |
9809 WIPHY_VENDOR_CMD_NEED_RUNNING,
9810 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9811 },
9812#endif /* WLAN_FEATURE_MEMDUMP */
9813 {
9814 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9815 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9816 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9817 WIPHY_VENDOR_CMD_NEED_NETDEV |
9818 WIPHY_VENDOR_CMD_NEED_RUNNING,
9819 .doit = wlan_hdd_cfg80211_vendor_scan
9820 },
9821
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309822 /* Vendor abort scan */
9823 {
9824 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9825 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9826 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9827 WIPHY_VENDOR_CMD_NEED_NETDEV |
9828 WIPHY_VENDOR_CMD_NEED_RUNNING,
9829 .doit = wlan_hdd_vendor_abort_scan
9830 },
9831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009832 /* OCB commands */
9833 {
9834 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9835 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9837 WIPHY_VENDOR_CMD_NEED_NETDEV |
9838 WIPHY_VENDOR_CMD_NEED_RUNNING,
9839 .doit = wlan_hdd_cfg80211_ocb_set_config
9840 },
9841 {
9842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9845 WIPHY_VENDOR_CMD_NEED_NETDEV |
9846 WIPHY_VENDOR_CMD_NEED_RUNNING,
9847 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9848 },
9849 {
9850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9851 .info.subcmd =
9852 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9853 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9854 WIPHY_VENDOR_CMD_NEED_NETDEV |
9855 WIPHY_VENDOR_CMD_NEED_RUNNING,
9856 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9857 },
9858 {
9859 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9860 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9861 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9862 WIPHY_VENDOR_CMD_NEED_NETDEV |
9863 WIPHY_VENDOR_CMD_NEED_RUNNING,
9864 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9865 },
9866 {
9867 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9868 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9869 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9870 WIPHY_VENDOR_CMD_NEED_NETDEV |
9871 WIPHY_VENDOR_CMD_NEED_RUNNING,
9872 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9873 },
9874 {
9875 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9876 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9877 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9878 WIPHY_VENDOR_CMD_NEED_NETDEV |
9879 WIPHY_VENDOR_CMD_NEED_RUNNING,
9880 .doit = wlan_hdd_cfg80211_dcc_get_stats
9881 },
9882 {
9883 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9884 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9885 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9886 WIPHY_VENDOR_CMD_NEED_NETDEV |
9887 WIPHY_VENDOR_CMD_NEED_RUNNING,
9888 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9889 },
9890 {
9891 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9892 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9893 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9894 WIPHY_VENDOR_CMD_NEED_NETDEV |
9895 WIPHY_VENDOR_CMD_NEED_RUNNING,
9896 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9897 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309898 {
9899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9902 WIPHY_VENDOR_CMD_NEED_NETDEV |
9903 WIPHY_VENDOR_CMD_NEED_RUNNING,
9904 .doit = wlan_hdd_cfg80211_get_link_properties
9905 },
Peng Xu278d0122015-09-24 16:34:17 -07009906 {
Peng Xud2220962016-07-11 17:59:17 -07009907 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009908 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9910 WIPHY_VENDOR_CMD_NEED_NETDEV |
9911 WIPHY_VENDOR_CMD_NEED_RUNNING,
9912 .doit = wlan_hdd_cfg80211_set_ota_test
9913 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009914#ifdef FEATURE_LFR_SUBNET_DETECTION
9915 {
9916 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9917 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9918 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9919 WIPHY_VENDOR_CMD_NEED_NETDEV |
9920 WIPHY_VENDOR_CMD_NEED_RUNNING,
9921 .doit = wlan_hdd_cfg80211_set_gateway_params
9922 },
9923#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009924 {
Peng Xud2220962016-07-11 17:59:17 -07009925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9928 WIPHY_VENDOR_CMD_NEED_NETDEV |
9929 WIPHY_VENDOR_CMD_NEED_RUNNING,
9930 .doit = wlan_hdd_cfg80211_txpower_scale
9931 },
9932 {
9933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9934 .info.subcmd =
9935 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9936 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9937 WIPHY_VENDOR_CMD_NEED_NETDEV |
9938 WIPHY_VENDOR_CMD_NEED_RUNNING,
9939 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9940 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309941 {
9942 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9943 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9944 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9945 WIPHY_VENDOR_CMD_NEED_NETDEV |
9946 WIPHY_VENDOR_CMD_NEED_RUNNING,
9947 .doit = wlan_hdd_cfg80211_bpf_offload
9948 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309949 {
9950 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309951 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9952 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9953 WIPHY_VENDOR_CMD_NEED_NETDEV |
9954 WIPHY_VENDOR_CMD_NEED_RUNNING,
9955 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9956 },
9957 {
9958 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309959 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9960 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9961 WIPHY_VENDOR_CMD_NEED_NETDEV |
9962 WIPHY_VENDOR_CMD_NEED_RUNNING,
9963 .doit = wlan_hdd_cfg80211_sta_roam_policy
9964 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309965#ifdef FEATURE_WLAN_CH_AVOID
9966 {
9967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9968 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9970 WIPHY_VENDOR_CMD_NEED_NETDEV |
9971 WIPHY_VENDOR_CMD_NEED_RUNNING,
9972 .doit = wlan_hdd_cfg80211_avoid_freq
9973 },
9974#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309975 {
9976 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309977 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9978 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9979 WIPHY_VENDOR_CMD_NEED_NETDEV |
9980 WIPHY_VENDOR_CMD_NEED_RUNNING,
9981 .doit = wlan_hdd_cfg80211_sap_configuration_set
9982 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009983 {
Peng Xu4225c152016-07-14 21:18:14 -07009984 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009985 .info.subcmd =
9986 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9987 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9988 WIPHY_VENDOR_CMD_NEED_NETDEV |
9989 WIPHY_VENDOR_CMD_NEED_RUNNING,
9990 .doit = wlan_hdd_cfg80211_p2p_lo_start
9991 },
9992 {
9993 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9994 .info.subcmd =
9995 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9997 WIPHY_VENDOR_CMD_NEED_NETDEV |
9998 WIPHY_VENDOR_CMD_NEED_RUNNING,
9999 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10000 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010001 {
10002 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10003 .info.subcmd =
10004 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10006 WIPHY_VENDOR_CMD_NEED_NETDEV |
10007 WIPHY_VENDOR_CMD_NEED_RUNNING,
10008 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10009 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010010#ifdef WLAN_FEATURE_NAN_DATAPATH
10011 {
10012 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10013 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10014 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10015 WIPHY_VENDOR_CMD_NEED_NETDEV |
10016 WIPHY_VENDOR_CMD_NEED_RUNNING,
10017 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10018 },
10019#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010020 {
10021 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10022 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10023 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10024 WIPHY_VENDOR_CMD_NEED_NETDEV |
10025 WIPHY_VENDOR_CMD_NEED_RUNNING,
10026 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10027 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010028 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10030 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10032 WIPHY_VENDOR_CMD_NEED_NETDEV |
10033 WIPHY_VENDOR_CMD_NEED_RUNNING,
10034 .doit = wlan_hdd_cfg80211_get_bus_size
10035 },
10036 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10040 WIPHY_VENDOR_CMD_NEED_NETDEV |
10041 WIPHY_VENDOR_CMD_NEED_RUNNING,
10042 .doit = wlan_hdd_cfg80211_update_vendor_channel
10043 },
10044 {
bingsd09dea32017-03-17 10:08:26 +080010045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10048 WIPHY_VENDOR_CMD_NEED_NETDEV |
10049 WIPHY_VENDOR_CMD_NEED_RUNNING,
10050 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010051 },
10052 {
10053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
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_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010059 },
10060#ifdef WLAN_FEATURE_DISA
10061 {
10062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10063 .info.subcmd =
10064 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10066 WIPHY_VENDOR_CMD_NEED_NETDEV |
10067 WIPHY_VENDOR_CMD_NEED_RUNNING,
10068 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10069 },
10070#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010071#ifdef FEATURE_WLAN_TDLS
10072 {
10073 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10074 .info.subcmd =
10075 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10076 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10077 WIPHY_VENDOR_CMD_NEED_NETDEV |
10078 WIPHY_VENDOR_CMD_NEED_RUNNING,
10079 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010080 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010081#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010082 {
10083 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10084 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10085 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10086 WIPHY_VENDOR_CMD_NEED_RUNNING,
10087 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10088 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010089 {
10090 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10091 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10092 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10093 WIPHY_VENDOR_CMD_NEED_NETDEV |
10094 WIPHY_VENDOR_CMD_NEED_RUNNING,
10095 .doit = wlan_hdd_cfg80211_set_trace_level
10096 },
10097
Paul Zhang3a210c52016-12-08 10:18:12 +080010098#ifdef WLAN_UMAC_CONVERGENCE
10099 COMMON_VENDOR_COMMANDS
10100#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010101 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102};
10103
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010104#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10105 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10106 defined(FEATURE_WLAN_SCAN_PNO)
10107/**
10108 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10109 * @wiphy: pointer to wiphy
10110 * @config: pointer to config
10111 *
10112 * Return: None
10113 */
10114static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10115 struct hdd_config *config)
10116{
10117 if (config->configPNOScanSupport) {
10118 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010119 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10120 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010121 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010122 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010123 if (config->max_sched_scan_plan_interval)
10124 wiphy->max_sched_scan_plan_interval =
10125 config->max_sched_scan_plan_interval;
10126 if (config->max_sched_scan_plan_iterations)
10127 wiphy->max_sched_scan_plan_iterations =
10128 config->max_sched_scan_plan_iterations;
10129 }
10130}
10131#else
10132static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10133 struct hdd_config *config)
10134{
10135}
10136#endif
10137
10138
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010139/**
10140 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10141 * @priv_size: Size of the hdd context.
10142 *
10143 * Allocate wiphy context and hdd context.
10144 *
10145 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010146 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010147hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148{
10149 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010150 hdd_context_t *hdd_ctx;
10151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010152 ENTER();
10153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010154 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10155
10156 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010157 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010158 return NULL;
10159 }
10160
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010161 hdd_ctx = wiphy_priv(wiphy);
10162
10163 hdd_ctx->wiphy = wiphy;
10164
10165 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010166}
10167
10168/*
10169 * FUNCTION: wlan_hdd_cfg80211_update_band
10170 * This function is called from the supplicant through a
10171 * private ioctl to change the band value
10172 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010173int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10174 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010175{
10176 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010177 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010178
10179 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010180 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010181
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010182 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010184
10185 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10186 struct ieee80211_supported_band *band = wiphy->bands[i];
10187
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010188 channelEnabledState = wlan_reg_get_channel_state(
10189 hdd_ctx->hdd_pdev,
10190 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191
Dustin Browna30892e2016-10-12 17:28:36 -070010192 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193 /* 5G only */
10194#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10195 /* Enable Social channels for P2P */
10196 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10197 (band->channels[j].center_freq)
10198 && CHANNEL_STATE_ENABLE ==
10199 channelEnabledState)
10200 band->channels[j].flags &=
10201 ~IEEE80211_CHAN_DISABLED;
10202 else
10203#endif
10204 band->channels[j].flags |=
10205 IEEE80211_CHAN_DISABLED;
10206 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010207 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010208 eCSR_BAND_24 == eBand) {
10209 /* 2G only */
10210 band->channels[j].flags |=
10211 IEEE80211_CHAN_DISABLED;
10212 continue;
10213 }
10214
Amar Singhal6842e8f2016-02-23 16:30:32 -080010215 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216 band->channels[j].flags &=
10217 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010218 }
10219 }
10220 return 0;
10221}
10222
Peng Xuacfdda12017-02-06 16:15:38 -080010223#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224/*
10225 * FUNCTION: wlan_hdd_cfg80211_init
10226 * This function is called by hdd_wlan_startup()
10227 * during initialization.
10228 * This function is used to initialize and register wiphy structure.
10229 */
10230int wlan_hdd_cfg80211_init(struct device *dev,
10231 struct wiphy *wiphy, struct hdd_config *pCfg)
10232{
10233 int i, j;
10234 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10235
10236 ENTER();
10237
10238 /* Now bind the underlying wlan device with wiphy */
10239 set_wiphy_dev(wiphy, dev);
10240
10241 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010243 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10244 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10245 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10246#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10247 | WIPHY_FLAG_4ADDR_STATION
10248#endif
10249 | WIPHY_FLAG_OFFCHAN_TX;
10250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010251#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10252 wiphy->wowlan = &wowlan_support_cfg80211_init;
10253#else
10254 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10255 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10256 wiphy->wowlan.pattern_min_len = 1;
10257 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10258#endif
10259
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010260 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261#ifdef FEATURE_WLAN_ESE
10262 || pCfg->isEseIniFeatureEnabled
10263#endif
10264 ) {
10265 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10266 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010267#ifdef FEATURE_WLAN_TDLS
10268 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10269 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10270#endif
10271
10272 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10273
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010274#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10275 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10276#endif
10277
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010278 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010279
10280#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010281 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010282#endif
10283
10284 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010285 * driver can still register regulatory callback and
10286 * it will get regulatory settings in wiphy->band[], but
10287 * driver need to determine what to do with both
10288 * regulatory settings
10289 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010291#if defined QCA_WIFI_FTM
10292}
10293#endif
10294
10295 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10296
10297 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10298
10299 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10300
Arun Khandavallifae92942016-08-01 13:31:08 +053010301 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10302 | BIT(NL80211_IFTYPE_ADHOC)
10303 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10304 | BIT(NL80211_IFTYPE_P2P_GO)
10305 | BIT(NL80211_IFTYPE_AP)
10306 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010307
Arun Khandavallifae92942016-08-01 13:31:08 +053010308 if (pCfg->advertiseConcurrentOperation) {
10309 if (pCfg->enableMCC) {
10310 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010311
Arun Khandavallifae92942016-08-01 13:31:08 +053010312 for (i = 0;
10313 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10314 i++) {
10315 if (!pCfg->allowMCCGODiffBI)
10316 wlan_hdd_iface_combination[i].
10317 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 }
10319 }
10320 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010321 ARRAY_SIZE(wlan_hdd_iface_combination);
10322 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 }
10324
10325 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010326 * on ini values
10327 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010328 if (!pCfg->ShortGI20MhzEnable) {
10329 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10330 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010331 }
10332
10333 if (!pCfg->ShortGI40MhzEnable) {
10334 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10335 }
10336
10337 if (!pCfg->nChannelBondingMode5GHz) {
10338 wlan_hdd_band_5_ghz.ht_cap.cap &=
10339 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10340 }
10341
Abhishek Singhf512bf32016-05-04 16:47:46 +053010342 /*
10343 * In case of static linked driver at the time of driver unload,
10344 * module exit doesn't happens. Module cleanup helps in cleaning
10345 * of static memory.
10346 * If driver load happens statically, at the time of driver unload,
10347 * wiphy flags don't get reset because of static memory.
10348 * It's better not to store channel in static memory.
10349 */
Dustin Browna30892e2016-10-12 17:28:36 -070010350 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10351 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010352 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010353 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010354 hdd_err("Not enough memory to allocate channels");
10355 return -ENOMEM;
10356 }
Dustin Browna30892e2016-10-12 17:28:36 -070010357 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010358 &hdd_channels_2_4_ghz[0],
10359 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010360 if ((hdd_is_5g_supported(pHddCtx)) &&
10361 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10362 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10363 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10364 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010365 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10366 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010367 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010368 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010369 hdd_err("Not enough memory to allocate channels");
10370 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010371 bands[NL80211_BAND_2GHZ]->channels);
10372 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010373 return -ENOMEM;
10374 }
Dustin Browna30892e2016-10-12 17:28:36 -070010375 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010376 &hdd_channels_5_ghz[0],
10377 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010378 }
10379
Dustin Browna30892e2016-10-12 17:28:36 -070010380 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010381
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010382 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010383 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010384
10385 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10386 struct ieee80211_supported_band *band = wiphy->bands[i];
10387
Dustin Browna30892e2016-10-12 17:28:36 -070010388 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010389 eCSR_BAND_5G == pCfg->nBandCapability) {
10390 /* 5G only */
10391#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10392 /* Enable social channels for P2P */
10393 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10394 (band->channels[j].center_freq))
10395 band->channels[j].flags &=
10396 ~IEEE80211_CHAN_DISABLED;
10397 else
10398#endif
10399 band->channels[j].flags |=
10400 IEEE80211_CHAN_DISABLED;
10401 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010402 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 eCSR_BAND_24 == pCfg->nBandCapability) {
10404 /* 2G only */
10405 band->channels[j].flags |=
10406 IEEE80211_CHAN_DISABLED;
10407 continue;
10408 }
10409 }
10410 }
10411 /*Initialise the supported cipher suite details */
10412 wiphy->cipher_suites = hdd_cipher_suites;
10413 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10414
10415 /*signal strength in mBm (100*dBm) */
10416 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10417 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10418
Anurag Chouhan6d760662016-02-20 16:05:43 +053010419 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010420 wiphy->n_vendor_commands =
10421 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10422 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10423
10424 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10425 wiphy->n_vendor_events =
10426 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10427 }
10428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010429 if (pCfg->enableDFSMasterCap) {
10430 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10431 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010432
10433 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10434
10435#ifdef QCA_HT_2040_COEX
10436 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10437#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010438 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010439
10440#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10441 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10442 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10443 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10444 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10445#endif
10446
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010447 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010448 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010449
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010450 EXIT();
10451 return 0;
10452}
10453
Abhishek Singhf512bf32016-05-04 16:47:46 +053010454/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010455 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10456 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010457 *
10458 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010459 * memory allocated in wlan_hdd_cfg80211_init also
10460 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010461 *
10462 * Return: void
10463 */
10464void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10465{
10466 int i;
10467
Dustin Browna30892e2016-10-12 17:28:36 -070010468 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010469 if (NULL != wiphy->bands[i] &&
10470 (NULL != wiphy->bands[i]->channels)) {
10471 qdf_mem_free(wiphy->bands[i]->channels);
10472 wiphy->bands[i]->channels = NULL;
10473 }
10474 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010475
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010476 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010477}
10478
Yingying Tang80e15f32016-09-27 18:23:01 +080010479/**
10480 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10481 * @hdd_ctx: HDD context
10482 *
10483 * this function will update capabilities for supported bands
10484 *
10485 * Return: void
10486 */
10487static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10488{
10489 uint32_t val32;
10490 uint16_t val16;
10491 tSirMacHTCapabilityInfo *ht_cap_info;
10492 QDF_STATUS status;
10493
10494 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10495 if (QDF_STATUS_SUCCESS != status) {
10496 hdd_err("could not get HT capability info");
10497 val32 = 0;
10498 }
10499 val16 = (uint16_t)val32;
10500 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10501
10502 if (ht_cap_info->txSTBC == true) {
10503 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10504 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10505 IEEE80211_HT_CAP_TX_STBC;
10506 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10507 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10508 IEEE80211_HT_CAP_TX_STBC;
10509 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010510
10511 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10512 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10513 vht_cap.vht_supported = 0;
10514 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10515 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10516 vht_cap.vht_supported = 0;
10517 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10518 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010519}
10520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010521/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010522 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010523 * initialization. In wlan_hdd_cfg80211_init, only the
10524 * default values will be initialized. The final initialization
10525 * of all required members can be done here.
10526 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010527void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010528{
Yingying Tang80e15f32016-09-27 18:23:01 +080010529 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10530
10531 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010532}
10533
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010534/**
10535 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10536 * @cfg: hdd cfg
10537 *
10538 * this function update 11n mode in hdd cfg
10539 *
10540 * Return: void
10541 */
10542void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10543{
10544 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010545 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010546 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010547 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010548 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10549 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10550 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10551 cfg->sap_p2p_11ac_override = 0;
10552 }
10553 }
10554}
10555
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556/* In this function we are registering wiphy. */
10557int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10558{
10559 ENTER();
10560 /* Register our wiphy dev with cfg80211 */
10561 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010562 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010563 return -EIO;
10564 }
10565
10566 EXIT();
10567 return 0;
10568}
10569
10570/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010571 * HDD function to update wiphy capability based on target offload status.
10572 *
10573 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10574 * capability even before downloading firmware to the target. In discrete
10575 * case, host will get know certain offload capability (say sched_scan
10576 * caps) only after downloading firmware to the target and target boots up.
10577 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10578 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010579 */
10580void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10581{
10582#ifdef FEATURE_WLAN_SCAN_PNO
10583 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10584 struct hdd_config *pCfg = pHddCtx->config;
10585
10586 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10587 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010588 * have PNO support.
10589 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010590 if (!pCfg->PnoOffload) {
10591 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10592 wiphy->max_sched_scan_ssids = 0;
10593 wiphy->max_match_sets = 0;
10594 wiphy->max_sched_scan_ie_len = 0;
10595 }
10596#endif
10597}
10598
10599/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010600#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10601
Wu Gao84d120c2017-03-24 18:46:00 +080010602void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10603{
10604 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10605 /* Register for all P2P action, public action etc frames */
10606 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10607
10608 ENTER();
10609
10610 /* Register frame indication call back */
10611 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10612
10613 /* Register for p2p ack indication */
10614 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10615
10616 /* Right now we are registering these frame when driver is getting
10617 * initialized. Once we will move to 2.6.37 kernel, in which we have
10618 * frame register ops, we will move this code as a part of that
10619 */
10620
10621 /* GAS Initial Request */
10622 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10623 (uint8_t *) GAS_INITIAL_REQ,
10624 GAS_INITIAL_REQ_SIZE);
10625
10626 /* GAS Initial Response */
10627 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10628 (uint8_t *) GAS_INITIAL_RSP,
10629 GAS_INITIAL_RSP_SIZE);
10630
10631 /* GAS Comeback Request */
10632 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10633 (uint8_t *) GAS_COMEBACK_REQ,
10634 GAS_COMEBACK_REQ_SIZE);
10635
10636 /* GAS Comeback Response */
10637 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10638 (uint8_t *) GAS_COMEBACK_RSP,
10639 GAS_COMEBACK_RSP_SIZE);
10640
10641 /* WNM BSS Transition Request frame */
10642 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10643 (uint8_t *) WNM_BSS_ACTION_FRAME,
10644 WNM_BSS_ACTION_FRAME_SIZE);
10645
10646 /* WNM-Notification */
10647 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10648 (uint8_t *) WNM_NOTIFICATION_FRAME,
10649 WNM_NOTIFICATION_FRAME_SIZE);
10650}
10651#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010652void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10653{
10654 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10655 /* Register for all P2P action, public action etc frames */
10656 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10657
10658 ENTER();
10659
Abhishek Singh7996eb72015-12-30 17:24:02 +053010660 /* Register frame indication call back */
10661 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10662
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010663 /* Register for p2p ack indication */
10664 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10665
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010666 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010667 * initialized. Once we will move to 2.6.37 kernel, in which we have
10668 * frame register ops, we will move this code as a part of that
10669 */
10670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671 /* GAS Initial Request */
10672 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10673 (uint8_t *) GAS_INITIAL_REQ,
10674 GAS_INITIAL_REQ_SIZE);
10675
10676 /* GAS Initial Response */
10677 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10678 (uint8_t *) GAS_INITIAL_RSP,
10679 GAS_INITIAL_RSP_SIZE);
10680
10681 /* GAS Comeback Request */
10682 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10683 (uint8_t *) GAS_COMEBACK_REQ,
10684 GAS_COMEBACK_REQ_SIZE);
10685
10686 /* GAS Comeback Response */
10687 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10688 (uint8_t *) GAS_COMEBACK_RSP,
10689 GAS_COMEBACK_RSP_SIZE);
10690
10691 /* P2P Public Action */
10692 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10693 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10694 P2P_PUBLIC_ACTION_FRAME_SIZE);
10695
10696 /* P2P Action */
10697 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10698 (uint8_t *) P2P_ACTION_FRAME,
10699 P2P_ACTION_FRAME_SIZE);
10700
10701 /* WNM BSS Transition Request frame */
10702 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10703 (uint8_t *) WNM_BSS_ACTION_FRAME,
10704 WNM_BSS_ACTION_FRAME_SIZE);
10705
10706 /* WNM-Notification */
10707 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10708 (uint8_t *) WNM_NOTIFICATION_FRAME,
10709 WNM_NOTIFICATION_FRAME_SIZE);
10710}
Wu Gao84d120c2017-03-24 18:46:00 +080010711#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010712
10713void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10714{
10715 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10716 /* Register for all P2P action, public action etc frames */
10717 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10718
10719 ENTER();
10720
10721 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010722 * initialized. Once we will move to 2.6.37 kernel, in which we have
10723 * frame register ops, we will move this code as a part of that
10724 */
10725
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010726 /* GAS Initial Request */
10727
10728 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10729 (uint8_t *) GAS_INITIAL_REQ,
10730 GAS_INITIAL_REQ_SIZE);
10731
10732 /* GAS Initial Response */
10733 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10734 (uint8_t *) GAS_INITIAL_RSP,
10735 GAS_INITIAL_RSP_SIZE);
10736
10737 /* GAS Comeback Request */
10738 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10739 (uint8_t *) GAS_COMEBACK_REQ,
10740 GAS_COMEBACK_REQ_SIZE);
10741
10742 /* GAS Comeback Response */
10743 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10744 (uint8_t *) GAS_COMEBACK_RSP,
10745 GAS_COMEBACK_RSP_SIZE);
10746
10747 /* P2P Public Action */
10748 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10749 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10750 P2P_PUBLIC_ACTION_FRAME_SIZE);
10751
10752 /* P2P Action */
10753 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10754 (uint8_t *) P2P_ACTION_FRAME,
10755 P2P_ACTION_FRAME_SIZE);
10756
10757 /* WNM-Notification */
10758 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10759 (uint8_t *) WNM_NOTIFICATION_FRAME,
10760 WNM_NOTIFICATION_FRAME_SIZE);
10761}
10762
10763#ifdef FEATURE_WLAN_WAPI
10764void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10765 const uint8_t *mac_addr, const uint8_t *key,
10766 int key_Len)
10767{
10768 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10769 tCsrRoamSetKey setKey;
10770 bool isConnected = true;
10771 int status = 0;
10772 uint32_t roamId = 0xFF;
10773 uint8_t *pKeyPtr = NULL;
10774 int n = 0;
10775
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010776 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 hdd_device_mode_to_string(pAdapter->device_mode),
10778 pAdapter->device_mode);
10779
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010780 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010781 setKey.keyId = key_index; /* Store Key ID */
10782 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10783 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10784 setKey.paeRole = 0; /* the PAE role */
10785 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010786 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010787 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010788 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010789 }
10790 setKey.keyLength = key_Len;
10791 pKeyPtr = setKey.Key;
10792 memcpy(pKeyPtr, key, key_Len);
10793
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010794 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010795 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010796 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010797 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010798
10799 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10800 if (isConnected) {
10801 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10802 pAdapter->sessionId, &setKey, &roamId);
10803 }
10804 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010805 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10807 }
10808}
10809#endif /* FEATURE_WLAN_WAPI */
10810
10811uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10812 uint8_t eid)
10813{
10814 int left = length;
10815 uint8_t *ptr = (uint8_t *)ies_ptr;
10816 uint8_t elem_id, elem_len;
10817
10818 while (left >= 2) {
10819 elem_id = ptr[0];
10820 elem_len = ptr[1];
10821 left -= 2;
10822 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010823 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010824 eid, elem_len, left);
10825 return NULL;
10826 }
10827 if (elem_id == eid) {
10828 return ptr;
10829 }
10830
10831 left -= elem_len;
10832 ptr += (elem_len + 2);
10833 }
10834 return NULL;
10835}
10836
10837/*
10838 * FUNCTION: wlan_hdd_validate_operation_channel
10839 * called by wlan_hdd_cfg80211_start_bss() and
10840 * wlan_hdd_set_channel()
10841 * This function validates whether given channel is part of valid
10842 * channel list.
10843 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010844QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 int channel)
10846{
10847
10848 uint32_t num_ch = 0;
10849 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10850 u32 indx = 0;
10851 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10852 uint8_t fValidChannel = false, count = 0;
10853 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10854
10855 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10856
10857 if (hdd_pConfig_ini->sapAllowAllChannel) {
10858 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010859 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010860 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 fValidChannel = true;
10862 break;
10863 }
10864 }
10865 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010866 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010867 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010868 }
10869 } else {
10870 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10871 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010872 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010873 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010874 }
10875 for (indx = 0; indx < num_ch; indx++) {
10876 if (channel == valid_ch[indx]) {
10877 break;
10878 }
10879 }
10880
10881 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010882 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010883 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 }
10885 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010886 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887
10888}
10889
10890#ifdef DHCP_SERVER_OFFLOAD
10891static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10892{
10893 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10894 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10895 uint8_t numEntries = 0;
10896 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10897 uint8_t num;
10898 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010899 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010901 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010902 return;
10903 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010904 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10905 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10906 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10907 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10908 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10909 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010910 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010911 goto end;
10912 }
10913 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010914 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010915 goto end;
10916 }
10917 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010918 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919 goto end;
10920 }
10921 for (num = 0; num < numEntries; num++) {
10922 temp = srv_ip[num];
10923 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10924 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010925 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010926 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010927 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010928 goto end;
10929 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010930 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010932 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010933 return;
10934}
10935#endif /* DHCP_SERVER_OFFLOAD */
10936
10937static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10938 struct net_device *dev,
10939 struct bss_parameters *params)
10940{
10941 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10942 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10943 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010944 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945
10946 ENTER();
10947
Anurag Chouhan6d760662016-02-20 16:05:43 +053010948 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010949 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 return -EINVAL;
10951 }
10952
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010953 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10954 hdd_err("invalid session id: %d", pAdapter->sessionId);
10955 return -EINVAL;
10956 }
10957
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010958 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010959 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10960 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010961 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010962 hdd_device_mode_to_string(pAdapter->device_mode),
10963 pAdapter->device_mode, params->ap_isolate);
10964
10965 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10966 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010967 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010968 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969
Krunal Sonib4326f22016-03-10 13:05:51 -080010970 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10971 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010972 return -EOPNOTSUPP;
10973 }
10974
10975 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010976 * want to update this parameter
10977 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010978 if (-1 != params->ap_isolate) {
10979 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10980 !!params->ap_isolate;
10981
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010982 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010983 pAdapter->sessionId,
10984 pAdapter->sessionCtx.
10985 ap.
10986 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010987 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010988 ret = -EINVAL;
10989 }
10990 }
10991
10992 EXIT();
10993 return ret;
10994}
10995
Krunal Soni8c37e322016-02-03 16:08:37 -080010996/**
10997 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10998 * @ndev: pointer to net device provided by supplicant
10999 * @type: type of the interface, upper layer wanted to change
11000 *
11001 * Upper layer provides the new interface mode that needs to be changed
11002 * for given net device
11003 *
11004 * Return: success or failure in terms of integer value
11005 */
11006static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 enum nl80211_iftype type)
11008{
Krunal Soni8c37e322016-02-03 16:08:37 -080011009 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11010 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11011 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011012 hdd_wext_state_t *wext;
11013 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011014 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015
11016 ENTER();
11017
Krunal Soni8c37e322016-02-03 16:08:37 -080011018 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011019 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 return 0;
11021 }
11022
11023 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011024 hdd_stop_adapter(hdd_ctx, adapter, true);
11025 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026 wdev->iftype = type;
11027 /*Check for sub-string p2p to confirm its a p2p interface */
11028 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011029 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011030 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011031 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011032 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011033 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011034 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011035 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011036 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011037 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011038 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011039 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11040 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011041 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11042 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011043 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011044 adapter->scan_info.scanAddIE.length;
11045 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011046 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011047 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11048 wext->roamProfile.phyMode =
11049 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11050 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011051 EXIT();
11052 return status;
11053}
11054
11055static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11056 struct net_device *dev,
11057 struct bss_parameters *params)
11058{
11059 int ret;
11060
11061 cds_ssr_protect(__func__);
11062 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11063 cds_ssr_unprotect(__func__);
11064
11065 return ret;
11066}
11067
11068/* FUNCTION: wlan_hdd_change_country_code_cd
11069 * to wait for contry code completion
11070 */
11071void *wlan_hdd_change_country_code_cb(void *pAdapter)
11072{
11073 hdd_adapter_t *call_back_pAdapter = pAdapter;
11074 complete(&call_back_pAdapter->change_country_code);
11075 return NULL;
11076}
11077
Rajeev Kumar98edb772016-01-19 12:42:19 -080011078/**
11079 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11080 * @wiphy: Pointer to the wiphy structure
11081 * @ndev: Pointer to the net device
11082 * @type: Interface type
11083 * @flags: Flags for change interface
11084 * @params: Pointer to change interface parameters
11085 *
11086 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 */
11088static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11089 struct net_device *ndev,
11090 enum nl80211_iftype type,
11091 u32 *flags,
11092 struct vif_params *params)
11093{
11094 struct wireless_dev *wdev;
11095 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11096 hdd_context_t *pHddCtx;
11097 tCsrRoamProfile *pRoamProfile = NULL;
11098 eCsrRoamBssType LastBSSType;
11099 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011100 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011101 int status;
11102
11103 ENTER();
11104
Anurag Chouhan6d760662016-02-20 16:05:43 +053011105 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011106 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107 return -EINVAL;
11108 }
11109
11110 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11111 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011112 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011113 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011114
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011115 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011116 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11117 pAdapter->sessionId, type));
11118
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011119 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011120 pAdapter->device_mode, type);
11121
Arun Khandavallifae92942016-08-01 13:31:08 +053011122 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11123 if (status) {
11124 hdd_err("Failed to start modules");
11125 return -EINVAL;
11126 }
11127
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011128 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11130 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011131 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 return -EINVAL;
11133 }
11134
11135 pConfig = pHddCtx->config;
11136 wdev = ndev->ieee80211_ptr;
11137
11138 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011139 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11140 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011141
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011142 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011143 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011144 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11145 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11146 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11147 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011148 hdd_wext_state_t *pWextState =
11149 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11150
11151 pRoamProfile = &pWextState->roamProfile;
11152 LastBSSType = pRoamProfile->BSSType;
11153
11154 switch (type) {
11155 case NL80211_IFTYPE_STATION:
11156 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011157 case NL80211_IFTYPE_ADHOC:
11158 if (type == NL80211_IFTYPE_ADHOC) {
11159 wlan_hdd_tdls_exit(pAdapter);
11160 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011161 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011162 }
11163 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11164 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011165 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011167 if (hdd_start_adapter(pAdapter)) {
11168 hdd_err("Failed to start adapter :%d",
11169 pAdapter->device_mode);
11170 return -EINVAL;
11171 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011173 case NL80211_IFTYPE_AP:
11174 case NL80211_IFTYPE_P2P_GO:
11175 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011176 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 (type ==
11178 NL80211_IFTYPE_AP) ? "SoftAP" :
11179 "P2pGo");
11180
11181 /* Cancel any remain on channel for GO mode */
11182 if (NL80211_IFTYPE_P2P_GO == type) {
11183 wlan_hdd_cancel_existing_remain_on_channel
11184 (pAdapter);
11185 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186
Arun Khandavallifae92942016-08-01 13:31:08 +053011187 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011188 /* De-init the adapter */
11189 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11190 memset(&pAdapter->sessionCtx, 0,
11191 sizeof(pAdapter->sessionCtx));
11192 pAdapter->device_mode =
11193 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011194 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11195 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196
11197 /*
11198 * Fw will take care incase of concurrency
11199 */
11200
Krunal Sonib4326f22016-03-10 13:05:51 -080011201 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011202 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011203 /* To meet Android requirements create
11204 * a randomized MAC address of the
11205 * form 02:1A:11:Fx:xx:xx
11206 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207 get_random_bytes(&ndev->dev_addr[3], 3);
11208 ndev->dev_addr[0] = 0x02;
11209 ndev->dev_addr[1] = 0x1A;
11210 ndev->dev_addr[2] = 0x11;
11211 ndev->dev_addr[3] |= 0xF0;
11212 memcpy(pAdapter->macAddressCurrent.
11213 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011214 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011215 pr_info("wlan: Generated HotSpot BSSID "
11216 MAC_ADDRESS_STR "\n",
11217 MAC_ADDR_ARRAY(ndev->dev_addr));
11218 }
11219
11220 hdd_set_ap_ops(pAdapter->dev);
11221
Arun Khandavallifae92942016-08-01 13:31:08 +053011222 if (hdd_start_adapter(pAdapter)) {
11223 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011224 return -EINVAL;
11225 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226 /* Interface type changed update in wiphy structure */
11227 if (wdev) {
11228 wdev->iftype = type;
11229 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011230 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011231 return -EINVAL;
11232 }
11233 goto done;
11234 }
11235
11236 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011237 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 return -EOPNOTSUPP;
11239 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011240 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11241 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 switch (type) {
11243 case NL80211_IFTYPE_STATION:
11244 case NL80211_IFTYPE_P2P_CLIENT:
11245 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011246 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11247 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011248 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011250 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011251 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011252 pAdapter->device_mode);
11253 return -EINVAL;
11254 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011255 goto done;
11256
11257 case NL80211_IFTYPE_AP:
11258 case NL80211_IFTYPE_P2P_GO:
11259 wdev->iftype = type;
11260 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011261 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262 goto done;
11263
11264 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011265 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011266 return -EOPNOTSUPP;
11267 }
11268 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011269 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 pAdapter->device_mode);
11271 return -EOPNOTSUPP;
11272 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273done:
11274 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011275 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11276 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011277
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011278 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011279
11280 EXIT();
11281 return 0;
11282}
11283
Rajeev Kumar98edb772016-01-19 12:42:19 -080011284/**
11285 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11286 * @wiphy: Pointer to the wiphy structure
11287 * @ndev: Pointer to the net device
11288 * @type: Interface type
11289 * @flags: Flags for change interface
11290 * @params: Pointer to change interface parameters
11291 *
11292 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011293 */
11294static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11295 struct net_device *ndev,
11296 enum nl80211_iftype type,
11297 u32 *flags,
11298 struct vif_params *params)
11299{
11300 int ret;
11301
11302 cds_ssr_protect(__func__);
11303 ret =
11304 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11305 cds_ssr_unprotect(__func__);
11306
11307 return ret;
11308}
11309
Frank Liud4b2fa02017-03-29 11:46:48 +080011310#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011311static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11312 int index, uint8_t match)
11313{
11314 int i;
11315 for (i = 0; i < index; i++) {
11316 if (arr[i] == match)
11317 return true;
11318 }
11319 return false;
11320}
11321#endif
11322
11323/**
11324 * __wlan_hdd_change_station() - change station
11325 * @wiphy: Pointer to the wiphy structure
11326 * @dev: Pointer to the net device.
11327 * @mac: bssid
11328 * @params: Pointer to station parameters
11329 *
11330 * Return: 0 for success, error number on failure.
11331 */
11332#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11333static int __wlan_hdd_change_station(struct wiphy *wiphy,
11334 struct net_device *dev,
11335 const uint8_t *mac,
11336 struct station_parameters *params)
11337#else
11338static int __wlan_hdd_change_station(struct wiphy *wiphy,
11339 struct net_device *dev,
11340 uint8_t *mac,
11341 struct station_parameters *params)
11342#endif
11343{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011344 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011345 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11346 hdd_context_t *pHddCtx;
11347 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011348 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011349#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011350 tCsrStaParams StaParams = { 0 };
11351 uint8_t isBufSta = 0;
11352 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011353 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354#endif
11355 int ret;
11356
11357 ENTER();
11358
Anurag Chouhan6d760662016-02-20 16:05:43 +053011359 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011360 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361 return -EINVAL;
11362 }
11363
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011364 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011365 TRACE_CODE_HDD_CHANGE_STATION,
11366 pAdapter->sessionId, params->listen_interval));
11367
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011368 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11369 hdd_err("invalid session id: %d", pAdapter->sessionId);
11370 return -EINVAL;
11371 }
11372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011373 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11374 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011375 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377
11378 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11379
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011380 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011381
Krunal Sonib4326f22016-03-10 13:05:51 -080011382 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11383 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011384 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11385 status =
11386 hdd_softap_change_sta_state(pAdapter,
11387 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011388 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011389
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011390 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011391 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392 return -EINVAL;
11393 }
11394 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011395 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11396 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011397 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011398#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11399 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11400 dev, mac, params);
11401#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011402
11403 if (cds_is_sub_20_mhz_enabled()) {
11404 hdd_err("TDLS not allowed with sub 20 MHz");
11405 return -EINVAL;
11406 }
11407
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011408 StaParams.capability = params->capability;
11409 StaParams.uapsd_queues = params->uapsd_queues;
11410 StaParams.max_sp = params->max_sp;
11411
11412 /* Convert (first channel , number of channels) tuple to
11413 * the total list of channels. This goes with the assumption
11414 * that if the first channel is < 14, then the next channels
11415 * are an incremental of 1 else an incremental of 4 till the number
11416 * of channels.
11417 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011418 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419 if (0 != params->supported_channels_len) {
11420 int i = 0, j = 0, k = 0, no_of_channels = 0;
11421 int num_unique_channels;
11422 int next;
11423 for (i = 0;
11424 i < params->supported_channels_len
11425 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11426 int wifi_chan_index;
11427 if (!wlan_hdd_is_duplicate_channel
11428 (StaParams.supported_channels, j,
11429 params->supported_channels[i])) {
11430 StaParams.
11431 supported_channels[j] =
11432 params->
11433 supported_channels[i];
11434 } else {
11435 continue;
11436 }
11437 wifi_chan_index =
11438 ((StaParams.supported_channels[j] <=
11439 HDD_CHANNEL_14) ? 1 : 4);
11440 no_of_channels =
11441 params->supported_channels[i + 1];
11442
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011443 hdd_debug("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 -080011444 StaParams.
11445 supported_channels[j],
11446 wifi_chan_index,
11447 no_of_channels);
11448 for (k = 1; k <= no_of_channels &&
11449 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11450 k++) {
11451 next =
11452 StaParams.
11453 supported_channels[j] +
11454 wifi_chan_index;
11455 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11456 StaParams.
11457 supported_channels[j
11458 +
11459 1]
11460 = next;
11461 } else {
11462 continue;
11463 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011464 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 j + 1,
11466 StaParams.
11467 supported_channels[j +
11468 1]);
11469 j += 1;
11470 }
11471 }
11472 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011473 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011474 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011475 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476 StaParams.
11477 supported_channels[i]);
11478 }
11479 if (MAX_CHANNEL < num_unique_channels)
11480 num_unique_channels = MAX_CHANNEL;
11481 StaParams.supported_channels_len =
11482 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011483 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011484 StaParams.supported_channels_len);
11485 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011486 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011487 params->supported_oper_classes,
11488 params->supported_oper_classes_len);
11489 StaParams.supported_oper_classes_len =
11490 params->supported_oper_classes_len;
11491
11492 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011493 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011494 params->ext_capab,
11495 sizeof(StaParams.extn_capability));
11496
11497 if (NULL != params->ht_capa) {
11498 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011499 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 sizeof(tSirHTCap));
11501 }
11502
11503 StaParams.supported_rates_len =
11504 params->supported_rates_len;
11505
11506 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11507 * The supported_rates array , for all the structures propogating till Add Sta
11508 * to the firmware has to be modified , if the supplicant (ieee80211) is
11509 * modified to send more rates.
11510 */
11511
11512 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11513 */
11514 if (StaParams.supported_rates_len >
11515 SIR_MAC_MAX_SUPP_RATES)
11516 StaParams.supported_rates_len =
11517 SIR_MAC_MAX_SUPP_RATES;
11518
11519 if (0 != StaParams.supported_rates_len) {
11520 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011521 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011522 params->supported_rates,
11523 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011524 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011525 StaParams.supported_rates_len);
11526 for (i = 0; i < StaParams.supported_rates_len;
11527 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011528 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 StaParams.supported_rates[i]);
11530 }
11531
11532 if (NULL != params->vht_capa) {
11533 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011534 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535 params->vht_capa,
11536 sizeof(tSirVHTCap));
11537 }
11538
11539 if (0 != params->ext_capab_len) {
11540 /*Define A Macro : TODO Sunil */
11541 if ((1 << 4) & StaParams.extn_capability[3]) {
11542 isBufSta = 1;
11543 }
11544 /* TDLS Channel Switching Support */
11545 if ((1 << 6) & StaParams.extn_capability[3]) {
11546 isOffChannelSupported = 1;
11547 }
11548 }
11549
Nitesh Shah99934ac2016-09-05 15:54:08 +053011550 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011551 (params->ht_capa || params->vht_capa ||
11552 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011553 is_qos_wmm_sta = true;
11554
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011555 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011556 " is_qos_wmm_sta= %d HTcapPresent = %d",
11557 __func__, is_qos_wmm_sta,
11558 StaParams.htcap_present);
11559
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011560 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011561 &StaParams,
11562 isBufSta,
11563 isOffChannelSupported,
11564 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011565 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011566 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 return -EINVAL;
11568 }
11569
11570 status =
11571 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11572 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011573 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011574 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011575 return -EINVAL;
11576 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011577#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011578 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011579 }
11580 EXIT();
11581 return ret;
11582}
11583
11584/**
11585 * wlan_hdd_change_station() - cfg80211 change station handler function
11586 * @wiphy: Pointer to the wiphy structure
11587 * @dev: Pointer to the net device.
11588 * @mac: bssid
11589 * @params: Pointer to station parameters
11590 *
11591 * This is the cfg80211 change station handler function which invokes
11592 * the internal function @__wlan_hdd_change_station with
11593 * SSR protection.
11594 *
11595 * Return: 0 for success, error number on failure.
11596 */
11597#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11598static int wlan_hdd_change_station(struct wiphy *wiphy,
11599 struct net_device *dev,
11600 const u8 *mac,
11601 struct station_parameters *params)
11602#else
11603static int wlan_hdd_change_station(struct wiphy *wiphy,
11604 struct net_device *dev,
11605 u8 *mac,
11606 struct station_parameters *params)
11607#endif
11608{
11609 int ret;
11610
11611 cds_ssr_protect(__func__);
11612 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11613 cds_ssr_unprotect(__func__);
11614
11615 return ret;
11616}
11617
11618/*
11619 * FUNCTION: __wlan_hdd_cfg80211_add_key
11620 * This function is used to initialize the key information
11621 */
11622static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11623 struct net_device *ndev,
11624 u8 key_index, bool pairwise,
11625 const u8 *mac_addr,
11626 struct key_params *params)
11627{
11628 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11629 tCsrRoamSetKey setKey;
11630 int status;
11631 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011633 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634 hdd_context_t *pHddCtx;
11635 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11636
11637 ENTER();
11638
Anurag Chouhan6d760662016-02-20 16:05:43 +053011639 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 return -EINVAL;
11642 }
11643
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011644 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011645 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011646 return -EINVAL;
11647 }
11648
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011649 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11651 pAdapter->sessionId, params->key_len));
11652 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11653 status = wlan_hdd_validate_context(pHddCtx);
11654
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011655 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011656 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011658 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011659 hdd_device_mode_to_string(pAdapter->device_mode),
11660 pAdapter->device_mode);
11661
11662 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011663 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664
11665 return -EINVAL;
11666 }
11667
11668 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011669 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011670
11671 return -EINVAL;
11672 }
11673
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011674 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011675
11676 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011677 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011678 setKey.keyId = key_index;
11679 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011680 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011681
11682 switch (params->cipher) {
11683 case WLAN_CIPHER_SUITE_WEP40:
11684 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11685 break;
11686
11687 case WLAN_CIPHER_SUITE_WEP104:
11688 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11689 break;
11690
11691 case WLAN_CIPHER_SUITE_TKIP:
11692 {
11693 u8 *pKey = &setKey.Key[0];
11694 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11695
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011696 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011697
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011698 /* Supplicant sends the 32bytes key in this order
11699 *
11700 * |--------------|----------|----------|
11701 * | Tk1 |TX-MIC | RX Mic |
11702 * |--------------|----------|----------|
11703 * <---16bytes---><--8bytes--><--8bytes-->
11704 *
11705 * Sme expects the 32 bytes key to be in the below order
11706 *
11707 * |--------------|----------|----------|
11708 * | Tk1 |RX-MIC | TX Mic |
11709 * |--------------|----------|----------|
11710 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011711 */
11712 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011713 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714
11715 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011716 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011717
11718 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011719 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011720
11721 break;
11722 }
11723
11724 case WLAN_CIPHER_SUITE_CCMP:
11725 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11726 break;
11727
11728#ifdef FEATURE_WLAN_WAPI
11729 case WLAN_CIPHER_SUITE_SMS4:
11730 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011731 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011732 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11733 mac_addr, params->key,
11734 params->key_len);
11735 return 0;
11736 }
11737#endif
11738
11739#ifdef FEATURE_WLAN_ESE
11740 case WLAN_CIPHER_SUITE_KRK:
11741 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11742 break;
11743#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11744 case WLAN_CIPHER_SUITE_BTK:
11745 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11746 break;
11747#endif
11748#endif
11749
11750#ifdef WLAN_FEATURE_11W
11751 case WLAN_CIPHER_SUITE_AES_CMAC:
11752 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11753 break;
11754#endif
11755
11756 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011757 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011758 return -EOPNOTSUPP;
11759 }
11760
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011761 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011762
11763 if (!pairwise) {
11764 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011765 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011767 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 } else {
11769 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011770 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011772 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011774 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775 /* if a key is already installed, block all subsequent ones */
11776 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011777 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011778 return 0;
11779 }
11780
11781 setKey.keyDirection = eSIR_TX_RX;
11782 /*Set the group key */
11783 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11784 pAdapter->sessionId, &setKey, &roamId);
11785
11786 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011787 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011788 return -EINVAL;
11789 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011790 /* Save the keys here and call sme_roam_set_key for setting
11791 * the PTK after peer joins the IBSS network
11792 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011793 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011794 &setKey, sizeof(tCsrRoamSetKey));
11795
11796 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11797 return status;
11798 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011799 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11800 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11802 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011803 status = wlansap_set_key_sta(
11804 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011805 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011806 hdd_err("wlansap_set_key_sta failed status: %d",
11807 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011808 }
11809 }
11810
11811 /* Save the key in ap ctx for use on START_BASS and restart */
11812 if (pairwise ||
11813 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11814 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011815 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816 sizeof(tCsrRoamSetKey));
11817 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011818 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011819 sizeof(tCsrRoamSetKey));
11820
Krunal Sonib4326f22016-03-10 13:05:51 -080011821 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11822 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 hdd_wext_state_t *pWextState =
11824 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11825 hdd_station_ctx_t *pHddStaCtx =
11826 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11827
11828 if (!pairwise) {
11829 /* set group key */
11830 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011831 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832 __func__, __LINE__);
11833 hdd_perform_roam_set_key_complete(pAdapter);
11834 }
11835 }
11836
11837 pWextState->roamProfile.Keys.KeyLength[key_index] =
11838 (u8) params->key_len;
11839
11840 pWextState->roamProfile.Keys.defaultIndex = key_index;
11841
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011842 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843 KeyMaterial[key_index][0], params->key,
11844 params->key_len);
11845
11846 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11847
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011848 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011849 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11850 setKey.keyDirection);
11851
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011852 /* The supplicant may attempt to set the PTK once
11853 * pre-authentication is done. Save the key in the
11854 * UMAC and include it in the ADD BSS request
11855 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011856 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011857 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011858 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011859 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011860 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011861 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011862 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011863 return -EINVAL;
11864 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865
11866 /* issue set key request to SME */
11867 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11868 pAdapter->sessionId, &setKey, &roamId);
11869
11870 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011871 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011872 pHddStaCtx->roam_info.roamingState =
11873 HDD_ROAM_STATE_NONE;
11874 return -EINVAL;
11875 }
11876
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011877 /* in case of IBSS as there was no information
11878 * available about WEP keys during IBSS join, group
11879 * key intialized with NULL key, so re-initialize
11880 * group key with correct value
11881 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882 if ((eCSR_BSS_TYPE_START_IBSS ==
11883 pWextState->roamProfile.BSSType)
11884 &&
11885 !((IW_AUTH_KEY_MGMT_802_1X ==
11886 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11887 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11888 pHddStaCtx->conn_info.authType)
11889 )
11890 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11891 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11892 )
11893 ) {
11894 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011895 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011896
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011897 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011898 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11899 setKey.keyDirection);
11900
11901 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11902 pAdapter->sessionId, &setKey,
11903 &roamId);
11904
11905 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011906 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011907 pHddStaCtx->roam_info.roamingState =
11908 HDD_ROAM_STATE_NONE;
11909 return -EINVAL;
11910 }
11911 }
11912 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011913 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011914 return 0;
11915}
11916
11917static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11918 struct net_device *ndev,
11919 u8 key_index, bool pairwise,
11920 const u8 *mac_addr,
11921 struct key_params *params)
11922{
11923 int ret;
11924 cds_ssr_protect(__func__);
11925 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11926 mac_addr, params);
11927 cds_ssr_unprotect(__func__);
11928
11929 return ret;
11930}
11931
11932/*
11933 * FUNCTION: __wlan_hdd_cfg80211_get_key
11934 * This function is used to get the key information
11935 */
11936static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11937 struct net_device *ndev,
11938 u8 key_index, bool pairwise,
11939 const u8 *mac_addr, void *cookie,
11940 void (*callback)(void *cookie,
11941 struct key_params *)
11942 )
11943{
11944 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11945 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11946 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11947 struct key_params params;
11948
11949 ENTER();
11950
Anurag Chouhan6d760662016-02-20 16:05:43 +053011951 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011952 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011953 return -EINVAL;
11954 }
11955
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011956 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011957 hdd_device_mode_to_string(pAdapter->device_mode),
11958 pAdapter->device_mode);
11959
11960 memset(&params, 0, sizeof(params));
11961
11962 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011963 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011964 return -EINVAL;
11965 }
11966
11967 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11968 case eCSR_ENCRYPT_TYPE_NONE:
11969 params.cipher = IW_AUTH_CIPHER_NONE;
11970 break;
11971
11972 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11973 case eCSR_ENCRYPT_TYPE_WEP40:
11974 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11975 break;
11976
11977 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11978 case eCSR_ENCRYPT_TYPE_WEP104:
11979 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11980 break;
11981
11982 case eCSR_ENCRYPT_TYPE_TKIP:
11983 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11984 break;
11985
11986 case eCSR_ENCRYPT_TYPE_AES:
11987 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11988 break;
11989
11990 default:
11991 params.cipher = IW_AUTH_CIPHER_NONE;
11992 break;
11993 }
11994
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011995 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 TRACE_CODE_HDD_CFG80211_GET_KEY,
11997 pAdapter->sessionId, params.cipher));
11998
11999 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12000 params.seq_len = 0;
12001 params.seq = NULL;
12002 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12003 callback(cookie, &params);
12004
12005 EXIT();
12006 return 0;
12007}
12008
12009static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12010 struct net_device *ndev,
12011 u8 key_index, bool pairwise,
12012 const u8 *mac_addr, void *cookie,
12013 void (*callback)(void *cookie,
12014 struct key_params *)
12015 )
12016{
12017 int ret;
12018
12019 cds_ssr_protect(__func__);
12020 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12021 mac_addr, cookie, callback);
12022 cds_ssr_unprotect(__func__);
12023
12024 return ret;
12025}
12026
12027/**
12028 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12029 * @wiphy: wiphy interface context
12030 * @ndev: pointer to net device
12031 * @key_index: Key index used in 802.11 frames
12032 * @unicast: true if it is unicast key
12033 * @multicast: true if it is multicast key
12034 *
12035 * This function is required for cfg80211_ops API.
12036 * It is used to delete the key information
12037 * Underlying hardware implementation does not have API to delete the
12038 * encryption key. It is automatically deleted when the peer is
12039 * removed. Hence this function currently does nothing.
12040 * Future implementation may interprete delete key operation to
12041 * replacing the key with a random junk value, effectively making it
12042 * useless.
12043 *
12044 * Return: status code, always 0.
12045 */
12046
12047static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12048 struct net_device *ndev,
12049 u8 key_index,
12050 bool pairwise, const u8 *mac_addr)
12051{
12052 EXIT();
12053 return 0;
12054}
12055
12056/**
12057 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12058 * @wiphy: Pointer to wiphy structure.
12059 * @dev: Pointer to net_device structure.
12060 * @key_index: key index
12061 * @pairwise: pairwise
12062 * @mac_addr: mac address
12063 *
12064 * This is the cfg80211 delete key handler function which invokes
12065 * the internal function @__wlan_hdd_cfg80211_del_key with
12066 * SSR protection.
12067 *
12068 * Return: 0 for success, error number on failure.
12069 */
12070static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12071 struct net_device *dev,
12072 u8 key_index,
12073 bool pairwise, const u8 *mac_addr)
12074{
12075 int ret;
12076
12077 cds_ssr_protect(__func__);
12078 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12079 pairwise, mac_addr);
12080 cds_ssr_unprotect(__func__);
12081
12082 return ret;
12083}
12084
12085/*
12086 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12087 * This function is used to set the default tx key index
12088 */
12089static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12090 struct net_device *ndev,
12091 u8 key_index,
12092 bool unicast, bool multicast)
12093{
12094 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12095 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12096 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12097 hdd_context_t *pHddCtx;
12098 int status;
12099
12100 ENTER();
12101
Anurag Chouhan6d760662016-02-20 16:05:43 +053012102 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012103 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012104 return -EINVAL;
12105 }
12106
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012107 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012108 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012109 return -EINVAL;
12110 }
12111
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012112 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12114 pAdapter->sessionId, key_index));
12115
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012116 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 hdd_device_mode_to_string(pAdapter->device_mode),
12118 pAdapter->device_mode, key_index);
12119
12120 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012121 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122 return -EINVAL;
12123 }
12124
12125 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12126 status = wlan_hdd_validate_context(pHddCtx);
12127
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012128 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012129 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012130
Krunal Sonib4326f22016-03-10 13:05:51 -080012131 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12132 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012133 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12134 pHddStaCtx->conn_info.ucEncryptionType) &&
12135 (eCSR_ENCRYPT_TYPE_AES !=
12136 pHddStaCtx->conn_info.ucEncryptionType)) {
12137 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012138 * then update the default key index
12139 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012140
12141 tCsrRoamSetKey setKey;
12142 uint32_t roamId = 0xFF;
12143 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12144
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012145 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012146
12147 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012148 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012149 setKey.keyId = key_index;
12150 setKey.keyLength = Keys->KeyLength[key_index];
12151
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012152 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012153 &Keys->KeyMaterial[key_index][0],
12154 Keys->KeyLength[key_index]);
12155
12156 setKey.keyDirection = eSIR_TX_RX;
12157
Anurag Chouhanc5548422016-02-24 18:33:27 +053012158 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012159 &pHddStaCtx->conn_info.bssId);
12160
12161 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12162 pWextState->roamProfile.EncryptionType.
12163 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012164 /* In the case of dynamic wep
12165 * supplicant hardcodes DWEP type to
12166 * eCSR_ENCRYPT_TYPE_WEP104 even
12167 * though ap is configured for WEP-40
12168 * encryption. In this canse the key
12169 * length is 5 but the encryption type
12170 * is 104 hence checking the key
12171 * lenght(5) and encryption type(104)
12172 * and switching encryption type to 40
12173 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 pWextState->roamProfile.EncryptionType.
12175 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12176 pWextState->roamProfile.mcEncryptionType.
12177 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12178 }
12179
12180 setKey.encType =
12181 pWextState->roamProfile.EncryptionType.
12182 encryptionType[0];
12183
12184 /* Issue set key request */
12185 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12186 pAdapter->sessionId, &setKey,
12187 &roamId);
12188
12189 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012190 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 status);
12192 return -EINVAL;
12193 }
12194 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012195 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012196 /* In SoftAp mode setting key direction for default mode */
12197 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12198 pWextState->roamProfile.EncryptionType.encryptionType[0])
12199 && (eCSR_ENCRYPT_TYPE_AES !=
12200 pWextState->roamProfile.EncryptionType.
12201 encryptionType[0])) {
12202 /* Saving key direction for default key index to TX default */
12203 hdd_ap_ctx_t *pAPCtx =
12204 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12205 pAPCtx->wepKey[key_index].keyDirection =
12206 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012207 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012208 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012209 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012210 }
12211 }
12212
12213 EXIT();
12214 return status;
12215}
12216
12217static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12218 struct net_device *ndev,
12219 u8 key_index,
12220 bool unicast, bool multicast)
12221{
12222 int ret;
12223 cds_ssr_protect(__func__);
12224 ret =
12225 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12226 multicast);
12227 cds_ssr_unprotect(__func__);
12228
12229 return ret;
12230}
12231
Abhishek Singhc9941602016-08-09 16:06:22 +053012232/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012233 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12234 * interface that BSS might have been lost.
12235 * @pAdapter: adaptor
12236 * @bssid: bssid which might have been lost
12237 *
12238 * Return: bss which is unlinked from kernel cache
12239 */
12240struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12241 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012242{
12243 struct net_device *dev = pAdapter->dev;
12244 struct wireless_dev *wdev = dev->ieee80211_ptr;
12245 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 struct cfg80211_bss *bss = NULL;
12247
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012248 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012249 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012250 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012251 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012252 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012253 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012254 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012255 cfg80211_unlink_bss(wiphy, bss);
12256 }
12257 return bss;
12258}
12259
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012260#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12261 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12262static struct cfg80211_bss *
12263wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12264 struct ieee80211_channel *chan,
12265 struct ieee80211_mgmt *mgmt,
12266 size_t frame_len,
12267 int rssi, gfp_t gfp,
12268 uint64_t boottime_ns)
12269{
12270 struct cfg80211_bss *bss_status = NULL;
12271 struct cfg80211_inform_bss data = {0};
12272
12273 data.chan = chan;
12274 data.boottime_ns = boottime_ns;
12275 data.signal = rssi;
12276 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12277 frame_len, gfp);
12278 return bss_status;
12279}
12280#else
12281static struct cfg80211_bss *
12282wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12283 struct ieee80211_channel *chan,
12284 struct ieee80211_mgmt *mgmt,
12285 size_t frame_len,
12286 int rssi, gfp_t gfp,
12287 uint64_t boottime_ns)
12288{
12289 struct cfg80211_bss *bss_status = NULL;
12290
12291 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12292 rssi, gfp);
12293 return bss_status;
12294}
12295#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012296
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297/**
12298 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12299 * @pAdapter: Pointer to adapter
12300 * @bss_desc: Pointer to bss descriptor
12301 *
12302 * This function is used to inform the BSS details to nl80211 interface.
12303 *
12304 * Return: struct cfg80211_bss pointer
12305 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012306struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12307 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012308{
12309 /*
12310 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12311 * already exists in bss data base of cfg80211 for that particular BSS
12312 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12313 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12314 * As of now there is no possibility to get the mgmt(probe response)
12315 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12316 * and passing to cfg80211_inform_bss_frame.
12317 */
12318 struct net_device *dev = pAdapter->dev;
12319 struct wireless_dev *wdev = dev->ieee80211_ptr;
12320 struct wiphy *wiphy = wdev->wiphy;
12321 int chan_no = bss_desc->channelId;
12322#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12323 qcom_ie_age *qie_age = NULL;
12324 int ie_length =
12325 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12326#else
12327 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12328#endif
12329 const char *ie =
12330 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12331 unsigned int freq;
12332 struct ieee80211_channel *chan;
12333 struct ieee80211_mgmt *mgmt = NULL;
12334 struct cfg80211_bss *bss_status = NULL;
12335 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12336 int rssi = 0;
12337 hdd_context_t *pHddCtx;
12338 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012340 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012341
12342 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12343 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012344 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012345 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012346
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012347 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012348 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012349 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012350 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012351 return NULL;
12352 }
12353
12354 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012357 * Instead it wants a monotonic increasing value
12358 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012359 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012360 mgmt->u.probe_resp.timestamp =
12361 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012362
12363 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12364 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12365
12366#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12367 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12368 /* Assuming this is the last IE, copy at the end */
12369 ie_length -= sizeof(qcom_ie_age);
12370 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12371 qie_age->element_id = QCOM_VENDOR_IE_ID;
12372 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12373 qie_age->oui_1 = QCOM_OUI1;
12374 qie_age->oui_2 = QCOM_OUI2;
12375 qie_age->oui_3 = QCOM_OUI3;
12376 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012377 /*
12378 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12379 * all bss related timestamp is in units of ms. Due to this when scan
12380 * results are sent to lowi the scan age is high.To address this,
12381 * send age in units of 1/10 ms.
12382 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012384 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012385 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012386 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12387 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012388 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12389 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390#endif
12391
12392 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12393 if (bss_desc->fProbeRsp) {
12394 mgmt->frame_control |=
12395 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12396 } else {
12397 mgmt->frame_control |=
12398 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12399 }
12400
12401 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012402 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403 freq =
12404 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012405 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012407 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 freq =
12409 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012410 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012411 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012412 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012413 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012414 return NULL;
12415 }
12416
12417 chan = __ieee80211_get_channel(wiphy, freq);
12418 /* When the band is changed on the fly using the GUI, three things are done
12419 * 1. scan abort
12420 * 2. flush scan results from cache
12421 * 3. update the band with the new band user specified (refer to the
12422 * hdd_set_band_helper function) as part of the scan abort, message will be
12423 * queued to PE and we proceed with flushing and changinh the band.
12424 * PE will stop the scanning further and report back the results what ever
12425 * it had till now by calling the call back function.
12426 * if the time between update band and scandone call back is sufficient
12427 * enough the band change reflects in SME, SME validates the channels
12428 * and discards the channels correponding to previous band and calls back
12429 * with zero bss results. but if the time between band update and scan done
12430 * callback is very small then band change will not reflect in SME and SME
12431 * reports to HDD all the channels correponding to previous band.this is due
12432 * to race condition.but those channels are invalid to the new band and so
12433 * this function __ieee80211_get_channel will return NULL.Each time we
12434 * report scan result with this pointer null warning kernel trace is printed.
12435 * if the scan results contain large number of APs continuosly kernel
12436 * warning trace is printed and it will lead to apps watch dog bark.
12437 * So drop the bss and continue to next bss.
12438 */
12439 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012440 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12441 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012442 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012443 return NULL;
12444 }
12445
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012446 /* Based on .ini configuration, raw rssi can be reported for bss.
12447 * Raw rssi is typically used for estimating power.
12448 */
12449
12450 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12451 bss_desc->rssi;
12452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012453 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012454 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012456 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012457 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012458 (int)(rssi / 100),
12459 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012460
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012461 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12462 frame_len, rssi,
12463 GFP_KERNEL,
12464 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012465 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012466 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012467 return bss_status;
12468}
12469
12470/**
12471 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12472 * @pAdapter: Pointer to adapter
12473 * @pRoamInfo: Pointer to roam info
12474 *
12475 * This function is used to update the BSS data base of CFG8011
12476 *
12477 * Return: struct cfg80211_bss pointer
12478 */
12479struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12480 tCsrRoamInfo *pRoamInfo)
12481{
12482 tCsrRoamConnectedProfile roamProfile;
12483 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12484 struct cfg80211_bss *bss = NULL;
12485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12487 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12488
12489 if (NULL != roamProfile.pBssDesc) {
12490 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12491 roamProfile.pBssDesc);
12492
12493 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012494 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012495
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012496 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012497 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012498 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012499 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 return bss;
12501}
12502/**
12503 * wlan_hdd_cfg80211_update_bss() - update bss
12504 * @wiphy: Pointer to wiphy
12505 * @pAdapter: Pointer to adapter
12506 * @scan_time: scan request timestamp
12507 *
12508 * Return: zero if success, non-zero otherwise
12509 */
12510int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12511 hdd_adapter_t *pAdapter,
12512 uint32_t scan_time)
12513{
12514 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12515 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012516 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012517 tScanResultHandle pResult;
12518 struct cfg80211_bss *bss_status = NULL;
12519 hdd_context_t *pHddCtx;
12520 int ret;
12521
12522 ENTER();
12523
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012524 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12525 hdd_err("invalid session id: %d", pAdapter->sessionId);
12526 return -EINVAL;
12527 }
12528
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012529 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12531 NO_SESSION, pAdapter->sessionId));
12532
12533 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12534 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012535 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012537
12538 /* start getting scan results and populate cgf80211 BSS database */
12539 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12540
12541 /* no scan results */
12542 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012543 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012544 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 }
12546
12547 pScanResult = sme_scan_result_get_first(hHal, pResult);
12548
12549 while (pScanResult) {
12550 /*
12551 * - cfg80211_inform_bss() is not updating ie field of bss
12552 * entry if entry already exists in bss data base of cfg80211
12553 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12554 * to update thebss entry instead of cfg80211_inform_bss,
12555 * But this call expects mgmt packet as input. As of now
12556 * there is no possibility to get the mgmt(probe response)
12557 * frame from PE, converting bss_desc to
12558 * ieee80211_mgmt(probe response) and passing to c
12559 * fg80211_inform_bss_frame.
12560 * - Update BSS only if beacon timestamp is later than
12561 * scan request timestamp.
12562 */
12563 if ((scan_time == 0) ||
12564 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012565 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012566 bss_status =
12567 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12568 &pScanResult->BssDescriptor);
12569
12570 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012571 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 } else {
12573 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 bss_status);
12576 }
12577 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012578 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12580 }
12581 pScanResult = sme_scan_result_get_next(hHal, pResult);
12582 }
12583
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012584 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012585 /*
12586 * For SAP mode, scan is invoked by hostapd during SAP start
12587 * if hostapd is restarted, we need to flush previous scan
12588 * result so that it will reflect environment change
12589 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012590 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012591#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12592 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12593#endif
12594 )
12595 sme_scan_flush_result(hHal);
12596
12597 EXIT();
12598 return 0;
12599}
12600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012601/**
12602 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12603 * @pAdapter: Pointer to adapter
12604 * @pRoamInfo: Pointer to roam info
12605 * @index: Index
12606 * @preauth: Preauth flag
12607 *
12608 * This function is used to notify the supplicant of a new PMKSA candidate.
12609 *
12610 * Return: 0 for success, non-zero for failure
12611 */
12612int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12613 tCsrRoamInfo *pRoamInfo,
12614 int index, bool preauth)
12615{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012616 struct net_device *dev = pAdapter->dev;
12617 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12618
12619 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012620 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012621
12622 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012623 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 return -EINVAL;
12625 }
12626
12627 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012628 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012629 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12630 cfg80211_pmksa_candidate_notify(dev, index,
12631 pRoamInfo->bssid.bytes,
12632 preauth, GFP_KERNEL);
12633 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012634 return 0;
12635}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012636
12637#ifdef FEATURE_WLAN_LFR_METRICS
12638/**
12639 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12640 * @pAdapter: Pointer to adapter
12641 * @pRoamInfo: Pointer to roam info
12642 *
12643 * 802.11r/LFR metrics reporting function to report preauth initiation
12644 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012645 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012646 */
12647#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012648QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012649 tCsrRoamInfo *pRoamInfo)
12650{
12651 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12652 union iwreq_data wrqu;
12653
12654 ENTER();
12655
12656 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012657 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012658 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659 }
12660
12661 /* create the event */
12662 memset(&wrqu, 0, sizeof(wrqu));
12663 memset(metrics_notification, 0, sizeof(metrics_notification));
12664
12665 wrqu.data.pointer = metrics_notification;
12666 wrqu.data.length = scnprintf(metrics_notification,
12667 sizeof(metrics_notification),
12668 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12669 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12670
12671 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12672 metrics_notification);
12673
12674 EXIT();
12675
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012676 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012677}
12678
12679/**
12680 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12681 * @pAdapter: Pointer to adapter
12682 * @pRoamInfo: Pointer to roam info
12683 * @preauth_status: Preauth status
12684 *
12685 * 802.11r/LFR metrics reporting function to report handover initiation
12686 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012687 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012688 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012689QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012690wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12691 tCsrRoamInfo *pRoamInfo,
12692 bool preauth_status)
12693{
12694 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12695 union iwreq_data wrqu;
12696
12697 ENTER();
12698
12699 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012700 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012701 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012702 }
12703
12704 /* create the event */
12705 memset(&wrqu, 0, sizeof(wrqu));
12706 memset(metrics_notification, 0, sizeof(metrics_notification));
12707
12708 scnprintf(metrics_notification, sizeof(metrics_notification),
12709 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12710 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12711
12712 if (1 == preauth_status)
12713 strlcat(metrics_notification, " true",
12714 sizeof(metrics_notification));
12715 else
12716 strlcat(metrics_notification, " false",
12717 sizeof(metrics_notification));
12718
12719 wrqu.data.pointer = metrics_notification;
12720 wrqu.data.length = strlen(metrics_notification);
12721
12722 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12723 metrics_notification);
12724
12725 EXIT();
12726
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012727 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728}
12729
12730/**
12731 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12732 * @pAdapter: Pointer to adapter
12733 * @pRoamInfo: Pointer to roam info
12734 *
12735 * 802.11r/LFR metrics reporting function to report handover initiation
12736 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012737 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012738 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012739QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740 tCsrRoamInfo *pRoamInfo)
12741{
12742 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12743 union iwreq_data wrqu;
12744
12745 ENTER();
12746
12747 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012748 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012749 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012750 }
12751
12752 /* create the event */
12753 memset(&wrqu, 0, sizeof(wrqu));
12754 memset(metrics_notification, 0, sizeof(metrics_notification));
12755
12756 wrqu.data.pointer = metrics_notification;
12757 wrqu.data.length = scnprintf(metrics_notification,
12758 sizeof(metrics_notification),
12759 "QCOM: LFR_PREAUTH_HANDOVER "
12760 MAC_ADDRESS_STR,
12761 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12762
12763 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12764 metrics_notification);
12765
12766 EXIT();
12767
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012768 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769}
12770#endif
12771
12772/**
12773 * hdd_select_cbmode() - select channel bonding mode
12774 * @pAdapter: Pointer to adapter
12775 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012776 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777 *
12778 * Return: none
12779 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012780void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012781 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012783 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012784 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012785 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012786 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012787
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012788 /*
12789 * CDS api expects secondary channel for calculating
12790 * the channel params
12791 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012792 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012793 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012794 if (operationChannel >= 1 && operationChannel <= 5)
12795 sec_ch = operationChannel + 4;
12796 else if (operationChannel >= 6 && operationChannel <= 13)
12797 sec_ch = operationChannel - 4;
12798 }
12799
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012800 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012801 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
12802 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012803
12804 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012805 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012806 uint8_t iniDot11Mode =
12807 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12808
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012809 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012810 switch (iniDot11Mode) {
12811 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012812 case eHDD_DOT11_MODE_11ax:
12813 case eHDD_DOT11_MODE_11ax_ONLY:
12814 if (sme_is_feature_supported_by_fw(DOT11AX))
12815 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12816 else if (sme_is_feature_supported_by_fw(DOT11AC))
12817 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12818 else
12819 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12820 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012821 case eHDD_DOT11_MODE_11ac:
12822 case eHDD_DOT11_MODE_11ac_ONLY:
12823 if (sme_is_feature_supported_by_fw(DOT11AC))
12824 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12825 else
12826 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12827 break;
12828 case eHDD_DOT11_MODE_11n:
12829 case eHDD_DOT11_MODE_11n_ONLY:
12830 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12831 break;
12832 default:
12833 hdd_dot11_mode = iniDot11Mode;
12834 break;
12835 }
12836 ch_info->channel_width = ch_params->ch_width;
12837 ch_info->phy_mode =
12838 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012839 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012840 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012841 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012842 ch_info->channel_width, ch_info->phy_mode,
12843 ch_info->channel);
12844 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012845}
12846
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012847/**
12848 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12849 * @adapter: STA adapter
12850 * @roam_profile: STA roam profile
12851 *
12852 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12853 *
12854 * Return: false if sta-sap conc is not allowed, else return true
12855 */
12856static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12857 tCsrRoamProfile *roam_profile)
12858{
12859 hdd_context_t *hdd_ctx;
12860 hdd_adapter_t *ap_adapter;
12861 hdd_ap_ctx_t *hdd_ap_ctx;
12862 hdd_hostapd_state_t *hostapd_state;
12863 uint8_t channel = 0;
12864 QDF_STATUS status;
12865
12866 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12867 if (!hdd_ctx) {
12868 hdd_err("HDD context is NULL");
12869 return true;
12870 }
12871
12872 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12873 /* probably no sap running, no handling required */
12874 if (ap_adapter == NULL)
12875 return true;
12876
12877 /*
12878 * sap is not in started state, so it is fine to go ahead with sta.
12879 * if sap is currently doing CAC then don't allow sta to go further.
12880 */
12881 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12882 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12883 return true;
12884
12885 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12886 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12887 return false;
12888 }
12889
12890 /*
12891 * log and return error, if we allow STA to go through, we don't
12892 * know what is going to happen better stop sta connection
12893 */
12894 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12895 if (NULL == hdd_ap_ctx) {
12896 hdd_err("AP context not found");
12897 return false;
12898 }
12899
12900 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012901 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
12902 hdd_ap_ctx->operatingChannel)) {
12903 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012904 return true;
12905 }
12906 /*
12907 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012908 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012909 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012910 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012911 roam_profile, &channel);
12912
Nitesh Shah59774522016-09-16 15:14:21 +053012913 /*
12914 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12915 * channels for roaming case.
12916 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012917 if (WLAN_REG_IS_24GHZ_CH(channel)) {
12918 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012919 return true;
12920 }
12921
12922 /*
12923 * If channel is 0 or DFS then better to call pcl and find out the
12924 * best channel. If channel is non-dfs 5 GHz then better move SAP
12925 * to STA's channel to make scc, so we have room for 3port MCC
12926 * scenario.
12927 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012928 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012929 channel = policy_mgr_get_nondfs_preferred_channel(
12930 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012931
12932 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12933 qdf_event_reset(&hostapd_state->qdf_event);
12934 status = wlansap_set_channel_change_with_csa(
12935 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12936 hdd_ap_ctx->sapConfig.ch_width_orig);
12937
12938 if (QDF_STATUS_SUCCESS != status) {
12939 hdd_err("Set channel with CSA IE failed, can't allow STA");
12940 return false;
12941 }
12942
12943 /*
12944 * wait here for SAP to finish the channel switch. When channel
12945 * switch happens, SAP sends few beacons with CSA_IE. After
12946 * successfully Transmission of those beacons, it will move its
12947 * state from started to disconnected and move to new channel.
12948 * once it moves to new channel, sap again moves its state
12949 * machine from disconnected to started and set this event.
12950 * wait for 10 secs to finish this.
12951 */
12952 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12953 if (!QDF_IS_STATUS_SUCCESS(status)) {
12954 hdd_err("wait for qdf_event failed, STA not allowed!!");
12955 return false;
12956 }
12957
12958 return true;
12959}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012960
Abhishek Singhcfb44482017-03-10 12:42:37 +053012961#ifdef WLAN_FEATURE_11W
12962/**
12963 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12964 * @roam_profile: pointer to roam profile
12965 *
12966 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12967 * or pmf=2 is an explicit configuration in the supplicant
12968 * configuration, drop the connection request.
12969 *
12970 * Return: 0 if check result is valid, otherwise return error code
12971 */
12972static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12973{
12974 if (roam_profile->MFPEnabled &&
12975 !(roam_profile->MFPRequired ||
12976 roam_profile->MFPCapable)) {
12977 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12978 roam_profile->MFPEnabled,
12979 roam_profile->MFPRequired,
12980 roam_profile->MFPCapable);
12981 return -EINVAL;
12982 }
12983 return 0;
12984}
12985#else
12986static inline
12987int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12988{
12989 return 0;
12990}
12991#endif
12992
Krunal Soni31949422016-07-29 17:17:53 -070012993/**
12994 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012996 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997 * @ssid_len: Length of ssid
12998 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012999 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013000 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013001 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013002 *
13003 * This function is used to start the association process
13004 *
13005 * Return: 0 for success, non-zero for failure
13006 */
Krunal Soni31949422016-07-29 17:17:53 -070013007static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013009 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013010 u8 operatingChannel,
13011 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013012{
13013 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013014 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015 hdd_wext_state_t *pWextState;
13016 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013017 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013018 uint32_t roamId;
13019 tCsrRoamProfile *pRoamProfile;
13020 eCsrAuthType RSNAuthType;
13021 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013022 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023
13024 ENTER();
13025
13026 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13027 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013028 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029
13030 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013031 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013032 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013033
13034 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013035 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013036 status = -EINVAL;
13037 goto ret_status;
13038 }
13039
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013040 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013041 hdd_err("Connection refused: conn in progress");
13042 status = -EINVAL;
13043 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013044 }
13045
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013046 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013047 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013049 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013050 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13051 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052
13053 if (pRoamProfile) {
13054 hdd_station_ctx_t *pHddStaCtx;
13055 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13056
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013057 /* Restart the opportunistic timer
13058 *
13059 * If hw_mode_change_in_progress is true, then wait
13060 * till firmware sends the callback for hw_mode change.
13061 *
13062 * Else set connect_in_progress as true and proceed.
13063 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013064 policy_mgr_restart_opportunistic_timer(
13065 pHddCtx->hdd_psoc, false);
13066 if (policy_mgr_is_hw_mode_change_in_progress(
13067 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013068 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013069 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013070 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013071 hdd_err("qdf wait for event failed!!");
13072 status = -EINVAL;
13073 goto ret_status;
13074 }
13075 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013076 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013078 if (HDD_WMM_USER_MODE_NO_QOS ==
13079 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13080 /*QoS not enabled in cfg file */
13081 pRoamProfile->uapsd_mask = 0;
13082 } else {
13083 /*QoS enabled, update uapsd mask from cfg file */
13084 pRoamProfile->uapsd_mask =
13085 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13086 }
13087
13088 pRoamProfile->SSIDs.numOfSSIDs = 1;
13089 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013090 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013091 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013092 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013093 ssid, ssid_len);
13094
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013095 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013096 /* cleanup bssid hint */
13097 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13098 QDF_MAC_ADDR_SIZE);
13099 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13100 QDF_MAC_ADDR_SIZE);
13101
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 if (bssid) {
13103 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013104 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013105 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013106 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013107 /*
13108 * Save BSSID in seperate variable as
13109 * pRoamProfile's BSSID is getting zeroed out in the
13110 * association process. In case of join failure
13111 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013113 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013114 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013115 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013116 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013117 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13118 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013119 /*
13120 * Save BSSID in a separate variable as
13121 * pRoamProfile's BSSID is getting zeroed out in the
13122 * association process. In case of join failure
13123 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013125 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013126 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013127 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013128 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013129 }
13130
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013131 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013132 pRoamProfile->SSIDs.SSIDList->SSID.length,
13133 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13134 operatingChannel);
13135
13136 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13137 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013139 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13140 }
13141#ifdef FEATURE_WLAN_WAPI
13142 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013143 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 switch (pAdapter->wapi_info.wapiAuthMode) {
13145 case WAPI_AUTH_MODE_PSK:
13146 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013147 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 pAdapter->wapi_info.wapiAuthMode);
13149 pRoamProfile->AuthType.authType[0] =
13150 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13151 break;
13152 }
13153 case WAPI_AUTH_MODE_CERT:
13154 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013155 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013156 pAdapter->wapi_info.wapiAuthMode);
13157 pRoamProfile->AuthType.authType[0] =
13158 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13159 break;
13160 }
13161 } /* End of switch */
13162 if (pAdapter->wapi_info.wapiAuthMode ==
13163 WAPI_AUTH_MODE_PSK
13164 || pAdapter->wapi_info.wapiAuthMode ==
13165 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013166 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013167 pRoamProfile->AuthType.numEntries = 1;
13168 pRoamProfile->EncryptionType.numEntries = 1;
13169 pRoamProfile->EncryptionType.encryptionType[0] =
13170 eCSR_ENCRYPT_TYPE_WPI;
13171 pRoamProfile->mcEncryptionType.numEntries = 1;
13172 pRoamProfile->mcEncryptionType.
13173 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13174 }
13175 }
Krunal Soni31949422016-07-29 17:17:53 -070013176#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013177 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013178 pRoamProfile->csrPersona = pAdapter->device_mode;
13179
13180 if (operatingChannel) {
13181 pRoamProfile->ChannelInfo.ChannelList =
13182 &operatingChannel;
13183 pRoamProfile->ChannelInfo.numOfChannels = 1;
13184 } else {
13185 pRoamProfile->ChannelInfo.ChannelList = NULL;
13186 pRoamProfile->ChannelInfo.numOfChannels = 0;
13187 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013188 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189 && operatingChannel) {
13190 /*
13191 * Need to post the IBSS power save parameters
13192 * to WMA. WMA will configure this parameters
13193 * to firmware if power save is enabled by the
13194 * firmware.
13195 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013196 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013197
Abhishek Singh471652b2017-04-14 12:28:32 +053013198 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013199 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013200 status = -EINVAL;
13201 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013202 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013203 pRoamProfile->ch_params.ch_width =
13204 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013205 /*
13206 * In IBSS mode while operating in 2.4 GHz,
13207 * the device supports only 20 MHz.
13208 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013209 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013210 pRoamProfile->ch_params.ch_width =
13211 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013212 hdd_select_cbmode(pAdapter, operatingChannel,
13213 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013214 }
13215
Abhishek Singhcfb44482017-03-10 12:42:37 +053013216 if (wlan_hdd_cfg80211_check_pmf_valid(
13217 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013218 status = -EINVAL;
13219 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013220 }
13221
Krunal Soni31949422016-07-29 17:17:53 -070013222 /*
13223 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013224 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013225 * enhancements, the supplicant is not issuing the scan command
13226 * now. So the unicast frames which are sent from the host are
13227 * not having the additional IEs. If it is P2P CLIENT and there
13228 * is no additional IE present in roamProfile, then use the
13229 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230 */
13231
Krunal Sonib4326f22016-03-10 13:05:51 -080013232 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 (!pRoamProfile->pAddIEScan)) {
13234 pRoamProfile->pAddIEScan =
13235 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13236 pRoamProfile->nAddIEScanLength =
13237 pAdapter->scan_info.scanAddIE.length;
13238 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013239
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013240 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13241 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013242 pRoamProfile))) {
13243 hdd_err("sap-sta conc will fail, can't allow sta");
13244 hdd_conn_set_connection_state(pAdapter,
13245 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013246 status = -ENOMEM;
13247 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013248 }
13249
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013250 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013251 if (!sme_config) {
13252 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013253 hdd_conn_set_connection_state(pAdapter,
13254 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013255 status = -ENOMEM;
13256 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013257 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 sme_get_config_param(pHddCtx->hHal, sme_config);
13259 /* These values are not sessionized. So, any change in these SME
13260 * configs on an older or parallel interface will affect the
13261 * cb mode. So, restoring the default INI params before starting
13262 * interfaces such as sta, cli etc.,
13263 */
13264 sme_config->csrConfig.channelBondingMode5GHz =
13265 pHddCtx->config->nChannelBondingMode5GHz;
13266 sme_config->csrConfig.channelBondingMode24GHz =
13267 pHddCtx->config->nChannelBondingMode24GHz;
13268 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013269 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013270 /*
13271 * Change conn_state to connecting before sme_roam_connect(),
13272 * because sme_roam_connect() has a direct path to call
13273 * hdd_sme_roam_callback(), which will change the conn_state
13274 * If direct path, conn_state will be accordingly changed to
13275 * NotConnected or Associated by either
13276 * hdd_association_completion_handler() or
13277 * hdd_dis_connect_handler() in sme_RoamCallback()if
13278 * sme_RomConnect is to be queued,
13279 * Connecting state will remain until it is completed.
13280 *
13281 * If connection state is not changed, connection state will
13282 * remain in eConnectionState_NotConnected state.
13283 * In hdd_association_completion_handler, "hddDisconInProgress"
13284 * is set to true if conn state is
13285 * eConnectionState_NotConnected.
13286 * If "hddDisconInProgress" is set to true then cfg80211 layer
13287 * is not informed of connect result indication which
13288 * is an issue.
13289 */
13290 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013291 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013292 hdd_conn_set_connection_state(pAdapter,
13293 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294
Komal Seelama89be8d2016-09-29 11:09:26 +053013295 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13296 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013297 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013298 pAdapter->sessionId, pRoamProfile,
13299 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013300 if (QDF_IS_STATUS_ERROR(qdf_status))
13301 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013302
Rajeev Kumard31e1542017-01-13 14:37:42 -080013303 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013304 (QDF_STA_MODE == pAdapter->device_mode ||
13305 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013306 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013307 "qdf_status %d. -> NotConnected",
13308 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013309 /* change back to NotAssociated */
13310 hdd_conn_set_connection_state(pAdapter,
13311 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013312 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13313 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 }
13315
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013316 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013317 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013319 pRoamProfile->ChannelInfo.ChannelList = NULL;
13320 pRoamProfile->ChannelInfo.numOfChannels = 0;
13321
Nitesh Shah044fd672016-10-13 18:53:25 +053013322 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013323 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13324 && !policy_mgr_is_hw_dbs_2x2_capable(
13325 pHddCtx->hdd_psoc)) {
13326 policy_mgr_get_channel_from_scan_result(
13327 pHddCtx->hdd_psoc,
13328 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013329 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013330 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013331 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13332 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013333 }
13334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013336 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013337 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013339 goto ret_status;
13340
13341conn_failure:
13342 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013343 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013344
13345ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 EXIT();
13347 return status;
13348}
13349
13350/**
13351 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13352 * @pAdapter: Pointer to adapter
13353 * @auth_type: Auth type
13354 *
13355 * This function is used to set the authentication type (OPEN/SHARED).
13356 *
13357 * Return: 0 for success, non-zero for failure
13358 */
13359static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13360 enum nl80211_auth_type auth_type)
13361{
13362 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13363 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 /*set authentication type */
13366 switch (auth_type) {
13367 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013368 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013369 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13370 break;
13371
13372 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013373 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013374 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013375 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13376 break;
13377
13378 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013379 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013380 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13381 break;
13382#ifdef FEATURE_WLAN_ESE
13383 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013384 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013385 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13386 break;
13387#endif
13388
13389 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013390 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13392 return -EINVAL;
13393 }
13394
13395 pWextState->roamProfile.AuthType.authType[0] =
13396 pHddStaCtx->conn_info.authType;
13397 return 0;
13398}
13399
13400/**
13401 * wlan_hdd_set_akm_suite() - set key management type
13402 * @pAdapter: Pointer to adapter
13403 * @key_mgmt: Key management type
13404 *
13405 * This function is used to set the key mgmt type(PSK/8021x).
13406 *
13407 * Return: 0 for success, non-zero for failure
13408 */
13409static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13410{
13411 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13412
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013413#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013415#endif
13416#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013418#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013419 /*set key mgmt type */
13420 switch (key_mgmt) {
13421 case WLAN_AKM_SUITE_PSK:
13422 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013424 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13426 break;
13427
13428 case WLAN_AKM_SUITE_8021X_SHA256:
13429 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013430 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013431 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13433 break;
13434#ifdef FEATURE_WLAN_ESE
13435#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13436#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13437 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013438 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013439 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13440 break;
13441#endif
13442#ifndef WLAN_AKM_SUITE_OSEN
13443#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13444#endif
13445 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013446 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013447 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13448 break;
13449
13450 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013451 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013452 return -EINVAL;
13453
13454 }
13455 return 0;
13456}
13457
13458/**
13459 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13460 * @pAdapter: Pointer to adapter
13461 * @cipher: Cipher type
13462 * @ucast: Unicast flag
13463 *
13464 * This function is used to set the encryption type
13465 * (NONE/WEP40/WEP104/TKIP/CCMP).
13466 *
13467 * Return: 0 for success, non-zero for failure
13468 */
13469static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13470 u32 cipher, bool ucast)
13471{
13472 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13473 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13474 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13475
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013476 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013477 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013478 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13479 } else {
13480
13481 /*set encryption method */
13482 switch (cipher) {
13483 case IW_AUTH_CIPHER_NONE:
13484 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13485 break;
13486
13487 case WLAN_CIPHER_SUITE_WEP40:
13488 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13489 break;
13490
13491 case WLAN_CIPHER_SUITE_WEP104:
13492 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13493 break;
13494
13495 case WLAN_CIPHER_SUITE_TKIP:
13496 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13497 break;
13498
13499 case WLAN_CIPHER_SUITE_CCMP:
13500 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13501 break;
13502#ifdef FEATURE_WLAN_WAPI
13503 case WLAN_CIPHER_SUITE_SMS4:
13504 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13505 break;
13506#endif
13507
13508#ifdef FEATURE_WLAN_ESE
13509 case WLAN_CIPHER_SUITE_KRK:
13510 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13511 break;
13512#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13513 case WLAN_CIPHER_SUITE_BTK:
13514 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13515 break;
13516#endif
13517#endif
13518 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013519 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520 return -EOPNOTSUPP;
13521 }
13522 }
13523
13524 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013525 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13527 pWextState->roamProfile.EncryptionType.numEntries = 1;
13528 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13529 encryptionType;
13530 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013531 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013532 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13533 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13534 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13535 encryptionType;
13536 }
13537
13538 return 0;
13539}
13540
13541/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013542 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13543 * @wext_state: Pointer to wext state
13544 * @gen_ie: Pointer to IE data
13545 * @len: length of IE data
13546 *
13547 * Return: 0 for success, non-zero for failure
13548 */
13549static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13550 const uint8_t *gen_ie, uint16_t len)
13551{
13552 uint16_t cur_add_ie_len =
13553 wext_state->assocAddIE.length;
13554
13555 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13556 (wext_state->assocAddIE.length + len)) {
13557 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13558 QDF_ASSERT(0);
13559 return -ENOMEM;
13560 }
13561 memcpy(wext_state->assocAddIE.addIEdata +
13562 cur_add_ie_len, gen_ie, len);
13563 wext_state->assocAddIE.length += len;
13564
13565 wext_state->roamProfile.pAddIEAssoc =
13566 wext_state->assocAddIE.addIEdata;
13567 wext_state->roamProfile.nAddIEAssocLength =
13568 wext_state->assocAddIE.length;
13569 return 0;
13570}
13571
13572/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573 * wlan_hdd_cfg80211_set_ie() - set IEs
13574 * @pAdapter: Pointer to adapter
13575 * @ie: Pointer ot ie
13576 * @ie: IE length
13577 *
13578 * Return: 0 for success, non-zero for failure
13579 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013580static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013581 size_t ie_len)
13582{
13583 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13584 const uint8_t *genie = ie;
13585 uint16_t remLen = ie_len;
13586#ifdef FEATURE_WLAN_WAPI
13587 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13588 u16 *tmp;
13589 uint16_t akmsuiteCount;
13590 int *akmlist;
13591#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013592 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013593
13594 /* clear previous assocAddIE */
13595 pWextState->assocAddIE.length = 0;
13596 pWextState->roamProfile.bWPSAssociation = false;
13597 pWextState->roamProfile.bOSENAssociation = false;
13598
13599 while (remLen >= 2) {
13600 uint16_t eLen = 0;
13601 uint8_t elementId;
13602 elementId = *genie++;
13603 eLen = *genie++;
13604 remLen -= 2;
13605
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013606 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607
13608 switch (elementId) {
13609 case DOT11F_EID_WPA:
13610 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 -070013611 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612 return -EINVAL;
13613 } else if (0 ==
13614 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13615 uint16_t curAddIELen =
13616 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013617 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618
13619 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13620 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013621 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013622 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 return -ENOMEM;
13624 }
13625 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13626 memcpy(pWextState->assocAddIE.addIEdata +
13627 curAddIELen, genie - 2, eLen + 2);
13628 pWextState->assocAddIE.length += eLen + 2;
13629
13630 pWextState->roamProfile.bWPSAssociation = true;
13631 pWextState->roamProfile.pAddIEAssoc =
13632 pWextState->assocAddIE.addIEdata;
13633 pWextState->roamProfile.nAddIEAssocLength =
13634 pWextState->assocAddIE.length;
13635 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013636 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637 memset(pWextState->WPARSNIE, 0,
13638 MAX_WPA_RSN_IE_LEN);
13639 memcpy(pWextState->WPARSNIE, genie - 2,
13640 (eLen + 2));
13641 pWextState->roamProfile.pWPAReqIE =
13642 pWextState->WPARSNIE;
13643 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13644 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13645 P2P_OUI_TYPE_SIZE))) {
13646 uint16_t curAddIELen =
13647 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013648 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649
13650 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13651 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013652 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013653 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654 return -ENOMEM;
13655 }
13656 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13657 memcpy(pWextState->assocAddIE.addIEdata +
13658 curAddIELen, genie - 2, eLen + 2);
13659 pWextState->assocAddIE.length += eLen + 2;
13660
13661 pWextState->roamProfile.pAddIEAssoc =
13662 pWextState->assocAddIE.addIEdata;
13663 pWextState->roamProfile.nAddIEAssocLength =
13664 pWextState->assocAddIE.length;
13665 }
13666#ifdef WLAN_FEATURE_WFD
13667 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13668 WFD_OUI_TYPE_SIZE)) &&
13669 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013670 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 pAdapter->device_mode)) {
13672 uint16_t curAddIELen =
13673 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013674 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013675
13676 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13677 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013678 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013679 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013680 return -ENOMEM;
13681 }
13682 /* WFD IE is saved to Additional IE ; it should
13683 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013684 * WFD IE
13685 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013686 memcpy(pWextState->assocAddIE.addIEdata +
13687 curAddIELen, genie - 2, eLen + 2);
13688 pWextState->assocAddIE.length += eLen + 2;
13689
13690 pWextState->roamProfile.pAddIEAssoc =
13691 pWextState->assocAddIE.addIEdata;
13692 pWextState->roamProfile.nAddIEAssocLength =
13693 pWextState->assocAddIE.length;
13694 }
13695#endif
13696 /* Appending HS 2.0 Indication Element in Assiciation Request */
13697 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13698 HS20_OUI_TYPE_SIZE))) {
13699 uint16_t curAddIELen =
13700 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013701 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702
13703 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13704 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013705 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013706 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013707 return -ENOMEM;
13708 }
13709 memcpy(pWextState->assocAddIE.addIEdata +
13710 curAddIELen, genie - 2, eLen + 2);
13711 pWextState->assocAddIE.length += eLen + 2;
13712
13713 pWextState->roamProfile.pAddIEAssoc =
13714 pWextState->assocAddIE.addIEdata;
13715 pWextState->roamProfile.nAddIEAssocLength =
13716 pWextState->assocAddIE.length;
13717 }
13718 /* Appending OSEN Information Element in Assiciation Request */
13719 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13720 OSEN_OUI_TYPE_SIZE))) {
13721 uint16_t curAddIELen =
13722 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013723 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013724
13725 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13726 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013727 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013728 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 return -ENOMEM;
13730 }
13731 memcpy(pWextState->assocAddIE.addIEdata +
13732 curAddIELen, genie - 2, eLen + 2);
13733 pWextState->assocAddIE.length += eLen + 2;
13734
13735 pWextState->roamProfile.bOSENAssociation = true;
13736 pWextState->roamProfile.pAddIEAssoc =
13737 pWextState->assocAddIE.addIEdata;
13738 pWextState->roamProfile.nAddIEAssocLength =
13739 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013740 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13741 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013742 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013743 status = wlan_hdd_add_assoc_ie(pWextState,
13744 genie - 2, eLen + 2);
13745 if (status)
13746 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013747 } else {
13748 uint16_t add_ie_len =
13749 pWextState->assocAddIE.length;
13750
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013751 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013752
13753 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13754 (pWextState->assocAddIE.length + eLen)) {
13755 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013756 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013757 return -ENOMEM;
13758 }
13759
13760 memcpy(pWextState->assocAddIE.addIEdata +
13761 add_ie_len, genie - 2, eLen + 2);
13762 pWextState->assocAddIE.length += eLen + 2;
13763
13764 pWextState->roamProfile.pAddIEAssoc =
13765 pWextState->assocAddIE.addIEdata;
13766 pWextState->roamProfile.nAddIEAssocLength =
13767 pWextState->assocAddIE.length;
13768 }
13769 break;
13770 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013771 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13773 memcpy(pWextState->WPARSNIE, genie - 2,
13774 (eLen + 2));
13775 pWextState->roamProfile.pRSNReqIE =
13776 pWextState->WPARSNIE;
13777 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13778 break;
13779 /*
13780 * Appending Extended Capabilities with Interworking bit set
13781 * in Assoc Req.
13782 *
13783 * In assoc req this EXT Cap will only be taken into account if
13784 * interworkingService bit is set to 1. Currently
13785 * driver is only interested in interworkingService capability
13786 * from supplicant. If in future any other EXT Cap info is
13787 * required from supplicat, it needs to be handled while
13788 * sending Assoc Req in LIM.
13789 */
13790 case DOT11F_EID_EXTCAP:
13791 {
13792 uint16_t curAddIELen =
13793 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013794 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013795
13796 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13797 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013798 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013799 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013800 return -ENOMEM;
13801 }
13802 memcpy(pWextState->assocAddIE.addIEdata +
13803 curAddIELen, genie - 2, eLen + 2);
13804 pWextState->assocAddIE.length += eLen + 2;
13805
13806 pWextState->roamProfile.pAddIEAssoc =
13807 pWextState->assocAddIE.addIEdata;
13808 pWextState->roamProfile.nAddIEAssocLength =
13809 pWextState->assocAddIE.length;
13810 break;
13811 }
13812#ifdef FEATURE_WLAN_WAPI
13813 case WLAN_EID_WAPI:
13814 /* Setting WAPI Mode to ON=1 */
13815 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013816 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817 tmp = (u16 *) ie;
13818 tmp = tmp + 2; /* Skip element Id and Len, Version */
13819 akmsuiteCount = WPA_GET_LE16(tmp);
13820 tmp = tmp + 1;
13821 akmlist = (int *)(tmp);
13822 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13823 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13824 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013825 hdd_err("Invalid akmSuite count: %u",
13826 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013827 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013828 return -EINVAL;
13829 }
13830
13831 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013832 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 pAdapter->wapi_info.wapiAuthMode =
13834 WAPI_AUTH_MODE_PSK;
13835 }
13836 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013837 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013838 pAdapter->wapi_info.wapiAuthMode =
13839 WAPI_AUTH_MODE_CERT;
13840 }
13841 break;
13842#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013843 case DOT11F_EID_SUPPOPERATINGCLASSES:
13844 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013845 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013846 status = wlan_hdd_add_assoc_ie(pWextState,
13847 genie - 2, eLen + 2);
13848 if (status)
13849 return status;
13850 break;
13851 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013852 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013853 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013854 /* when Unknown IE is received we break
13855 * and continue to the next IE in the buffer
13856 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013857 break;
13858 }
13859 genie += eLen;
13860 remLen -= eLen;
13861 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013862 return 0;
13863}
13864
13865/**
13866 * hdd_is_wpaie_present() - check for WPA ie
13867 * @ie: Pointer to ie
13868 * @ie_len: Ie length
13869 *
13870 * Parse the received IE to find the WPA IE
13871 *
13872 * Return: true if wpa ie is found else false
13873 */
13874static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13875{
13876 uint8_t eLen = 0;
13877 uint16_t remLen = ie_len;
13878 uint8_t elementId = 0;
13879
13880 while (remLen >= 2) {
13881 elementId = *ie++;
13882 eLen = *ie++;
13883 remLen -= 2;
13884 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013885 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013886 return false;
13887 }
13888 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13889 /* OUI - 0x00 0X50 0XF2
13890 * WPA Information Element - 0x01
13891 * WPA version - 0x01
13892 */
13893 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13894 return true;
13895 }
13896 ie += eLen;
13897 remLen -= eLen;
13898 }
13899 return false;
13900}
13901
13902/**
13903 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13904 * @pAdapter: Pointer to adapter
13905 * @req: Pointer to security parameters
13906 *
13907 * Return: 0 for success, non-zero for failure
13908 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013909static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13910 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911{
13912 int status = 0;
13913 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13914 ENTER();
13915
13916 /*set wpa version */
13917 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13918
13919 if (req->crypto.wpa_versions) {
13920 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13921 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13922 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13923 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13924 }
13925 }
13926
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013927 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928
13929 /*set authentication type */
13930 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13931
13932 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013933 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013934 return status;
13935 }
13936
13937 /*set key mgmt type */
13938 if (req->crypto.n_akm_suites) {
13939 status =
13940 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13941 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013942 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013943 return status;
13944 }
13945 }
13946
13947 /*set pairwise cipher type */
13948 if (req->crypto.n_ciphers_pairwise) {
13949 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13950 req->crypto.
13951 ciphers_pairwise[0],
13952 true);
13953 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013954 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013955 return status;
13956 }
13957 } else {
13958 /*Reset previous cipher suite to none */
13959 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13960 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013961 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013962 return status;
13963 }
13964 }
13965
13966 /*set group cipher type */
13967 status =
13968 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13969 false);
13970
13971 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013972 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013973 return status;
13974 }
13975#ifdef WLAN_FEATURE_11W
13976 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13977#endif
13978
13979 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13980 if (req->ie_len) {
13981 status =
13982 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13983 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013984 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 return status;
13986 }
13987 }
13988
13989 /*incase of WEP set default key information */
13990 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013991 u8 key_len = req->key_len;
13992 u8 key_idx = req->key_idx;
13993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13995 || (WLAN_CIPHER_SUITE_WEP104 ==
13996 req->crypto.ciphers_pairwise[0])
13997 ) {
13998 if (IW_AUTH_KEY_MGMT_802_1X
13999 ==
14000 (pWextState->
14001 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014002 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014005
Jeff Johnson68755312017-02-10 11:46:55 -080014006 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14007 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014008 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014009 key_idx, key_len);
14010 qdf_mem_copy(&pWextState->roamProfile.
14011 Keys.
14012 KeyMaterial[key_idx][0],
14013 req->key, key_len);
14014 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014015 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014016 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014017 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 }
14019 }
14020 }
14021
14022 return status;
14023}
14024
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014025int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026{
14027 unsigned long rc;
14028 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014029 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014030 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031
14032 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014033 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14034 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014035 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014036 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14037 }
14038 /*
14039 * If firmware has already started roaming process, driver
14040 * needs to defer the processing of this disconnect request.
14041 *
14042 */
14043 if (hdd_is_roaming_in_progress(pAdapter)) {
14044 /*
14045 * Defer the disconnect action until firmware roaming
14046 * result is received. If STA is in connected state after
14047 * that, send the disconnect command to CSR, otherwise
14048 * CSR would have already sent disconnect event to upper
14049 * layer.
14050 */
14051
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014052 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014053 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14054 pAdapter->cfg80211_disconnect_reason =
14055 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14056 return 0;
14057 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014058
Jeff Johnson9edf9572016-10-03 15:24:49 -070014059 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014060 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14061 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14062 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014063 hdd_conn_set_connection_state(pAdapter,
14064 eConnectionState_Disconnecting);
14065 /* Issue disconnect to CSR */
14066 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014067
14068 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14069 pAdapter->sessionId,
14070 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14071 /*
14072 * Wait here instead of returning directly, this will block the
14073 * next connect command and allow processing of the scan for
14074 * ssid and the previous connect command in CSR. Else we might
14075 * hit some race conditions leading to SME and HDD out of sync.
14076 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014077 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014078 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014079 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014080 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014081 (int)status);
14082 pHddStaCtx->staDebugState = status;
14083 result = -EINVAL;
14084 goto disconnected;
14085 }
14086
14087 rc = wait_for_completion_timeout(
14088 &pAdapter->disconnect_comp_var,
14089 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014090 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014091 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014092 pAdapter->sessionId, pHddStaCtx->staDebugState);
14093 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014094 }
14095 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014096 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014097 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014098 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014100 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014101 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014102 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014103 }
14104 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014105disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014106 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14107 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108}
14109
14110/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014111 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14112 * @adapter: Pointer to the HDD adapter
14113 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014114 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014115 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014116 * This function will start reassociation if prev_bssid is set and bssid/
14117 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014118 *
Naveen Rawat07332902016-07-27 09:13:17 -070014119 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014120 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014121#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14122 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014123static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14124 struct cfg80211_connect_params *req,
14125 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014126{
Naveen Rawat07332902016-07-27 09:13:17 -070014127 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014128 const uint8_t *bssid = NULL;
14129 uint16_t channel = 0;
14130
14131 if (req->bssid)
14132 bssid = req->bssid;
14133 else if (req->bssid_hint)
14134 bssid = req->bssid_hint;
14135
14136 if (req->channel)
14137 channel = req->channel->hw_value;
14138 else if (req->channel_hint)
14139 channel = req->channel_hint->hw_value;
14140
14141 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014142 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014143 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014144 channel, MAC_ADDR_ARRAY(bssid));
14145 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014146 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014147 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014148 }
Naveen Rawat07332902016-07-27 09:13:17 -070014149 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014150}
14151#else
Naveen Rawat07332902016-07-27 09:13:17 -070014152static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14153 struct cfg80211_connect_params *req,
14154 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014155{
Naveen Rawat07332902016-07-27 09:13:17 -070014156 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014157}
14158#endif
14159
14160/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14162 * @wiphy: Pointer to wiphy
14163 * @dev: Pointer to network device
14164 * @req: Pointer to cfg80211 connect request
14165 *
14166 * This function is used to start the association process
14167 *
14168 * Return: 0 for success, non-zero for failure
14169 */
14170static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14171 struct net_device *ndev,
14172 struct cfg80211_connect_params *req)
14173{
14174 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014175 u16 channel;
14176#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14177 const u8 *bssid_hint = req->bssid_hint;
14178#else
14179 const u8 *bssid_hint = NULL;
14180#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14182 hdd_context_t *pHddCtx;
14183
14184 ENTER();
14185
Anurag Chouhan6d760662016-02-20 16:05:43 +053014186 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014187 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014188 return -EINVAL;
14189 }
14190
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014191 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14192 hdd_err("invalid session id: %d", pAdapter->sessionId);
14193 return -EINVAL;
14194 }
14195
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014196 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 TRACE_CODE_HDD_CFG80211_CONNECT,
14198 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014199 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 hdd_device_mode_to_string(pAdapter->device_mode),
14201 pAdapter->device_mode);
14202
Krunal Sonib4326f22016-03-10 13:05:51 -080014203 if (pAdapter->device_mode != QDF_STA_MODE &&
14204 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014205 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014206 hdd_device_mode_to_string(pAdapter->device_mode),
14207 pAdapter->device_mode);
14208 return -EINVAL;
14209 }
14210
14211 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14212 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014213 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014214 return -EINVAL;
14215 }
14216
14217 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014218 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014219 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014220
Naveen Rawat07332902016-07-27 09:13:17 -070014221 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014222 return status;
14223
Agrawal Ashishf156e942016-08-04 14:54:47 +053014224 /* Try disconnecting if already in connected state */
14225 status = wlan_hdd_try_disconnect(pAdapter);
14226 if (0 > status) {
14227 hdd_err("Failed to disconnect the existing connection");
14228 return -EALREADY;
14229 }
14230
14231 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014233 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14234 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014235 pAdapter->device_mode),
14236 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014237 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238 return -ECONNREFUSED;
14239 }
14240 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014241 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14242 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014244 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014245 return -ECONNREFUSED;
14246 }
14247 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014248
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014249 /*initialise security parameters */
14250 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14251
14252 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014253 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014254 return status;
14255 }
14256
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014257 if (req->channel)
14258 channel = req->channel->hw_value;
14259 else
14260 channel = 0;
14261 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14262 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014263 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014265 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014266 return status;
14267 }
14268 EXIT();
14269 return status;
14270}
14271
14272/**
14273 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14274 * @wiphy: Pointer to wiphy
14275 * @dev: Pointer to network device
14276 * @req: Pointer to cfg80211 connect request
14277 *
14278 * Return: 0 for success, non-zero for failure
14279 */
14280static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14281 struct net_device *ndev,
14282 struct cfg80211_connect_params *req)
14283{
14284 int ret;
14285 cds_ssr_protect(__func__);
14286 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14287 cds_ssr_unprotect(__func__);
14288
14289 return ret;
14290}
14291
14292/**
14293 * wlan_hdd_disconnect() - hdd disconnect api
14294 * @pAdapter: Pointer to adapter
14295 * @reason: Disconnect reason code
14296 *
14297 * This function is used to issue a disconnect request to SME
14298 *
14299 * Return: 0 for success, non-zero for failure
14300 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014301static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014302{
14303 int status, result = 0;
14304 unsigned long rc;
14305 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14306 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014307 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014308 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014309
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014310 ENTER();
14311
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312 status = wlan_hdd_validate_context(pHddCtx);
14313
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014314 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014315 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014316 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014317 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014318 status = sme_stop_roaming(hal, pAdapter->sessionId,
14319 eCsrHddIssued);
14320 }
14321 /*
14322 * If firmware has already started roaming process, driver
14323 * needs to defer the processing of this disconnect request.
14324 */
14325 if (hdd_is_roaming_in_progress(pAdapter)) {
14326 /*
14327 * Defer the disconnect action until firmware roaming
14328 * result is received. If STA is in connected state after
14329 * that, send the disconnect command to CSR, otherwise
14330 * CSR would have already sent disconnect event to upper
14331 * layer.
14332 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014333 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014334 pAdapter->defer_disconnect =
14335 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14336 pAdapter->cfg80211_disconnect_reason = reason;
14337 return 0;
14338 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014340 prev_conn_state = pHddStaCtx->conn_info.connState;
14341
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014342 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014343 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014344 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014345 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014346 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14348 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14349
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014350 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014351
14352 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14353 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014354 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14355 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014356 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014357 result = 0;
14358 goto disconnected;
14359 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14360 /*
14361 * Wait here instead of returning directly, this will block the
14362 * next connect command and allow processing of the scan for
14363 * ssid and the previous connect command in CSR. Else we might
14364 * hit some race conditions leading to SME and HDD out of sync.
14365 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014366 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014368 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014369 pHddStaCtx->staDebugState = status;
14370 result = -EINVAL;
14371 goto disconnected;
14372 }
14373 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14374 msecs_to_jiffies
14375 (WLAN_WAIT_TIME_DISCONNECT));
14376
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014377 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014378 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014379 result = -ETIMEDOUT;
14380 }
14381disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14383#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14384 /* Sending disconnect event to userspace for kernel version < 3.11
14385 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14386 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014387 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014388 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14389 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014390#endif
14391
14392 return result;
14393}
14394
14395/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014396 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14397 * @reason: ieee80211 reason code.
14398 *
14399 * This utility function helps log string conversion of reason code.
14400 *
14401 * Return: string conversion of reason code, if match found;
14402 * "Unknown" otherwise.
14403 */
14404static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14405{
14406 switch (reason) {
14407 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14408 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14409 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14410 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14411 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14412 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14413 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14414 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14415 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14416 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14417 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14418 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14419 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14420 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14421 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14422 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14423 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14424 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14425 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14426 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14427 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14428 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14429 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14430 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14431 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14432 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14433 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14434 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14435 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14436 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14437 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14438 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14439 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14440 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14441 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14442 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14443 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14444 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14445 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14446 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14447 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14448 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14449 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14450 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14451 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14452 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14453 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14454 default:
14455 return "Unknown";
14456 }
14457}
14458
14459/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014460 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14461 * @wiphy: Pointer to wiphy
14462 * @dev: Pointer to network device
14463 * @reason: Disconnect reason code
14464 *
14465 * This function is used to issue a disconnect request to SME
14466 *
14467 * Return: 0 for success, non-zero for failure
14468 */
14469static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14470 struct net_device *dev, u16 reason)
14471{
14472 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14473 int status;
14474 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14475 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14476#ifdef FEATURE_WLAN_TDLS
14477 uint8_t staIdx;
14478#endif
14479
14480 ENTER();
14481
Anurag Chouhan6d760662016-02-20 16:05:43 +053014482 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014483 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014484 return -EINVAL;
14485 }
14486
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014487 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014488 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014489 return -EINVAL;
14490 }
14491
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014492 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014493 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14494 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014495 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496 hdd_device_mode_to_string(pAdapter->device_mode),
14497 pAdapter->device_mode, reason);
14498
14499 status = wlan_hdd_validate_context(pHddCtx);
14500
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014501 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014502 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014503
14504 /* Issue disconnect request to SME, if station is in connected state */
14505 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14506 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14507 eCsrRoamDisconnectReason reasonCode =
14508 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14509 hdd_scaninfo_t *pScanInfo;
14510
14511 switch (reason) {
14512 case WLAN_REASON_MIC_FAILURE:
14513 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14514 break;
14515
14516 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14517 case WLAN_REASON_DISASSOC_AP_BUSY:
14518 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14519 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14520 break;
14521
14522 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14523 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14524 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14525 break;
14526
14527 case WLAN_REASON_DEAUTH_LEAVING:
14528 reasonCode =
14529 pHddCtx->config->
14530 gEnableDeauthToDisassocMap ?
14531 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14532 eCSR_DISCONNECT_REASON_DEAUTH;
14533 break;
14534 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14535 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14536 break;
14537 default:
14538 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14539 break;
14540 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541 pScanInfo = &pAdapter->scan_info;
14542 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014543 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014545 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014546 eCSR_SCAN_ABORT_DEFAULT);
14547 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014548 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014549#ifdef FEATURE_WLAN_TDLS
14550 /* First clean up the tdls peers if any */
14551 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14552 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14553 pAdapter->sessionId)
14554 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14555 uint8_t *mac;
14556 mac =
14557 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014558 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014559 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014560 pHddCtx->tdlsConnInfo[staIdx].staId,
14561 pAdapter->sessionId,
14562 MAC_ADDR_ARRAY(mac));
14563 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14564 (pAdapter),
14565 pAdapter->sessionId, mac);
14566 }
14567 }
14568#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014569 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14570 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014571 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14572 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014573 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014574 return -EINVAL;
14575 }
14576 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014577 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014578 pHddStaCtx->conn_info.connState);
14579 }
14580
14581 return status;
14582}
14583
14584/**
14585 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14586 * @wiphy: Pointer to wiphy
14587 * @dev: Pointer to network device
14588 * @reason: Disconnect reason code
14589 *
14590 * Return: 0 for success, non-zero for failure
14591 */
14592static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14593 struct net_device *dev, u16 reason)
14594{
14595 int ret;
14596 cds_ssr_protect(__func__);
14597 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14598 cds_ssr_unprotect(__func__);
14599
14600 return ret;
14601}
14602
14603/**
14604 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14605 * @pAdapter: Pointer to adapter
14606 * @param: Pointer to IBSS parameters
14607 *
14608 * This function is used to initialize the security settings in IBSS mode
14609 *
14610 * Return: 0 for success, non-zero for failure
14611 */
14612static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14613 struct cfg80211_ibss_params
14614 *params)
14615{
14616 int status = 0;
14617 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14618 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14619 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14620
14621 ENTER();
14622
14623 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014624 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014625 pHddStaCtx->ibss_enc_key_installed = 0;
14626
14627 if (params->ie_len && (NULL != params->ie)) {
14628 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14629 params->ie_len, WLAN_EID_RSN)) {
14630 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14631 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14632 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14633 tDot11fIEWPA dot11WPAIE;
14634 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14635 u8 *ie;
14636
14637 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14638 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14639 params->ie_len,
14640 DOT11F_EID_WPA);
14641 if (NULL != ie) {
14642 pWextState->wpaVersion =
14643 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014644 /* Unpack the WPA IE
14645 * Skip past the EID byte and length byte
14646 * and four byte WiFi OUI
14647 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014648 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014649 &ie[2 + 4], ie[1] - 4,
14650 &dot11WPAIE, false);
14651 /*
14652 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014653 * encType for unicast cipher for
14654 * wpa-none is none
14655 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 encryptionType =
14657 hdd_translate_wpa_to_csr_encryption_type
14658 (dot11WPAIE.multicast_cipher);
14659 }
14660 }
14661
14662 status =
14663 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14664 params->ie_len);
14665
14666 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014667 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014668 return status;
14669 }
14670 }
14671
14672 pWextState->roamProfile.AuthType.authType[0] =
14673 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14674
14675 if (params->privacy) {
14676 /* Security enabled IBSS, At this time there is no information
14677 * available about the security paramters, so initialise the
14678 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14679 * The correct security parameters will be updated later in
14680 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14681 * set inorder enable privacy bit in beacons
14682 */
14683
14684 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14685 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014686 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14688 pWextState->roamProfile.EncryptionType.numEntries = 1;
14689 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14690 encryptionType;
14691 return status;
14692}
14693
14694/**
14695 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14696 * @wiphy: Pointer to wiphy
14697 * @dev: Pointer to network device
14698 * @param: Pointer to IBSS join parameters
14699 *
14700 * This function is used to create/join an IBSS network
14701 *
14702 * Return: 0 for success, non-zero for failure
14703 */
14704static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14705 struct net_device *dev,
14706 struct cfg80211_ibss_params *params)
14707{
14708 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14709 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14710 tCsrRoamProfile *pRoamProfile;
14711 int status;
14712 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14713 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014714 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014715 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716
14717 ENTER();
14718
Anurag Chouhan6d760662016-02-20 16:05:43 +053014719 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014720 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014721 return -EINVAL;
14722 }
14723
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014724 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014725 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014726 return -EINVAL;
14727 }
14728
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014729 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014730 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14731 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014732 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733 hdd_device_mode_to_string(pAdapter->device_mode),
14734 pAdapter->device_mode);
14735
14736 status = wlan_hdd_validate_context(pHddCtx);
14737
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014738 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014740
14741 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014742 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014743 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14744 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14745 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14746 int indx;
14747
14748 /* Get channel number */
14749 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750 params->
14751 chandef.
14752 chan->
14753 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014754
14755 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14756 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014757 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014758 return -EOPNOTSUPP;
14759 }
14760
14761 for (indx = 0; indx < numChans; indx++) {
14762 if (channelNum == validChan[indx]) {
14763 break;
14764 }
14765 }
14766 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014767 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014768 return -EINVAL;
14769 }
14770 }
14771
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014772 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14773 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014774 hdd_err("This concurrency combination is not allowed");
14775 return -ECONNREFUSED;
14776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014777
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014778 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014779 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014780 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014781
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014782 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14783 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014784 SIR_UPDATE_REASON_JOIN_IBSS);
14785 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014786 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014787 return -EINVAL;
14788 }
14789
14790 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014791 status = policy_mgr_wait_for_connection_update(
14792 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014793 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014794 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014795 return -EINVAL;
14796 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014797 }
14798
14799 /*Try disconnecting if already in connected state */
14800 status = wlan_hdd_try_disconnect(pAdapter);
14801 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014802 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014803 return -EALREADY;
14804 }
14805
14806 pRoamProfile = &pWextState->roamProfile;
14807
14808 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014809 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 return -EINVAL;
14811 }
14812
14813 /* enable selected protection checks in IBSS mode */
14814 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14815
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014816 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014817 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14818 pHddCtx->config->
14819 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014820 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014821 }
14822
14823 /* BSSID is provided by upper layers hence no need to AUTO generate */
14824 if (NULL != params->bssid) {
14825 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014826 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014827 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014828 return -EIO;
14829 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014830 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014831 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14832 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014833 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014834 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014835 return -EIO;
14836 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014837 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014838 }
14839 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14840 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14841 pRoamProfile->beaconInterval = params->beacon_interval;
14842 else {
14843 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014844 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014845 params->beacon_interval, pRoamProfile->beaconInterval);
14846 }
14847
14848 /* Set Channel */
14849 if (channelNum) {
14850 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014851 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852 pRoamProfile->ChannelInfo.numOfChannels = 1;
14853 pHddStaCtx->conn_info.operationChannel = channelNum;
14854 pRoamProfile->ChannelInfo.ChannelList =
14855 &pHddStaCtx->conn_info.operationChannel;
14856 }
14857
14858 /* Initialize security parameters */
14859 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14860 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014861 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014862 return status;
14863 }
14864
14865 /* Issue connect start */
14866 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14867 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014868 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014869 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014870 operationChannel,
14871 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014872
14873 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014874 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014875 return status;
14876 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014877 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878 return 0;
14879}
14880
14881/**
14882 * wlan_hdd_cfg80211_join_ibss() - join ibss
14883 * @wiphy: Pointer to wiphy
14884 * @dev: Pointer to network device
14885 * @param: Pointer to IBSS join parameters
14886 *
14887 * This function is used to create/join an IBSS network
14888 *
14889 * Return: 0 for success, non-zero for failure
14890 */
14891static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14892 struct net_device *dev,
14893 struct cfg80211_ibss_params *params)
14894{
14895 int ret = 0;
14896
14897 cds_ssr_protect(__func__);
14898 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14899 cds_ssr_unprotect(__func__);
14900
14901 return ret;
14902}
14903
14904/**
14905 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14906 * @wiphy: Pointer to wiphy
14907 * @dev: Pointer to network device
14908 *
14909 * This function is used to leave an IBSS network
14910 *
14911 * Return: 0 for success, non-zero for failure
14912 */
14913static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14914 struct net_device *dev)
14915{
14916 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14917 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14918 tCsrRoamProfile *pRoamProfile;
14919 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14920 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014921 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014922 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014923 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014924
14925 ENTER();
14926
Anurag Chouhan6d760662016-02-20 16:05:43 +053014927 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014928 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014929 return -EINVAL;
14930 }
14931
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014932 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014933 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014934 return -EINVAL;
14935 }
14936
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014937 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014938 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14939 pAdapter->sessionId,
14940 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14941 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014942 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014943 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014944
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014945 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014946 hdd_device_mode_to_string(pAdapter->device_mode),
14947 pAdapter->device_mode);
14948 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014949 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014950 return -EIO;
14951 }
14952
14953 pRoamProfile = &pWextState->roamProfile;
14954
14955 /* Issue disconnect only if interface type is set to IBSS */
14956 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014957 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014958 return -EINVAL;
14959 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014960 /* Clearing add IE of beacon */
14961 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14962 sizeof(tSirMacAddr));
14963 updateIE.smeSessionId = pAdapter->sessionId;
14964 updateIE.ieBufferlength = 0;
14965 updateIE.pAdditionIEBuffer = NULL;
14966 updateIE.append = true;
14967 updateIE.notify = true;
14968 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14969 &updateIE,
14970 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014971 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014972 }
14973
14974 /* Reset WNI_CFG_PROBE_RSP Flags */
14975 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014976
14977 /* Issue Disconnect request */
14978 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14979 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14980 pAdapter->sessionId,
14981 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014982 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014983 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014984 hal_status);
14985 return -EAGAIN;
14986 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014987
14988 /* wait for mc thread to cleanup and then return to upper stack
14989 * so by the time upper layer calls the change interface, we are
14990 * all set to proceed further
14991 */
14992 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14993 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14994 if (!rc) {
14995 hdd_err("Failed to disconnect, timed out");
14996 return -ETIMEDOUT;
14997 }
14998
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014999 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015000 return 0;
15001}
15002
15003/**
15004 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15005 * @wiphy: Pointer to wiphy
15006 * @dev: Pointer to network device
15007 *
15008 * This function is used to leave an IBSS network
15009 *
15010 * Return: 0 for success, non-zero for failure
15011 */
15012static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15013 struct net_device *dev)
15014{
15015 int ret = 0;
15016
15017 cds_ssr_protect(__func__);
15018 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15019 cds_ssr_unprotect(__func__);
15020
15021 return ret;
15022}
15023
15024/**
15025 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15026 * @wiphy: Pointer to wiphy
15027 * @changed: Parameters changed
15028 *
15029 * This function is used to set the phy parameters. RTS Threshold/FRAG
15030 * Threshold/Retry Count etc.
15031 *
15032 * Return: 0 for success, non-zero for failure
15033 */
15034static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15035 u32 changed)
15036{
15037 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15038 tHalHandle hHal = pHddCtx->hHal;
15039 int status;
15040
15041 ENTER();
15042
Anurag Chouhan6d760662016-02-20 16:05:43 +053015043 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015044 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015045 return -EINVAL;
15046 }
15047
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015048 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015049 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15050 NO_SESSION, wiphy->rts_threshold));
15051 status = wlan_hdd_validate_context(pHddCtx);
15052
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015053 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015054 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015055
15056 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15057 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15058 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15059
15060 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15061 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015062 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015063 rts_threshold);
15064 return -EINVAL;
15065 }
15066
15067 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15068 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015069 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 rts_threshold);
15071 return -EIO;
15072 }
15073
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015074 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075 }
15076
15077 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15078 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15079 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15080 wiphy->frag_threshold;
15081
15082 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15083 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015084 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 frag_threshold);
15086 return -EINVAL;
15087 }
15088
15089 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15090 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015091 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015092 frag_threshold);
15093 return -EIO;
15094 }
15095
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015096 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015097 }
15098
15099 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15100 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15101 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15102 wiphy->retry_short : wiphy->retry_long;
15103
15104 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15105 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015106 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015107 return -EINVAL;
15108 }
15109
15110 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15111 if (0 != sme_cfg_set_int(hHal,
15112 WNI_CFG_LONG_RETRY_LIMIT,
15113 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015114 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015115 retry_value);
15116 return -EIO;
15117 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015118 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015119 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15120 if (0 != sme_cfg_set_int(hHal,
15121 WNI_CFG_SHORT_RETRY_LIMIT,
15122 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015123 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015124 retry_value);
15125 return -EIO;
15126 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015127 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015128 }
15129 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015130 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015131 return 0;
15132}
15133
15134/**
15135 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15136 * @wiphy: Pointer to wiphy
15137 * @changed: Parameters changed
15138 *
15139 * Return: 0 for success, non-zero for failure
15140 */
15141static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15142{
15143 int ret;
15144
15145 cds_ssr_protect(__func__);
15146 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15147 cds_ssr_unprotect(__func__);
15148
15149 return ret;
15150}
15151
15152/**
15153 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15154 * key
15155 * @wiphy: Pointer to wiphy
15156 * @dev: Pointer to network device
15157 * @key_index: Key index
15158 *
15159 * Return: 0
15160 */
15161static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15162 struct net_device *netdev,
15163 u8 key_index)
15164{
15165 ENTER();
15166 return 0;
15167}
15168
15169/**
15170 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15171 * wlan_hdd_set_default_mgmt_key
15172 * @wiphy: pointer to wiphy
15173 * @netdev: pointer to net_device structure
15174 * @key_index: key index
15175 *
15176 * Return: 0 on success, error number on failure
15177 */
15178static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15179 struct net_device *netdev,
15180 u8 key_index)
15181{
15182 int ret;
15183
15184 cds_ssr_protect(__func__);
15185 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15186 cds_ssr_unprotect(__func__);
15187
15188 return ret;
15189}
15190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015191/**
15192 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15193 * @wiphy: Pointer to wiphy
15194 * @dev: Pointer to network device
15195 * @params: Pointer to tx queue parameters
15196 *
15197 * Return: 0
15198 */
15199static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15200 struct net_device *dev,
15201 struct ieee80211_txq_params *params)
15202{
15203 ENTER();
15204 return 0;
15205}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015206
15207/**
15208 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15209 * @wiphy: pointer to wiphy
15210 * @netdev: pointer to net_device structure
15211 * @params: pointer to ieee80211_txq_params
15212 *
15213 * Return: 0 on success, error number on failure
15214 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015215static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15216 struct net_device *dev,
15217 struct ieee80211_txq_params *params)
15218{
15219 int ret;
15220
15221 cds_ssr_protect(__func__);
15222 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15223 cds_ssr_unprotect(__func__);
15224
15225 return ret;
15226}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015227
15228/**
15229 * __wlan_hdd_cfg80211_del_station() - delete station v2
15230 * @wiphy: Pointer to wiphy
15231 * @param: Pointer to delete station parameter
15232 *
15233 * Return: 0 for success, non-zero for failure
15234 */
15235static
15236int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15237 struct net_device *dev,
15238 struct tagCsrDelStaParams *pDelStaParams)
15239{
15240 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15241 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015242 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015243 hdd_hostapd_state_t *hapd_state;
15244 int status;
15245 uint8_t staId;
15246 uint8_t *mac;
15247
15248 ENTER();
15249
Anurag Chouhan6d760662016-02-20 16:05:43 +053015250 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015251 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015252 return -EINVAL;
15253 }
15254
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015255 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015256 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015257 return -EINVAL;
15258 }
15259
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015260 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015261 TRACE_CODE_HDD_CFG80211_DEL_STA,
15262 pAdapter->sessionId, pAdapter->device_mode));
15263
15264 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15265 status = wlan_hdd_validate_context(pHddCtx);
15266
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015267 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015268 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015269
15270 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15271
Krunal Sonib4326f22016-03-10 13:05:51 -080015272 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15273 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015274
15275 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15276 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015277 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015278 return 0;
15279 }
15280
Anurag Chouhanc5548422016-02-24 18:33:27 +053015281 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 uint16_t i;
15283 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15284 if ((pAdapter->aStaInfo[i].isUsed) &&
15285 (!pAdapter->aStaInfo[i].
15286 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015287 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015288 mac,
15289 pAdapter->aStaInfo[i].
15290 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015291 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015292 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15293 hdd_ipa_wlan_evt(pAdapter,
15294 pAdapter->
15295 aStaInfo[i].
15296 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015297 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298 mac);
15299 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015300 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015301 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015302 MAC_ADDR_ARRAY(mac));
15303
15304 if (pHddCtx->dev_dfs_cac_status ==
15305 DFS_CAC_IN_PROGRESS)
15306 goto fn_end;
15307
Wei Song2f76f642016-11-18 16:32:53 +080015308 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015310 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015311 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015312 hdd_softap_sta_deauth(pAdapter,
15313 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015314 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315 pAdapter->aStaInfo[i].
15316 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015317 qdf_status =
15318 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015319 &hapd_state->
15320 qdf_sta_disassoc_event,
15321 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015322 if (!QDF_IS_STATUS_SUCCESS(
15323 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015324 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015325 }
15326 }
15327 }
15328 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015329 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015330 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015331 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015332 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015333 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015334 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015335 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015336 MAC_ADDR_ARRAY(mac));
15337 return -ENOENT;
15338 }
15339
15340 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15341 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015342 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015343 }
15344
15345 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15346 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015347 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015348 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015349 MAC_ADDR_ARRAY(mac));
15350 return -ENOENT;
15351 }
15352
15353 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15354
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015355 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356 MAC_ADDR_ARRAY(mac));
15357
15358 /* Case: SAP in ACS selected DFS ch and client connected
15359 * Now Radar detected. Then if random channel is another
15360 * DFS ch then new CAC is initiated and no TX allowed.
15361 * So do not send any mgmt frames as it will timeout
15362 * during CAC.
15363 */
15364
15365 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15366 goto fn_end;
15367
Wei Song2f76f642016-11-18 16:32:53 +080015368 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015369 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15370 (pAdapter), pAdapter->sessionId,
15371 (uint8_t *)&pDelStaParams->peerMacAddr,
15372 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015373 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015375 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015376 pAdapter->aStaInfo[staId].isDeauthInProgress =
15377 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015378 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015379 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015380 MAC_ADDR_ARRAY(mac));
15381 return -ENOENT;
15382 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015383 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015384 &hapd_state->
15385 qdf_sta_disassoc_event,
15386 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015387 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015388 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015389 }
15390 }
15391 }
15392
15393fn_end:
15394 EXIT();
15395 return 0;
15396}
15397
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015398#if defined(USE_CFG80211_DEL_STA_V2)
15399/**
15400 * wlan_hdd_del_station() - delete station wrapper
15401 * @adapter: pointer to the hdd adapter
15402 *
15403 * Return: None
15404 */
15405void wlan_hdd_del_station(hdd_adapter_t *adapter)
15406{
15407 struct station_del_parameters del_sta;
15408 del_sta.mac = NULL;
15409 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15410 del_sta.reason_code = eCsrForcedDeauthSta;
15411
15412 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15413 &del_sta);
15414}
15415#else
15416void wlan_hdd_del_station(hdd_adapter_t *adapter)
15417{
15418 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15419}
15420#endif
15421
15422#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015423/**
15424 * wlan_hdd_cfg80211_del_station() - delete station v2
15425 * @wiphy: Pointer to wiphy
15426 * @param: Pointer to delete station parameter
15427 *
15428 * Return: 0 for success, non-zero for failure
15429 */
15430int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15431 struct net_device *dev,
15432 struct station_del_parameters *param)
15433#else
15434/**
15435 * wlan_hdd_cfg80211_del_station() - delete station
15436 * @wiphy: Pointer to wiphy
15437 * @mac: Pointer to station mac address
15438 *
15439 * Return: 0 for success, non-zero for failure
15440 */
15441#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15442int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15443 struct net_device *dev,
15444 const uint8_t *mac)
15445#else
15446int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15447 struct net_device *dev,
15448 uint8_t *mac)
15449#endif
15450#endif
15451{
15452 int ret;
15453 struct tagCsrDelStaParams delStaParams;
15454
15455 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015456#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015457 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015458 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015459 return -EINVAL;
15460 }
15461 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15462 param->subtype, &delStaParams);
15463#else
15464 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15465 (SIR_MAC_MGMT_DEAUTH >> 4),
15466 &delStaParams);
15467#endif
15468 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15469 cds_ssr_unprotect(__func__);
15470
15471 return ret;
15472}
15473
15474/**
15475 * __wlan_hdd_cfg80211_add_station() - add station
15476 * @wiphy: Pointer to wiphy
15477 * @mac: Pointer to station mac address
15478 * @pmksa: Pointer to add station parameter
15479 *
15480 * Return: 0 for success, non-zero for failure
15481 */
15482static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15483 struct net_device *dev,
15484 const uint8_t *mac,
15485 struct station_parameters *params)
15486{
15487 int status = -EPERM;
15488#ifdef FEATURE_WLAN_TDLS
15489 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15490 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15491 u32 mask, set;
15492
15493 ENTER();
15494
Anurag Chouhan6d760662016-02-20 16:05:43 +053015495 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015496 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015497 return -EINVAL;
15498 }
15499
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015500 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015501 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015502 return -EINVAL;
15503 }
15504
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015505 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015506 TRACE_CODE_HDD_CFG80211_ADD_STA,
15507 pAdapter->sessionId, params->listen_interval));
15508
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015509 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015510 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015511
15512 mask = params->sta_flags_mask;
15513
15514 set = params->sta_flags_set;
15515
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015516 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015517 MAC_ADDR_ARRAY(mac));
15518
15519 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15520 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015521#if defined(CONVERGED_TDLS_ENABLE)
15522 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15523 dev, mac);
15524#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015525 status =
15526 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015527#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015528 }
15529 }
15530#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015531 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015532 return status;
15533}
15534
15535/**
15536 * wlan_hdd_cfg80211_add_station() - add station
15537 * @wiphy: Pointer to wiphy
15538 * @mac: Pointer to station mac address
15539 * @pmksa: Pointer to add station parameter
15540 *
15541 * Return: 0 for success, non-zero for failure
15542 */
15543#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15544static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15545 struct net_device *dev,
15546 const uint8_t *mac,
15547 struct station_parameters *params)
15548#else
15549static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15550 struct net_device *dev, uint8_t *mac,
15551 struct station_parameters *params)
15552#endif
15553{
15554 int ret;
15555
15556 cds_ssr_protect(__func__);
15557 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15558 cds_ssr_unprotect(__func__);
15559
15560 return ret;
15561}
15562
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015563/**
15564 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15565 * @wiphy: Pointer to wiphy
15566 * @dev: Pointer to network device
15567 * @pmksa: Pointer to set pmksa parameter
15568 *
15569 * Return: 0 for success, non-zero for failure
15570 */
15571static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15572 struct net_device *dev,
15573 struct cfg80211_pmksa *pmksa)
15574{
15575 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15576 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15577 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015578 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015579 int status;
15580 tPmkidCacheInfo pmk_id;
15581
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015582 ENTER();
15583
Anurag Chouhan6d760662016-02-20 16:05:43 +053015584 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015585 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586 return -EINVAL;
15587 }
15588
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015589 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015590 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015591 return -EINVAL;
15592 }
15593
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015594 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015595 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015596 return -EINVAL;
15597 }
15598
15599 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015600 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 pmksa->bssid, pmksa->pmkid);
15602 return -EINVAL;
15603 }
15604
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015605 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606 MAC_ADDR_ARRAY(pmksa->bssid));
15607
15608 status = wlan_hdd_validate_context(pHddCtx);
15609
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015610 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015611 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015612
15613 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15614
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015615 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15616 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015617
15618 /* Add to the PMKSA ID Cache in CSR */
15619 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15620 &pmk_id, 1, false);
15621
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015622 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015623 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15624 pAdapter->sessionId, result));
15625
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015626 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015627 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015628}
15629
15630/**
15631 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15632 * @wiphy: Pointer to wiphy
15633 * @dev: Pointer to network device
15634 * @pmksa: Pointer to set pmksa parameter
15635 *
15636 * Return: 0 for success, non-zero for failure
15637 */
15638static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15639 struct net_device *dev,
15640 struct cfg80211_pmksa *pmksa)
15641{
15642 int ret;
15643
15644 cds_ssr_protect(__func__);
15645 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15646 cds_ssr_unprotect(__func__);
15647
15648 return ret;
15649}
15650
15651/**
15652 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15653 * @wiphy: Pointer to wiphy
15654 * @dev: Pointer to network device
15655 * @pmksa: Pointer to pmksa parameter
15656 *
15657 * Return: 0 for success, non-zero for failure
15658 */
15659static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15660 struct net_device *dev,
15661 struct cfg80211_pmksa *pmksa)
15662{
15663 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15664 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15665 tHalHandle halHandle;
15666 int status = 0;
15667
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015668 ENTER();
15669
Anurag Chouhan6d760662016-02-20 16:05:43 +053015670 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015671 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015672 return -EINVAL;
15673 }
15674
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015675 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15676 hdd_err("invalid session id: %d", pAdapter->sessionId);
15677 return -EINVAL;
15678 }
15679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015680 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015681 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015682 return -EINVAL;
15683 }
15684
15685 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015686 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015687 return -EINVAL;
15688 }
15689
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015690 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015691 MAC_ADDR_ARRAY(pmksa->bssid));
15692
15693 status = wlan_hdd_validate_context(pHddCtx);
15694
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015695 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015696 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015697
15698 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15699
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015700 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015701 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15702 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015704 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015705 sme_roam_del_pmkid_from_cache(halHandle,
15706 pAdapter->sessionId, pmksa->bssid,
15707 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015708 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015709 MAC_ADDR_ARRAY(pmksa->bssid));
15710 status = -EINVAL;
15711 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015712 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015713 return status;
15714}
15715
15716/**
15717 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15718 * @wiphy: Pointer to wiphy
15719 * @dev: Pointer to network device
15720 * @pmksa: Pointer to pmksa parameter
15721 *
15722 * Return: 0 for success, non-zero for failure
15723 */
15724static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15725 struct net_device *dev,
15726 struct cfg80211_pmksa *pmksa)
15727{
15728 int ret;
15729
15730 cds_ssr_protect(__func__);
15731 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15732 cds_ssr_unprotect(__func__);
15733
15734 return ret;
15735
15736}
15737
15738/**
15739 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15740 * @wiphy: Pointer to wiphy
15741 * @dev: Pointer to network device
15742 *
15743 * Return: 0 for success, non-zero for failure
15744 */
15745static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15746 struct net_device *dev)
15747{
15748 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15749 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15750 tHalHandle halHandle;
15751 int status = 0;
15752
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015753 ENTER();
15754
Anurag Chouhan6d760662016-02-20 16:05:43 +053015755 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015756 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757 return -EINVAL;
15758 }
15759
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015760 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15761 hdd_err("invalid session id: %d", pAdapter->sessionId);
15762 return -EINVAL;
15763 }
15764
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015765 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015766
15767 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15768 status = wlan_hdd_validate_context(pHddCtx);
15769
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015770 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015771 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015772
15773 /* Retrieve halHandle */
15774 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15775
15776 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015777 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015778 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15779 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015780 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781 status = -EINVAL;
15782 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015783 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015784 return status;
15785}
15786
15787/**
15788 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15789 * @wiphy: Pointer to wiphy
15790 * @dev: Pointer to network device
15791 *
15792 * Return: 0 for success, non-zero for failure
15793 */
15794static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15795 struct net_device *dev)
15796{
15797 int ret;
15798
15799 cds_ssr_protect(__func__);
15800 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15801 cds_ssr_unprotect(__func__);
15802
15803 return ret;
15804}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015805
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015806#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015807/**
15808 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15809 * @wiphy: Pointer to wiphy
15810 * @dev: Pointer to network device
15811 * @ftie: Pointer to fast transition ie parameter
15812 *
15813 * Return: 0 for success, non-zero for failure
15814 */
15815static int
15816__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15817 struct net_device *dev,
15818 struct cfg80211_update_ft_ies_params *ftie)
15819{
15820 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15821 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15822 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15823 int status;
15824
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015825 ENTER();
15826
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 status = wlan_hdd_validate_context(hdd_ctx);
15828 if (status)
15829 return status;
15830
Anurag Chouhan6d760662016-02-20 16:05:43 +053015831 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015832 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015833 return -EINVAL;
15834 }
15835
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015836 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15837 hdd_err("invalid session id: %d", pAdapter->sessionId);
15838 return -EINVAL;
15839 }
15840
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015841 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015842 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15843 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15844 /* Added for debug on reception of Re-assoc Req. */
15845 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015846 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015847 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015848 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015850 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015851 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015852
15853 /* Pass the received FT IEs to SME */
15854 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15855 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015856 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015857 return 0;
15858}
15859
15860/**
15861 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15862 * @wiphy: Pointer to wiphy
15863 * @dev: Pointer to network device
15864 * @ftie: Pointer to fast transition ie parameter
15865 *
15866 * Return: 0 for success, non-zero for failure
15867 */
15868static int
15869wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15870 struct net_device *dev,
15871 struct cfg80211_update_ft_ies_params *ftie)
15872{
15873 int ret;
15874
15875 cds_ssr_protect(__func__);
15876 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15877 cds_ssr_unprotect(__func__);
15878
15879 return ret;
15880}
15881#endif
15882
Mukul Sharma3d36c392017-01-18 18:39:12 +053015883void wlan_hdd_cfg80211_update_replay_counter_callback(
15884 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015886{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015887 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15888 uint8_t temp_replay_counter[8];
15889 int i;
15890 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015891
15892 ENTER();
15893
Mukul Sharma3d36c392017-01-18 18:39:12 +053015894 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015895 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015896 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015897 }
15898
Mukul Sharma3d36c392017-01-18 18:39:12 +053015899 if (!gtk_rsp_param) {
15900 hdd_err("gtk_rsp_param is Null");
15901 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015902 }
15903
Mukul Sharma3d36c392017-01-18 18:39:12 +053015904 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015905 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015906 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907 }
15908
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015909 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015910 gtk_rsp_param->replay_counter);
15911 /* convert little to big endian since supplicant works on big endian */
15912 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15913 for (i = 0; i < 8; i++)
15914 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015915
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015916 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015917 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015918 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015919 gtk_rsp_param->bssid.bytes,
15920 temp_replay_counter, GFP_KERNEL);
15921out:
15922 EXIT();
15923
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015924}
15925
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015926static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015928 struct net_device *dev,
15929 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015930{
15931 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015932 int result, i;
15933 struct pmo_gtk_req *gtk_req = NULL;
15934 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15935 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015936 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015937
15938 ENTER();
15939
Anurag Chouhan6d760662016-02-20 16:05:43 +053015940 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015941 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015942 result = -EINVAL;
15943 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015944 }
15945
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015946 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15947 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015948 result = -EINVAL;
15949 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015950 }
15951
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015952 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015953 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15954 pAdapter->sessionId, pAdapter->device_mode));
15955
Mukul Sharma3d36c392017-01-18 18:39:12 +053015956 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015957 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015958 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015959
Mukul Sharma3d36c392017-01-18 18:39:12 +053015960 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15961 if (!gtk_req) {
15962 hdd_err("cannot allocate gtk_req");
15963 result = -ENOMEM;
15964 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965 }
15966
Mukul Sharma3d36c392017-01-18 18:39:12 +053015967 /* convert big to little endian since driver work on little endian */
15968 buf = (uint8_t *)&gtk_req->replay_counter;
15969 for (i = 0; i < 8; i++)
15970 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015971
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015972 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015973 gtk_req->replay_counter);
15974 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15975 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15976 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15977 if (status != QDF_STATUS_SUCCESS) {
15978 hdd_err("Failed to cache GTK Offload");
15979 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015980 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015981out:
15982 if (gtk_req)
15983 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015984 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015986 return result;
15987}
15988
15989/**
15990 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15991 * @wiphy: Pointer to wiphy
15992 * @dev: Pointer to network device
15993 * @data: Pointer to rekey data
15994 *
15995 * This function is used to offload GTK rekeying job to the firmware.
15996 *
15997 * Return: 0 for success, non-zero for failure
15998 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015999static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016000int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16001 struct net_device *dev,
16002 struct cfg80211_gtk_rekey_data *data)
16003{
16004 int ret;
16005
16006 cds_ssr_protect(__func__);
16007 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16008 cds_ssr_unprotect(__func__);
16009
16010 return ret;
16011}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012
16013/**
16014 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16015 * @wiphy: Pointer to wiphy
16016 * @dev: Pointer to network device
16017 * @param: Pointer to access control parameter
16018 *
16019 * Return: 0 for success, non-zero for failure
16020 */
16021static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16022 struct net_device *dev,
16023 const struct cfg80211_acl_data *params)
16024{
16025 int i;
16026 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16027 hdd_hostapd_state_t *pHostapdState;
16028 tsap_Config_t *pConfig;
16029 v_CONTEXT_t p_cds_context = NULL;
16030 hdd_context_t *pHddCtx;
16031 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016032 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033
16034 ENTER();
16035
Anurag Chouhan6d760662016-02-20 16:05:43 +053016036 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016037 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016038 return -EINVAL;
16039 }
16040
16041 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016042 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016043 return -EINVAL;
16044 }
16045
16046 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16047 status = wlan_hdd_validate_context(pHddCtx);
16048
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016049 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016051
16052 p_cds_context = pHddCtx->pcds_context;
16053 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16054
16055 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016056 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 return -EINVAL;
16058 }
16059
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016060 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016061 params->n_acl_entries);
16062
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016063 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016064 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16065 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016066 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016067 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16068
16069 /* default value */
16070 pConfig->num_accept_mac = 0;
16071 pConfig->num_deny_mac = 0;
16072
16073 /**
16074 * access control policy
16075 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16076 * listed in hostapd.deny file.
16077 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16078 * listed in hostapd.accept file.
16079 */
16080 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16081 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16082 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16083 params->acl_policy) {
16084 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16085 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016086 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016087 params->acl_policy);
16088 return -ENOTSUPP;
16089 }
16090
16091 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16092 pConfig->num_accept_mac = params->n_acl_entries;
16093 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016094 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016095 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016096 MAC_ADDR_ARRAY(
16097 params->mac_addrs[i].addr));
16098
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016099 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016100 params->mac_addrs[i].addr,
16101 sizeof(qcmacaddr));
16102 }
16103 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16104 pConfig->num_deny_mac = params->n_acl_entries;
16105 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016106 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016107 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016108 MAC_ADDR_ARRAY(
16109 params->mac_addrs[i].addr));
16110
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016111 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016112 params->mac_addrs[i].addr,
16113 sizeof(qcmacaddr));
16114 }
16115 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016116 qdf_status = wlansap_set_mac_acl(
16117 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016118 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016119 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016120 return -EINVAL;
16121 }
16122 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016123 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016124 hdd_device_mode_to_string(pAdapter->device_mode),
16125 pAdapter->device_mode);
16126 return -EINVAL;
16127 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016128 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016129 return 0;
16130}
16131
16132/**
16133 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16134 * __wlan_hdd_cfg80211_set_mac_acl
16135 * @wiphy: pointer to wiphy structure
16136 * @dev: pointer to net_device
16137 * @params: pointer to cfg80211_acl_data
16138 *
16139 * Return; 0 on success, error number otherwise
16140 */
16141static int
16142wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16143 struct net_device *dev,
16144 const struct cfg80211_acl_data *params)
16145{
16146 int ret;
16147
16148 cds_ssr_protect(__func__);
16149 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16150 cds_ssr_unprotect(__func__);
16151
16152 return ret;
16153}
16154
16155#ifdef WLAN_NL80211_TESTMODE
16156#ifdef FEATURE_WLAN_LPHB
16157/**
16158 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16159 * @pHddCtx: Pointer to hdd context
16160 * @lphbInd: Pointer to low power heart beat indication parameter
16161 *
16162 * Return: none
16163 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016164static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016165 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166{
16167 struct sk_buff *skb;
16168
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016169 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016170
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016171 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016172 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016173
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016174 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016175 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176 return;
16177 }
16178
16179 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016180 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016181 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016182 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016183 return;
16184 }
16185
16186 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016187 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188 goto nla_put_failure;
16189 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016190 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016191 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016192 goto nla_put_failure;
16193 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016194 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16195 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016196 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197 goto nla_put_failure;
16198 }
16199 cfg80211_testmode_event(skb, GFP_ATOMIC);
16200 return;
16201
16202nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016203 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016204 kfree_skb(skb);
16205
16206 return;
16207}
16208#endif /* FEATURE_WLAN_LPHB */
16209
16210/**
16211 * __wlan_hdd_cfg80211_testmode() - test mode
16212 * @wiphy: Pointer to wiphy
16213 * @data: Data pointer
16214 * @len: Data length
16215 *
16216 * Return: 0 for success, non-zero for failure
16217 */
16218static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16219 void *data, int len)
16220{
16221 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16222 int err;
16223 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16224
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016225 ENTER();
16226
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227 err = wlan_hdd_validate_context(pHddCtx);
16228 if (err)
16229 return err;
16230
16231 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16232 len, wlan_hdd_tm_policy);
16233 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016234 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235 return err;
16236 }
16237
16238 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016239 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 return -EINVAL;
16241 }
16242
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016243 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016244 TRACE_CODE_HDD_CFG80211_TESTMODE,
16245 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16247#ifdef FEATURE_WLAN_LPHB
16248 /* Low Power Heartbeat configuration request */
16249 case WLAN_HDD_TM_CMD_WLAN_HB:
16250 {
16251 int buf_len;
16252 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016253 struct pmo_lphb_req *hb_params = NULL;
16254 struct pmo_lphb_req *hb_params_temp = NULL;
16255 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016256
16257 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016258 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016259 return -EINVAL;
16260 }
16261
16262 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16263 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16264
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016265 hb_params_temp = (struct pmo_lphb_req *) buf;
16266 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16267 && (hb_params_temp->params.lphb_tcp_params.
16268 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269 return -EINVAL;
16270
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016271 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16272 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016274 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275 return -ENOMEM;
16276 }
16277
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016278 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016279 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16280 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016281 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016282 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016283 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016284
16285 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016286 return 0;
16287 }
16288#endif /* FEATURE_WLAN_LPHB */
16289
16290#if defined(QCA_WIFI_FTM)
16291 case WLAN_HDD_TM_CMD_WLAN_FTM:
16292 {
16293 int buf_len;
16294 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016295 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016296 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016297 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016298 return -EINVAL;
16299 }
16300
16301 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16302 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16303
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016304 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016305
16306 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16307
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016308 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016309 err = -EBUSY;
16310 break;
16311 }
16312#endif
16313
16314 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016315 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016316 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16317 return -EOPNOTSUPP;
16318 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016319 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016320 return err;
16321}
16322
16323/**
16324 * wlan_hdd_cfg80211_testmode() - test mode
16325 * @wiphy: Pointer to wiphy
16326 * @dev: Pointer to network device
16327 * @data: Data pointer
16328 * @len: Data length
16329 *
16330 * Return: 0 for success, non-zero for failure
16331 */
16332static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16333#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16334 struct wireless_dev *wdev,
16335#endif
16336 void *data, int len)
16337{
16338 int ret;
16339
16340 cds_ssr_protect(__func__);
16341 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16342 cds_ssr_unprotect(__func__);
16343
16344 return ret;
16345}
16346
16347#if defined(QCA_WIFI_FTM)
16348/**
16349 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16350 * @buf: Pointer to buffer
16351 * @buf_len: Buffer length
16352 *
16353 * Return: none
16354 */
16355void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16356{
16357 struct sk_buff *skb;
16358 hdd_context_t *hdd_ctx;
16359
16360 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016361 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016362 return;
16363 }
16364
Anurag Chouhan6d760662016-02-20 16:05:43 +053016365 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016366 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016367 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016368 return;
16369 }
16370
16371 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16372 buf_len, GFP_KERNEL);
16373 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016374 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016375 return;
16376 }
16377
16378 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16379 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16380 goto nla_put_failure;
16381
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016382 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016383
16384 cfg80211_testmode_event(skb, GFP_KERNEL);
16385 return;
16386
16387nla_put_failure:
16388 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016389 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016390}
16391#endif
16392#endif /* CONFIG_NL80211_TESTMODE */
16393
16394#ifdef QCA_HT_2040_COEX
16395/**
16396 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16397 * @wiphy: Pointer to wiphy
16398 * @dev: Pointer to network device
16399 * @chandef: Pointer to channel definition parameter
16400 *
16401 * Return: 0 for success, non-zero for failure
16402 */
16403static int
16404__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16405 struct net_device *dev,
16406 struct cfg80211_chan_def *chandef)
16407{
16408 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16409 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016410 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016411 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016412 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016413
Anurag Chouhan6d760662016-02-20 16:05:43 +053016414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016415 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016416 return -EINVAL;
16417 }
16418
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016419 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16420 hdd_err("invalid session id: %d", pAdapter->sessionId);
16421 return -EINVAL;
16422 }
16423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016424 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16425 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016426 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016427 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016428
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016429 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016430 sme_get_config_param(pHddCtx->hHal, &sme_config);
16431 switch (chandef->width) {
16432 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016433 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434 if (sme_config.csrConfig.channelBondingMode24GHz !=
16435 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16436 sme_config.csrConfig.channelBondingMode24GHz =
16437 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16438 sme_update_config(pHddCtx->hHal, &sme_config);
16439 cbModeChange = true;
16440 }
16441 break;
16442
16443 case NL80211_CHAN_WIDTH_40:
16444 if (sme_config.csrConfig.channelBondingMode24GHz ==
16445 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16446 if (NL80211_CHAN_HT40MINUS ==
16447 cfg80211_get_chandef_type(chandef))
16448 sme_config.csrConfig.channelBondingMode24GHz =
16449 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16450 else
16451 sme_config.csrConfig.channelBondingMode24GHz =
16452 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16453 sme_update_config(pHddCtx->hHal, &sme_config);
16454 cbModeChange = true;
16455 }
16456 break;
16457
16458 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016459 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016460 return -EINVAL;
16461 }
16462
16463 if (!cbModeChange)
16464 return 0;
16465
Krunal Sonib4326f22016-03-10 13:05:51 -080016466 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016467 return 0;
16468
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016469 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016470 sme_config.csrConfig.channelBondingMode24GHz);
16471
16472 /* Change SAP ht2040 mode */
16473 status = hdd_set_sap_ht2040_mode(pAdapter,
16474 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016475 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016476 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016477 return -EINVAL;
16478 }
16479
16480 return 0;
16481}
16482
16483/**
16484 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16485 * @wiphy: Pointer to wiphy
16486 * @dev: Pointer to network device
16487 * @chandef: Pointer to channel definition parameter
16488 *
16489 * Return: 0 for success, non-zero for failure
16490 */
16491static int
16492wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16493 struct net_device *dev,
16494 struct cfg80211_chan_def *chandef)
16495{
16496 int ret;
16497
16498 cds_ssr_protect(__func__);
16499 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16500 cds_ssr_unprotect(__func__);
16501
16502 return ret;
16503}
16504#endif
16505
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016506#ifdef CHANNEL_SWITCH_SUPPORTED
16507/**
16508 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16509 * channel in SAP/GO
16510 * @wiphy: wiphy pointer
16511 * @dev: dev pointer.
16512 * @csa_params: Change channel params
16513 *
16514 * This function is called to switch channel in SAP/GO
16515 *
16516 * Return: 0 if success else return non zero
16517 */
16518static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16519 struct net_device *dev,
16520 struct cfg80211_csa_settings *csa_params)
16521{
16522 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16523 hdd_context_t *hdd_ctx;
16524 uint8_t channel;
16525 uint16_t freq;
16526 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016527 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016528
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016529 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016530 csa_params->chandef.chan->center_freq);
16531
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016532 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16533 hdd_err("invalid session id: %d", adapter->sessionId);
16534 return -EINVAL;
16535 }
16536
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016537 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16538 ret = wlan_hdd_validate_context(hdd_ctx);
16539
16540 if (0 != ret)
16541 return ret;
16542
Krunal Sonib4326f22016-03-10 13:05:51 -080016543 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16544 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016545 return -ENOTSUPP;
16546
16547 freq = csa_params->chandef.chan->center_freq;
16548 channel = cds_freq_to_chan(freq);
16549
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016550 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16551
16552 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016553 return ret;
16554}
16555
16556/**
16557 * wlan_hdd_cfg80211_channel_switch()- function to switch
16558 * channel in SAP/GO
16559 * @wiphy: wiphy pointer
16560 * @dev: dev pointer.
16561 * @csa_params: Change channel params
16562 *
16563 * This function is called to switch channel in SAP/GO
16564 *
16565 * Return: 0 if success else return non zero
16566 */
16567static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16568 struct net_device *dev,
16569 struct cfg80211_csa_settings *csa_params)
16570{
16571 int ret;
16572
16573 cds_ssr_protect(__func__);
16574 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16575 cds_ssr_unprotect(__func__);
16576 return ret;
16577}
16578#endif
16579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016580/**
16581 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16582 * translation from NL to policy manager type
16583 * @type: Generic connection mode type defined in NL
16584 *
16585 *
16586 * This function provides the type translation
16587 *
16588 * Return: cds_con_mode enum
16589 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016590enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016591 enum nl80211_iftype type)
16592{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016593 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016594 switch (type) {
16595 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016596 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016597 break;
16598 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016599 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016600 break;
16601 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016602 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016603 break;
16604 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016605 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016606 break;
16607 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016608 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016609 break;
16610 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016611 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016612 }
16613 return mode;
16614}
16615
16616/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016617 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16618 * @wiphy: Handle to struct wiphy to get handle to module context.
16619 * @chandef: Contains information about the capture channel to be set.
16620 *
16621 * This interface is called if and only if monitor mode interface alone is
16622 * active.
16623 *
16624 * Return: 0 success or error code on failure.
16625 */
16626static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16627 struct cfg80211_chan_def *chandef)
16628{
16629 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16630 hdd_adapter_t *adapter;
16631 hdd_station_ctx_t *sta_ctx;
16632 struct hdd_mon_set_ch_info *ch_info;
16633 QDF_STATUS status;
16634 tHalHandle hal_hdl;
16635 struct qdf_mac_addr bssid;
16636 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016637 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016638 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016639 int ret;
16640 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16641
16642 ENTER();
16643
16644 ret = wlan_hdd_validate_context(hdd_ctx);
16645 if (ret)
16646 return ret;
16647
16648 hal_hdl = hdd_ctx->hHal;
16649
16650 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16651 if (!adapter)
16652 return -EIO;
16653
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016654 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016655 adapter->dev->name, chan_num, chandef->chan->center_freq);
16656
16657 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16658 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016659 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16660 roam_profile.ChannelInfo.numOfChannels = 1;
16661 roam_profile.phyMode = ch_info->phy_mode;
16662 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016663 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016664
16665 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16666 QDF_MAC_ADDR_SIZE);
16667
16668 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016669 /*
16670 * CDS api expects secondary channel for calculating
16671 * the channel params
16672 */
16673 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016674 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016675 if (chan_num >= 1 && chan_num <= 5)
16676 sec_ch = chan_num + 4;
16677 else if (chan_num >= 6 && chan_num <= 13)
16678 sec_ch = chan_num - 4;
16679 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016680 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16681 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016682 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16683 &roam_profile);
16684 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016685 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016686 status);
16687 ret = qdf_status_to_os_return(status);
16688 return ret;
16689 }
16690 EXIT();
16691 return 0;
16692}
16693
16694/**
16695 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16696 * @wiphy: Handle to struct wiphy to get handle to module context.
16697 * @chandef: Contains information about the capture channel to be set.
16698 *
16699 * This interface is called if and only if monitor mode interface alone is
16700 * active.
16701 *
16702 * Return: 0 success or error code on failure.
16703 */
16704static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16705 struct cfg80211_chan_def *chandef)
16706{
16707 int ret;
16708
16709 cds_ssr_protect(__func__);
16710 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16711 cds_ssr_unprotect(__func__);
16712 return ret;
16713}
16714
16715/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016716 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16717 * @adapter: pointer to adapter
16718 *
16719 * Wrapper function to clear link layer stats.
16720 * return - void
16721 */
16722void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16723{
16724 tSirLLStatsClearReq link_layer_stats_clear_req;
16725 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16726
Mukul Sharma491021c2016-09-29 21:39:19 +053016727 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16728 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016729 link_layer_stats_clear_req.stopReq = 0;
16730 link_layer_stats_clear_req.reqId = 1;
16731 link_layer_stats_clear_req.staId = adapter->sessionId;
16732 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16733
16734 return;
16735}
16736
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016737/**
16738 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16739 * @adapter: HDD Adapter
16740 *
16741 * If roaming is in progress and there is a request to
16742 * disconnect the session, then it is deferred. Once
16743 * roaming is complete/aborted, then this routine is
16744 * used to resume the disconnect that was deferred
16745 *
16746 * Return: None
16747 */
16748void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16749{
16750 switch (adapter->defer_disconnect) {
16751 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16752 adapter->defer_disconnect = 0;
16753 wlan_hdd_disconnect(adapter,
16754 adapter->cfg80211_disconnect_reason);
16755 break;
16756 case DEFER_DISCONNECT_TRY_DISCONNECT:
16757 wlan_hdd_try_disconnect(adapter);
16758 adapter->defer_disconnect = 0;
16759 break;
16760 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016761 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016762 adapter->defer_disconnect);
16763 break;
16764 }
16765}
16766
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016767#define CNT_DIFF(cur, prev) \
16768 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16769#define MAX_COUNT 0xffffffff
16770static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16771 struct scan_chan_info *chan,
16772 struct scan_chan_info *info, uint32_t cmd_flag)
16773{
16774 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16775 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16776 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16777
16778 mutex_lock(&hdd_ctx->chan_info_lock);
16779
16780 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16781 qdf_mem_zero(chan, sizeof(*chan));
16782
16783 chan->freq = info->freq;
16784 chan->noise_floor = info->noise_floor;
16785 chan->clock_freq = info->clock_freq;
16786 chan->cmd_flag = info->cmd_flag;
16787 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16788
16789 chan->rx_clear_count =
16790 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16791
16792 chan->tx_frame_count =
16793 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16794
16795 mutex_unlock(&hdd_ctx->chan_info_lock);
16796
16797}
16798#undef CNT_DIFF
16799#undef MAX_COUNT
16800
16801/**
16802 * wlan_hdd_chan_info_cb() - channel info callback
16803 * @chan_info: struct scan_chan_info
16804 *
16805 * Store channel info into HDD context
16806 *
16807 * Return: None.
16808 */
16809static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16810{
16811 hdd_context_t *hdd_ctx;
16812 struct scan_chan_info *chan;
16813 uint8_t idx;
16814
16815 ENTER();
16816
16817 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16818 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16819 hdd_err("hdd_ctx is invalid");
16820 return;
16821 }
16822
16823 if (!hdd_ctx->chan_info) {
16824 hdd_err("chan_info is NULL");
16825 return;
16826 }
16827
16828 chan = hdd_ctx->chan_info;
16829 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16830 if (chan[idx].freq == info->freq) {
16831 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16832 info->cmd_flag);
16833 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16834 chan[idx].cmd_flag, chan[idx].freq,
16835 chan[idx].noise_floor,
16836 chan[idx].cycle_count, chan[idx].rx_clear_count,
16837 chan[idx].clock_freq, chan[idx].cmd_flag,
16838 chan[idx].tx_frame_count, idx);
16839 if (chan[idx].freq == 0)
16840 break;
16841
16842 }
16843 }
16844
16845 EXIT();
16846}
16847
16848/**
16849 * wlan_hdd_init_chan_info() - init chan info in hdd context
16850 * @hdd_ctx: HDD context pointer
16851 *
16852 * Return: none
16853 */
16854void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16855{
16856 uint8_t num_2g, num_5g, index = 0;
16857
16858 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16859 hdd_info("SNR monitoring is disabled");
16860 return;
16861 }
16862
16863 hdd_ctx->chan_info =
16864 qdf_mem_malloc(sizeof(struct scan_chan_info)
16865 * QDF_MAX_NUM_CHAN);
16866 if (hdd_ctx->chan_info == NULL) {
16867 hdd_err("Failed to malloc for chan info");
16868 return;
16869 }
16870 mutex_init(&hdd_ctx->chan_info_lock);
16871
16872 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16873 for (; index < num_2g; index++) {
16874 hdd_ctx->chan_info[index].freq =
16875 hdd_channels_2_4_ghz[index].center_freq;
16876 }
16877
16878 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16879 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016880 if (WLAN_REG_IS_11P_CH(
16881 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016882 continue;
16883 hdd_ctx->chan_info[index].freq =
16884 hdd_channels_5_ghz[index - num_2g].center_freq;
16885 }
16886 sme_set_chan_info_callback(hdd_ctx->hHal,
16887 &wlan_hdd_chan_info_cb);
16888}
16889
16890/**
16891 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16892 * @hdd_ctx: hdd context pointer
16893 *
16894 * Return: none
16895 */
16896void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16897{
16898 struct scan_chan_info *chan;
16899
16900 chan = hdd_ctx->chan_info;
16901 hdd_ctx->chan_info = NULL;
16902 if (chan)
16903 qdf_mem_free(chan);
16904}
16905
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016906/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016907 * struct cfg80211_ops - cfg80211_ops
16908 *
16909 * @add_virtual_intf: Add virtual interface
16910 * @del_virtual_intf: Delete virtual interface
16911 * @change_virtual_intf: Change virtual interface
16912 * @change_station: Change station
16913 * @add_beacon: Add beacon in sap mode
16914 * @del_beacon: Delete beacon in sap mode
16915 * @set_beacon: Set beacon in sap mode
16916 * @start_ap: Start ap
16917 * @change_beacon: Change beacon
16918 * @stop_ap: Stop ap
16919 * @change_bss: Change bss
16920 * @add_key: Add key
16921 * @get_key: Get key
16922 * @del_key: Delete key
16923 * @set_default_key: Set default key
16924 * @set_channel: Set channel
16925 * @scan: Scan
16926 * @connect: Connect
16927 * @disconnect: Disconnect
16928 * @join_ibss = Join ibss
16929 * @leave_ibss = Leave ibss
16930 * @set_wiphy_params = Set wiphy params
16931 * @set_tx_power = Set tx power
16932 * @get_tx_power = get tx power
16933 * @remain_on_channel = Remain on channel
16934 * @cancel_remain_on_channel = Cancel remain on channel
16935 * @mgmt_tx = Tx management frame
16936 * @mgmt_tx_cancel_wait = Cancel management tx wait
16937 * @set_default_mgmt_key = Set default management key
16938 * @set_txq_params = Set tx queue parameters
16939 * @get_station = Get station
16940 * @set_power_mgmt = Set power management
16941 * @del_station = Delete station
16942 * @add_station = Add station
16943 * @set_pmksa = Set pmksa
16944 * @del_pmksa = Delete pmksa
16945 * @flush_pmksa = Flush pmksa
16946 * @update_ft_ies = Update FT IEs
16947 * @tdls_mgmt = Tdls management
16948 * @tdls_oper = Tdls operation
16949 * @set_rekey_data = Set rekey data
16950 * @sched_scan_start = Scheduled scan start
16951 * @sched_scan_stop = Scheduled scan stop
16952 * @resume = Resume wlan
16953 * @suspend = Suspend wlan
16954 * @set_mac_acl = Set mac acl
16955 * @testmode_cmd = Test mode command
16956 * @set_ap_chanwidth = Set AP channel bandwidth
16957 * @dump_survey = Dump survey
16958 * @key_mgmt_set_pmk = Set pmk key management
16959 */
16960static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16961 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16962 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16963 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16964 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016965 .start_ap = wlan_hdd_cfg80211_start_ap,
16966 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16967 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016968 .change_bss = wlan_hdd_cfg80211_change_bss,
16969 .add_key = wlan_hdd_cfg80211_add_key,
16970 .get_key = wlan_hdd_cfg80211_get_key,
16971 .del_key = wlan_hdd_cfg80211_del_key,
16972 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16973 .scan = wlan_hdd_cfg80211_scan,
16974 .connect = wlan_hdd_cfg80211_connect,
16975 .disconnect = wlan_hdd_cfg80211_disconnect,
16976 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16977 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16978 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16979 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16980 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16981 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16982 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16983 .mgmt_tx = wlan_hdd_mgmt_tx,
16984 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16985 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16986 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016987 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016988 .get_station = wlan_hdd_cfg80211_get_station,
16989 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16990 .del_station = wlan_hdd_cfg80211_del_station,
16991 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016992 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16993 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16994 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016995#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016996 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16997#endif
16998#ifdef FEATURE_WLAN_TDLS
16999 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17000 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17001#endif
17002#ifdef WLAN_FEATURE_GTK_OFFLOAD
17003 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17004#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17005#ifdef FEATURE_WLAN_SCAN_PNO
17006 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17007 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17008#endif /*FEATURE_WLAN_SCAN_PNO */
17009 .resume = wlan_hdd_cfg80211_resume_wlan,
17010 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17011 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17012#ifdef WLAN_NL80211_TESTMODE
17013 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17014#endif
17015#ifdef QCA_HT_2040_COEX
17016 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17017#endif
17018 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017019#ifdef CHANNEL_SWITCH_SUPPORTED
17020 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17021#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017022 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017023#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17024 defined(CFG80211_ABORT_SCAN)
17025 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17026#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017027};