blob: 42a81f38afd17ae75ebbbaac62c61d0b7e6e51b0 [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 },
981#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
982 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
987 },
988 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
989 .vendor_id = QCA_NL80211_VENDOR_ID,
990 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
991 },
992#ifdef WLAN_FEATURE_ROAM_OFFLOAD
993 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
994 .vendor_id =
995 QCA_NL80211_VENDOR_ID,
996 .subcmd =
997 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
998 },
999#endif
1000 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1001 .vendor_id =
1002 QCA_NL80211_VENDOR_ID,
1003 .subcmd =
1004 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1005 },
1006 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1007 .vendor_id =
1008 QCA_NL80211_VENDOR_ID,
1009 .subcmd =
1010 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1011 },
1012 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1013 .vendor_id =
1014 QCA_NL80211_VENDOR_ID,
1015 .subcmd =
1016 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1017 },
1018 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1019 .vendor_id =
1020 QCA_NL80211_VENDOR_ID,
1021 .subcmd =
1022 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1023 },
1024 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1025 .vendor_id =
1026 QCA_NL80211_VENDOR_ID,
1027 .subcmd =
1028 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1029 },
1030#ifdef FEATURE_WLAN_EXTSCAN
1031 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1032 .vendor_id = QCA_NL80211_VENDOR_ID,
1033 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1034 },
1035 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1038 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1042 },
1043#endif /* FEATURE_WLAN_EXTSCAN */
1044 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1047 },
1048#ifdef WLAN_FEATURE_MEMDUMP
1049 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1050 .vendor_id = QCA_NL80211_VENDOR_ID,
1051 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1052 },
1053#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001054#ifdef WLAN_FEATURE_TSF
1055 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1058 },
1059#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1061 .vendor_id = QCA_NL80211_VENDOR_ID,
1062 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1063 },
1064 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1067 },
1068 /* OCB events */
1069 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1072 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001073#ifdef FEATURE_LFR_SUBNET_DETECTION
1074 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1075 .vendor_id = QCA_NL80211_VENDOR_ID,
1076 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1077 },
1078#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001079
1080#ifdef WLAN_FEATURE_NAN_DATAPATH
1081 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1082 .vendor_id = QCA_NL80211_VENDOR_ID,
1083 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1084 },
1085#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001086
1087 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1090 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301091 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1092 .vendor_id = QCA_NL80211_VENDOR_ID,
1093 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1094 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301095 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1098 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001099#ifdef WLAN_UMAC_CONVERGENCE
1100 COMMON_VENDOR_EVENTS
1101#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102};
1103
1104/**
1105 * __is_driver_dfs_capable() - get driver DFS capability
1106 * @wiphy: pointer to wireless wiphy structure.
1107 * @wdev: pointer to wireless_dev structure.
1108 * @data: Pointer to the data to be passed via vendor interface
1109 * @data_len:Length of the data to be passed
1110 *
1111 * This function is called by userspace to indicate whether or not
1112 * the driver supports DFS offload.
1113 *
1114 * Return: 0 on success, negative errno on failure
1115 */
1116static int __is_driver_dfs_capable(struct wiphy *wiphy,
1117 struct wireless_dev *wdev,
1118 const void *data,
1119 int data_len)
1120{
1121 u32 dfs_capability = 0;
1122 struct sk_buff *temp_skbuff;
1123 int ret_val;
1124 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1125
Jeff Johnson1f61b612016-02-12 16:28:33 -08001126 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001127
1128 ret_val = wlan_hdd_validate_context(hdd_ctx);
1129 if (ret_val)
1130 return ret_val;
1131
Anurag Chouhan6d760662016-02-20 16:05:43 +05301132 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001133 hdd_err("Command not allowed in FTM mode");
1134 return -EPERM;
1135 }
1136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138
1139 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1140 NLMSG_HDRLEN);
1141
1142 if (temp_skbuff != NULL) {
1143 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1144 dfs_capability);
1145 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001146 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147 kfree_skb(temp_skbuff);
1148
1149 return ret_val;
1150 }
1151
1152 return cfg80211_vendor_cmd_reply(temp_skbuff);
1153 }
1154
Jeff Johnson020db452016-06-29 14:37:26 -07001155 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 return -ENOMEM;
1157}
1158
1159/**
1160 * is_driver_dfs_capable() - get driver DFS capability
1161 * @wiphy: pointer to wireless wiphy structure.
1162 * @wdev: pointer to wireless_dev structure.
1163 * @data: Pointer to the data to be passed via vendor interface
1164 * @data_len:Length of the data to be passed
1165 *
1166 * This function is called by userspace to indicate whether or not
1167 * the driver supports DFS offload. This is an SSR-protected
1168 * wrapper function.
1169 *
1170 * Return: 0 on success, negative errno on failure
1171 */
1172static int is_driver_dfs_capable(struct wiphy *wiphy,
1173 struct wireless_dev *wdev,
1174 const void *data,
1175 int data_len)
1176{
1177 int ret;
1178
1179 cds_ssr_protect(__func__);
1180 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1181 cds_ssr_unprotect(__func__);
1182
1183 return ret;
1184}
1185
1186/**
1187 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1188 *
1189 * @adapter: SAP adapter pointer
1190 *
1191 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1192 * radio. So in case of DFS MCC scenario override current SAP given config
1193 * to follow concurrent SAP DFS config
1194 *
1195 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1196 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001197int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1198{
1199 hdd_adapter_t *con_sap_adapter;
1200 tsap_Config_t *sap_config, *con_sap_config;
1201 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001202 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001204 if (!hdd_ctx) {
1205 hdd_err("hdd context is NULL");
1206 return 0;
1207 }
1208
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209 /*
1210 * Check if AP+AP case, once primary AP chooses a DFS
1211 * channel secondary AP should always follow primary APs channel
1212 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001213 if (!policy_mgr_concurrent_beaconing_sessions_running(
1214 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 return 0;
1216
1217 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1218 if (!con_sap_adapter)
1219 return 0;
1220
1221 sap_config = &adapter->sessionCtx.ap.sapConfig;
1222 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1223 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1224
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001225 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226 return 0;
1227
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001228 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001230 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 sap_config->channel = con_ch;
1232
1233 if (con_sap_config->acs_cfg.acs_mode == true) {
1234 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1235 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001236 hdd_err("Primary AP channel config error");
1237 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 con_ch, con_sap_config->acs_cfg.pri_ch,
1239 con_sap_config->acs_cfg.ht_sec_ch);
1240 return -EINVAL;
1241 }
1242 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1243 * MCC restriction. So free ch list allocated in do_acs
1244 * func for Sec AP and realloc for Pri AP ch list size
1245 */
1246 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301247 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250 &con_sap_config->acs_cfg,
1251 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 sizeof(uint8_t) *
1254 con_sap_config->acs_cfg.ch_list_count);
1255 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001256 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 return -ENOMEM;
1258 }
1259
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301260 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 con_sap_config->acs_cfg.ch_list,
1262 con_sap_config->acs_cfg.ch_list_count);
1263
1264 } else {
1265 sap_config->acs_cfg.pri_ch = con_ch;
1266 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1267 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1268 }
1269
1270 return con_ch;
1271}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272
1273/**
1274 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1275 * @sap_cfg: pointer to SAP config struct
1276 *
1277 * This function sets the default ACS start and end channel for the given band
1278 * and also parses the given ACS channel list.
1279 *
1280 * Return: None
1281 */
1282
1283static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1284 bool vht_enabled)
1285{
1286 int i;
1287 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001289 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1290 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001293 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001297 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1298 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001301 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1302 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 }
1304
1305 if (ht_enabled)
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1307
1308 if (vht_enabled)
1309 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1310
1311
1312 /* Parse ACS Chan list from hostapd */
1313 if (!sap_cfg->acs_cfg.ch_list)
1314 return;
1315
1316 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1317 sap_cfg->acs_cfg.end_ch =
1318 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1319 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301320 /* avoid channel as start channel */
1321 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1322 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1324 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1325 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1326 }
1327}
1328
1329
1330static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1331
1332/**
1333 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1334 * @adapter: pointer to SAP adapter struct
1335 *
1336 * This function starts the ACS procedure if there are no
1337 * constraints like MBSSID DFS restrictions.
1338 *
1339 * Return: Status of ACS Start procedure
1340 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301341int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001342{
1343
1344 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1345 tsap_Config_t *sap_config;
1346 tpWLAN_SAPEventCB acs_event_callback;
1347 int status;
1348
1349 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301350 if (hdd_ctx->acs_policy.acs_channel)
1351 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1352 else
1353 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001354
1355 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001356 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001357 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001358
1359 if (status > 0) {
1360 /*notify hostapd about channel override */
1361 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1362 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1363 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 }
Jeff Johnson68755312017-02-10 11:46:55 -08001365
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1367 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001368 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369 return -EINVAL;
1370 }
1371
1372 acs_event_callback = hdd_hostapd_sap_event_cb;
1373
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301374 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301375 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301376 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 acs_event_callback, sap_config, adapter->dev);
1380
1381
1382 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001383 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 return -EINVAL;
1385 }
bings394afdd2017-01-09 11:22:38 +08001386 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1387 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1389
1390 return 0;
1391}
1392
1393/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301394 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1395 * @ap_adapter: AP adapter
1396 * @nol: Non-occupancy list
1397 * @nol_len: Length of NOL
1398 *
1399 * Get the NOL for SAP
1400 *
1401 * Return: Zero on success, non-zero on failure
1402 */
1403static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1404 uint32_t *nol_len)
1405{
1406 QDF_STATUS ret;
1407
1408 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1409 nol, nol_len);
1410 if (QDF_IS_STATUS_ERROR(ret))
1411 return -EINVAL;
1412
1413 return 0;
1414}
1415
1416/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301417 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1418 * @hdd_ctx: hdd context
1419 * @acs_chan_params: external acs channel params
1420 * @sap_config: SAP config
1421 *
1422 * This API provides unsorted pcl list.
1423 * this list is a subset of the valid channel list given by hostapd.
1424 * if channel is not present in pcl, weightage will be given as zero
1425 *
1426 * Return: Zero on success, non-zero on failure
1427 */
1428static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1429 struct hdd_vendor_acs_chan_params *acs_chan_params,
1430 tsap_Config_t *sap_config)
1431{
1432 int i, j;
1433
1434 for (i = 0; i < acs_chan_params->channel_count; i++) {
1435 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1436 if (acs_chan_params->channel_list[i] ==
1437 sap_config->acs_cfg.pcl_channels[j]) {
1438 acs_chan_params->vendor_pcl_list[i] =
1439 sap_config->acs_cfg.pcl_channels[j];
1440 acs_chan_params->vendor_weight_list[i] =
1441 sap_config->acs_cfg.
1442 pcl_channels_weight_list[j];
1443 break;
1444 } else {
1445 acs_chan_params->vendor_pcl_list[i] =
1446 acs_chan_params->channel_list[i];
1447 acs_chan_params->vendor_weight_list[i] = 0;
1448 }
1449 }
1450 }
1451 if (hdd_ctx->unsafe_channel_count == 0)
1452 return;
1453 /* Update unsafe channel weight as zero */
1454 for (i = 0; i < acs_chan_params->channel_count; i++) {
1455 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1456 if (acs_chan_params->channel_list[i] ==
1457 hdd_ctx->unsafe_channel_list[j]) {
1458 acs_chan_params->vendor_weight_list[i] = 0;
1459 }
1460 }
1461 }
1462}
1463
1464/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301465 * hdd_update_reg_chan_info : This API contructs channel info
1466 * for all the given channel
1467 * @adapter: pointer to SAP adapter struct
1468 * @channel_count: channel count
1469 * @channel_list: channel list
1470 *
1471 * Return: Status of of channel information updation
1472 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301473static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301474 uint32_t channel_count,
1475 uint8_t *channel_list)
1476{
1477 int i;
1478 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001479 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301480 uint8_t bw_offset = 0, chan = 0;
1481 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1482 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1483
1484 /* memory allocation */
1485 sap_config->channel_info = qdf_mem_malloc(
1486 sizeof(struct hdd_channel_info) *
1487 channel_count);
1488 if (!sap_config->channel_info) {
1489 hdd_err("memory allocation failed");
1490 return -ENOMEM;
1491
1492 }
1493 for (i = 0; i < channel_count; i++) {
1494 icv = &sap_config->channel_info[i];
1495 chan = channel_list[i];
1496
1497 if (chan == 0)
1498 continue;
1499
1500 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1501 bw_offset = 1 << BW_40_OFFSET_BIT;
1502 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1503 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001504 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301505 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001506 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1507 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301508
1509 /* filling demo values */
1510 icv->max_radio_power = HDD_MAX_TX_POWER;
1511 icv->min_radio_power = HDD_MIN_TX_POWER;
1512 /* not supported in current driver */
1513 icv->max_antenna_gain = 0;
1514
1515 icv->reg_class_id = wlan_hdd_find_opclass(
1516 WLAN_HDD_GET_HAL_CTX(adapter),
1517 chan, bw_offset);
1518
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001519 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301520 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001521 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1522 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301523 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1524 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1525 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001526
Kapil Gupta086c6202016-12-11 18:17:06 +05301527 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001528 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301529 sap_config->acs_cfg.ch_width,
1530 sap_config->acs_cfg.is_ht_enabled,
1531 sap_config->acs_cfg.is_vht_enabled,
1532 hdd_ctx->config->enable_sub_20_channel_width);
1533
1534 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1535 icv->freq, icv->flags,
1536 icv->flagext, icv->ieee_chan_number,
1537 icv->max_reg_power, icv->max_radio_power,
1538 icv->min_radio_power, icv->reg_class_id,
1539 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1540 icv->vht_center_freq_seg1);
1541 }
1542 return 0;
1543}
1544
1545/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1546#define CHAN_INFO_ATTR_FLAGS \
1547 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1548#define CHAN_INFO_ATTR_FLAG_EXT \
1549 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1550#define CHAN_INFO_ATTR_FREQ \
1551 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1552#define CHAN_INFO_ATTR_MAX_REG_POWER \
1553 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1554#define CHAN_INFO_ATTR_MAX_POWER \
1555 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1556#define CHAN_INFO_ATTR_MIN_POWER \
1557 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1558#define CHAN_INFO_ATTR_REG_CLASS_ID \
1559 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1560#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1561 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1562#define CHAN_INFO_ATTR_VHT_SEG_0 \
1563 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1564#define CHAN_INFO_ATTR_VHT_SEG_1 \
1565 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1566
1567/**
1568 * hdd_cfg80211_update_channel_info() - add channel info attributes
1569 * @skb: pointer to sk buff
1570 * @hdd_ctx: pointer to hdd station context
1571 * @idx: attribute index
1572 *
1573 * Return: Success(0) or reason code for failure
1574 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301575static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301576hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1577 tsap_Config_t *sap_config, int idx)
1578{
1579 struct nlattr *nla_attr, *channel;
1580 struct hdd_channel_info *icv;
1581 int i;
1582
1583 nla_attr = nla_nest_start(skb, idx);
1584 if (!nla_attr)
1585 goto fail;
1586
1587 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1588 channel = nla_nest_start(skb, i);
1589 if (!channel)
1590 goto fail;
1591
1592 icv = &sap_config->channel_info[i];
1593 if (!icv) {
1594 hdd_err("channel info not found");
1595 goto fail;
1596 }
1597 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1598 icv->freq) ||
1599 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1600 icv->flags) ||
1601 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1602 icv->flagext) ||
1603 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1604 icv->max_reg_power) ||
1605 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1606 icv->max_radio_power) ||
1607 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1608 icv->min_radio_power) ||
1609 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1610 icv->reg_class_id) ||
1611 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1612 icv->max_antenna_gain) ||
1613 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1614 icv->vht_center_freq_seg0) ||
1615 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1616 icv->vht_center_freq_seg1)) {
1617 hdd_err("put fail");
1618 goto fail;
1619 }
1620 nla_nest_end(skb, channel);
1621 }
1622 nla_nest_end(skb, nla_attr);
1623 return 0;
1624fail:
1625 hdd_err("nl channel update failed");
1626 return -EINVAL;
1627}
1628#undef CHAN_INFO_ATTR_FLAGS
1629#undef CHAN_INFO_ATTR_FLAG_EXT
1630#undef CHAN_INFO_ATTR_FREQ
1631#undef CHAN_INFO_ATTR_MAX_REG_POWER
1632#undef CHAN_INFO_ATTR_MAX_POWER
1633#undef CHAN_INFO_ATTR_MIN_POWER
1634#undef CHAN_INFO_ATTR_REG_CLASS_ID
1635#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1636#undef CHAN_INFO_ATTR_VHT_SEG_0
1637#undef CHAN_INFO_ATTR_VHT_SEG_1
1638
1639/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301640 * hdd_cfg80211_update_pcl() - add pcl info attributes
1641 * @skb: pointer to sk buff
1642 * @hdd_ctx: pointer to hdd station context
1643 * @idx: attribute index
1644 * @vendor_pcl_list: PCL list
1645 * @vendor_weight_list: PCL weights
1646 *
1647 * Return: Success(0) or reason code for failure
1648 */
1649static int32_t
1650hdd_cfg80211_update_pcl(struct sk_buff *skb,
1651 uint8_t ch_list_count, int idx,
1652 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1653{
1654 struct nlattr *nla_attr, *channel;
1655 int i;
1656
1657 nla_attr = nla_nest_start(skb, idx);
1658
1659 if (!nla_attr)
1660 goto fail;
1661
1662 for (i = 0; i < ch_list_count; i++) {
1663 channel = nla_nest_start(skb, i);
1664 if (!channel)
1665 goto fail;
1666 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1667 vendor_pcl_list[i]) ||
1668 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1669 vendor_weight_list[i])) {
1670 hdd_err("put fail");
1671 goto fail;
1672 }
1673 nla_nest_end(skb, channel);
1674 }
1675 nla_nest_end(skb, nla_attr);
1676
1677 return 0;
1678fail:
1679 hdd_err("updating pcl list failed");
1680 return -EINVAL;
1681}
1682
1683static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1684{
1685 /* Get scan band */
1686 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1687 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1688 *band = eCSR_BAND_24;
1689 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1690 *band = eCSR_BAND_5G;
1691 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1692 *band = eCSR_BAND_ALL;
1693 }
1694 /* Auto is not supported currently */
1695 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1696 hdd_err("invalid band");
1697 *band = eCSR_BAND_24;
1698 }
1699}
1700
1701void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1702 uint8_t reason)
1703{
1704 struct sk_buff *skb;
1705 tsap_Config_t *sap_config;
1706 uint32_t channel_count = 0, status;
1707 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1708 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1709 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1710 struct hdd_vendor_acs_chan_params acs_chan_params;
1711 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1712 eCsrBand band = eCSR_BAND_24;
1713 eCsrPhyMode phy_mode;
1714
1715 if (!hdd_ctx) {
1716 hdd_err("HDD context is NULL");
1717 return;
1718 }
1719
1720 ENTER();
1721 sap_config = &adapter->sessionCtx.ap.sapConfig;
1722
1723 /* Get valid channels for SAP */
1724 wlan_hdd_sap_get_valid_channellist(adapter,
1725 &channel_count, channel_list);
1726
1727 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1728 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1729 /* Get phymode */
1730 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1731
1732 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1733 &(adapter->wdev),
1734 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1735 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1736 GFP_KERNEL);
1737
1738 if (!skb) {
1739 hdd_err("cfg80211_vendor_event_alloc failed");
1740 return;
1741 }
1742 /*
1743 * Application expects pcl to be a subset of channel list
1744 * Remove all channels which are not in channel list from pcl
1745 * and add weight as zero
1746 */
1747 acs_chan_params.channel_count = channel_count;
1748 acs_chan_params.channel_list = channel_list;
1749 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1750 acs_chan_params.vendor_weight_list = vendor_weight_list;
1751
1752 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1753 sap_config);
1754 /* Update values in NL buffer */
1755 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1756 reason) ||
1757 nla_put_u8(skb,
1758 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1759 false) ||
1760 nla_put_u8(skb,
1761 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1762 true) ||
1763 nla_put_u8(skb,
1764 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1765 true) ||
1766 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1767 sap_config->acs_cfg.ch_width) ||
1768 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1769 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1770 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1771 band) ||
1772 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1773 phy_mode) ||
1774 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1775 channel_count, channel_list)) {
1776 hdd_err("nla put fail");
1777 goto fail;
1778 }
1779 status = hdd_cfg80211_update_pcl(skb, channel_count,
1780 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1781 vendor_pcl_list, vendor_weight_list);
1782
1783 if (status != 0)
1784 goto fail;
1785
1786 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1787 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1788
1789 if (status != 0)
1790 goto fail;
1791
1792 cfg80211_vendor_event(skb, GFP_KERNEL);
1793 return;
1794fail:
1795 if (skb)
1796 kfree_skb(skb);
1797}
1798
1799static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1800{
1801 struct hdd_external_acs_timer_context *timer_context;
1802
1803 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1804 return 0;
1805
1806 hdd_notice("Starting vendor app based ACS");
1807 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1808 timer_context->adapter = adapter;
1809
1810 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1811 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1812 QDF_TIMER_TYPE_SW,
1813 hdd_acs_response_timeout_handler, timer_context);
1814 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1815 return 0;
1816}
1817
1818/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1820 * @wiphy: Linux wiphy struct pointer
1821 * @wdev: Linux wireless device struct pointer
1822 * @data: ACS information from hostapd
1823 * @data_len: ACS information length
1824 *
1825 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1826 * and starts ACS procedure.
1827 *
1828 * Return: ACS procedure start status
1829 */
1830
1831static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1832 struct wireless_dev *wdev,
1833 const void *data, int data_len)
1834{
1835 struct net_device *ndev = wdev->netdev;
1836 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1837 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1838 tsap_Config_t *sap_config;
1839 struct sk_buff *temp_skbuff;
1840 int status = -EINVAL, i = 0;
1841 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1842 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301843 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001844
1845 /* ***Note*** Donot set SME config related to ACS operation here because
1846 * ACS operation is not synchronouse and ACS for Second AP may come when
1847 * ACS operation for first AP is going on. So only do_acs is split to
1848 * seperate start_acs routine. Also SME-PMAC struct that is used to
1849 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1850 * config shall be set only from start_acs.
1851 */
1852
1853 /* nla_policy Policy template. Policy not applied as some attributes are
1854 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1855 *
1856 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1857 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1858 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1859 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1860 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1861 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1862 */
1863
Jeff Johnson1f61b612016-02-12 16:28:33 -08001864 ENTER_DEV(ndev);
1865
Anurag Chouhan6d760662016-02-20 16:05:43 +05301866 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 hdd_err("Command not allowed in FTM mode");
1868 return -EPERM;
1869 }
1870
Kapil Gupta8878ad92017-02-13 11:56:04 +05301871 if (hdd_ctx->config->force_sap_acs &&
1872 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001873 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 return -EPERM;
1875 }
1876
1877 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301878 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301880
Naveen Rawat64e477e2016-05-20 10:34:56 -07001881 if (cds_is_sub_20_mhz_enabled()) {
1882 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1883 status = -EINVAL;
1884 goto out;
1885 }
1886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301888 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889
1890 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1891 NULL);
1892 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001893 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 goto out;
1895 }
1896
1897 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001898 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 goto out;
1900 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301901 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1902 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903
1904 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1905 ht_enabled =
1906 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1907 else
1908 ht_enabled = 0;
1909
1910 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1911 ht40_enabled =
1912 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1913 else
1914 ht40_enabled = 0;
1915
1916 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1917 vht_enabled =
1918 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1919 else
1920 vht_enabled = 0;
1921
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301922 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1923 vht_enabled = 0;
1924 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1925 }
1926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1928 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1929 } else {
1930 if (ht_enabled && ht40_enabled)
1931 ch_width = 40;
1932 else
1933 ch_width = 20;
1934 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301935
1936 /* this may be possible, when sap_force_11n_for_11ac is set */
1937 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1938 if (ht_enabled && ht40_enabled)
1939 ch_width = 40;
1940 else
1941 ch_width = 20;
1942 }
1943
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001944 if (ch_width == 80)
1945 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1946 else if (ch_width == 40)
1947 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1948 else
1949 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1950
1951 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1952 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1953 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1954 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1955 * since it contains the frequency values of the channels in
1956 * the channel list.
1957 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1958 * is present
1959 */
1960 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1961 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1962 sap_config->acs_cfg.ch_list_count = nla_len(
1963 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1964 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301965 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 sizeof(uint8_t) *
1967 sap_config->acs_cfg.ch_list_count);
1968 if (sap_config->acs_cfg.ch_list == NULL)
1969 goto out;
1970
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301971 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 sap_config->acs_cfg.ch_list_count);
1973 }
1974 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1975 uint32_t *freq =
1976 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1977 sap_config->acs_cfg.ch_list_count = nla_len(
1978 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1979 sizeof(uint32_t);
1980 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301981 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 sap_config->acs_cfg.ch_list_count);
1983 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001984 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 status = -ENOMEM;
1986 goto out;
1987 }
1988
1989 /* convert frequency to channel */
1990 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1991 sap_config->acs_cfg.ch_list[i] =
1992 ieee80211_frequency_to_channel(freq[i]);
1993 }
1994 }
1995
1996 hdd_debug("get pcl for DO_ACS vendor command");
1997
1998 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001999 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302000 sap_config->acs_cfg.pcl_channels,
2001 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302002 sap_config->acs_cfg.pcl_channels_weight_list,
2003 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302004 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002005 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302008 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2009 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002010 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 vht_enabled = 1;
2012 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2013 sap_config->acs_cfg.ch_width =
2014 hdd_ctx->config->vhtChannelWidth;
2015 /* No VHT80 in 2.4G so perform ACS accordingly */
2016 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302017 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302019 ch_width = 40;
2020 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 }
2022
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302023 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2024
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002025 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 -08002026 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2027 ch_width, ht_enabled, vht_enabled,
2028 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2029
Kapil Gupta8878ad92017-02-13 11:56:04 +05302030 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2031 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2032
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002034 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035 sap_config->acs_cfg.ch_list_count);
2036 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002037 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 }
2039 sap_config->acs_cfg.acs_mode = true;
2040 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002041 /* ***Note*** Completion variable usage is not allowed
2042 * here since ACS scan operation may take max 2.2 sec
2043 * for 5G band:
2044 * 9 Active channel X 40 ms active scan time +
2045 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2047 * for this long. So we split up the scanning part.
2048 */
2049 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002050 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 status = 0;
2052 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302053 /* Check if vendor specific acs is enabled */
2054 if (hdd_ctx->config->vendor_acs_support) {
2055 sap_config->acs_cfg.hw_mode = hw_mode;
2056 hdd_create_acs_timer(adapter);
2057 hdd_update_acs_timer_reason(adapter,
2058 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2059 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2060 wlan_sap_set_vendor_acs(
2061 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2062 true);
2063 else
2064 wlan_sap_set_vendor_acs(
2065 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2066 false);
2067
2068 } else
2069 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 }
2071
2072out:
2073 if (0 == status) {
2074 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2075 NLMSG_HDRLEN);
2076 if (temp_skbuff != NULL)
2077 return cfg80211_vendor_cmd_reply(temp_skbuff);
2078 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002079 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002080 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2081
2082 return status;
2083}
2084
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002085/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2087 * @wiphy: Linux wiphy struct pointer
2088 * @wdev: Linux wireless device struct pointer
2089 * @data: ACS information from hostapd
2090 * @data_len: ACS information len
2091 *
2092 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2093 * and starts ACS procedure.
2094 *
2095 * Return: ACS procedure start status
2096 */
2097
2098static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2099 struct wireless_dev *wdev,
2100 const void *data, int data_len)
2101{
2102 int ret;
2103
2104 cds_ssr_protect(__func__);
2105 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2106 cds_ssr_unprotect(__func__);
2107
2108 return ret;
2109}
2110
2111/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002112 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2113 * @adapter: Pointer to adapter struct
2114 *
2115 * This function handle cleanup of what was done in DO_ACS, including free
2116 * memory.
2117 *
2118 * Return: void
2119 */
2120
2121void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2122{
2123 if (adapter == NULL)
2124 return;
2125 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2126 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2127 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2128 }
2129}
2130
2131/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002132 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2133 * @work: Linux workqueue struct pointer for ACS work
2134 *
2135 * This function starts the ACS procedure which was marked pending when an ACS
2136 * procedure was in progress for a concurrent SAP interface.
2137 *
2138 * Return: None
2139 */
2140
2141static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2142{
2143 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2144 acs_pending_work.work);
2145 wlan_hdd_cfg80211_start_acs(adapter);
2146}
2147
2148/**
2149 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2150 * @adapter: Pointer to SAP adapter struct
2151 * @pri_channel: SAP ACS procedure selected Primary channel
2152 * @sec_channel: SAP ACS procedure selected secondary channel
2153 *
2154 * This is a callback function from SAP module on ACS procedure is completed.
2155 * This function send the ACS selected channel information to hostapd
2156 *
2157 * Return: None
2158 */
2159
2160void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2161{
2162 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2163 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2164 struct sk_buff *vendor_event;
2165 int ret_val;
2166 hdd_adapter_t *con_sap_adapter;
2167 uint16_t ch_width;
2168
2169 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002170 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2172 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2173 GFP_KERNEL);
2174
2175 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002176 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177 return;
2178 }
2179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002180 ret_val = nla_put_u8(vendor_event,
2181 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2182 sap_cfg->acs_cfg.pri_ch);
2183 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002184 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 kfree_skb(vendor_event);
2186 return;
2187 }
2188
2189 ret_val = nla_put_u8(vendor_event,
2190 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2191 sap_cfg->acs_cfg.ht_sec_ch);
2192 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002193 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 kfree_skb(vendor_event);
2195 return;
2196 }
2197
2198 ret_val = nla_put_u8(vendor_event,
2199 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2200 sap_cfg->acs_cfg.vht_seg0_center_ch);
2201 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002202 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 kfree_skb(vendor_event);
2204 return;
2205 }
2206
2207 ret_val = nla_put_u8(vendor_event,
2208 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2209 sap_cfg->acs_cfg.vht_seg1_center_ch);
2210 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002211 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 kfree_skb(vendor_event);
2213 return;
2214 }
2215
2216 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2217 ch_width = 80;
2218 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2219 ch_width = 40;
2220 else
2221 ch_width = 20;
2222
2223 ret_val = nla_put_u16(vendor_event,
2224 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2225 ch_width);
2226 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002227 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228 kfree_skb(vendor_event);
2229 return;
2230 }
2231 if (sap_cfg->acs_cfg.pri_ch > 14)
2232 ret_val = nla_put_u8(vendor_event,
2233 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2234 QCA_ACS_MODE_IEEE80211A);
2235 else
2236 ret_val = nla_put_u8(vendor_event,
2237 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2238 QCA_ACS_MODE_IEEE80211G);
2239
2240 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002241 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002242 kfree_skb(vendor_event);
2243 return;
2244 }
2245
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002246 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 -08002247 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2248 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2249 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2250
2251 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2252 /* ***Note*** As already mentioned Completion variable usage is not
2253 * allowed here since ACS scan operation may take max 2.2 sec.
2254 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2255 * operation.
2256 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2257 * when Primary AP ACS is complete and secondary AP ACS is started here
2258 * immediately, Primary AP start_bss may come inbetween ACS operation
2259 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2260 * delay. This path and below constraint will be removed on sessionizing
2261 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2262 * As per design constraint user space control application must take
2263 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2264 * this code path. Sec AP hostapd should be started after Primary AP
2265 * start beaconing which can be confirmed by getchannel iwpriv command
2266 */
2267
2268 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2269 if (con_sap_adapter &&
2270 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002271 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2272 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002273 /* Lets give 500ms for OBSS + START_BSS to complete */
2274 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2275 msecs_to_jiffies(500));
2276 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2277 }
2278
2279 return;
2280}
2281
2282static int
2283__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2284 struct wireless_dev *wdev,
2285 const void *data,
2286 int data_len)
2287{
2288 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2289 struct sk_buff *skb = NULL;
2290 uint32_t fset = 0;
2291 int ret;
2292
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002293 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302294
Anurag Chouhan6d760662016-02-20 16:05:43 +05302295 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002296 hdd_err("Command not allowed in FTM mode");
2297 return -EPERM;
2298 }
2299
2300 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302301 if (ret)
2302 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303
2304 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002305 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002306 fset |= WIFI_FEATURE_INFRA;
2307 }
2308 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002309 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310 fset |= WIFI_FEATURE_INFRA_5G;
2311 }
2312#ifdef WLAN_FEATURE_P2P
2313 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2314 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002315 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316 fset |= WIFI_FEATURE_P2P;
2317 }
2318#endif
2319 fset |= WIFI_FEATURE_SOFT_AP;
2320
2321 /* HOTSPOT is a supplicant feature, enable it by default */
2322 fset |= WIFI_FEATURE_HOTSPOT;
2323
2324#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302325 if (pHddCtx->config->extscan_enabled &&
2326 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002327 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2329 }
2330#endif
2331 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002332 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 fset |= WIFI_FEATURE_NAN;
2334 }
2335 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002336 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 fset |= WIFI_FEATURE_D2D_RTT;
2338 fset |= WIFI_FEATURE_D2AP_RTT;
2339 }
2340#ifdef FEATURE_WLAN_SCAN_PNO
2341 if (pHddCtx->config->configPNOScanSupport &&
2342 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002343 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 fset |= WIFI_FEATURE_PNO;
2345 }
2346#endif
2347 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2348#ifdef FEATURE_WLAN_TDLS
2349 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2350 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002351 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002352 fset |= WIFI_FEATURE_TDLS;
2353 }
2354 if (sme_is_feature_supported_by_fw(TDLS) &&
2355 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2356 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002357 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002358 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2359 }
2360#endif
2361#ifdef WLAN_AP_STA_CONCURRENCY
2362 fset |= WIFI_FEATURE_AP_STA;
2363#endif
2364 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002365 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366
2367 if (hdd_link_layer_stats_supported())
2368 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2369
2370 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2371 NLMSG_HDRLEN);
2372 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002373 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 return -EINVAL;
2375 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002376 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002378 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 goto nla_put_failure;
2380 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302381 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302382 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383nla_put_failure:
2384 kfree_skb(skb);
2385 return -EINVAL;
2386}
2387
2388/**
2389 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2390 * @wiphy: pointer to wireless wiphy structure.
2391 * @wdev: pointer to wireless_dev structure.
2392 * @data: Pointer to the data to be passed via vendor interface
2393 * @data_len:Length of the data to be passed
2394 *
2395 * Return: Return the Success or Failure code.
2396 */
2397static int
2398wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2399 struct wireless_dev *wdev,
2400 const void *data, int data_len)
2401{
2402 int ret = 0;
2403
2404 cds_ssr_protect(__func__);
2405 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2406 data, data_len);
2407 cds_ssr_unprotect(__func__);
2408
2409 return ret;
2410}
2411
2412/**
2413 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2414 * @wiphy: pointer to wireless wiphy structure.
2415 * @wdev: pointer to wireless_dev structure.
2416 * @data: Pointer to the data to be passed via vendor interface
2417 * @data_len:Length of the data to be passed
2418 *
2419 * Set the MAC address that is to be used for scanning.
2420 *
2421 * Return: Return the Success or Failure code.
2422 */
2423static int
2424__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2425 struct wireless_dev *wdev,
2426 const void *data,
2427 int data_len)
2428{
2429 tpSirScanMacOui pReqMsg = NULL;
2430 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2431 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302432 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 int ret;
2434
Jeff Johnson1f61b612016-02-12 16:28:33 -08002435 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436
Anurag Chouhan6d760662016-02-20 16:05:43 +05302437 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 hdd_err("Command not allowed in FTM mode");
2439 return -EPERM;
2440 }
2441
2442 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302443 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445
2446 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002447 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448 return -ENOTSUPP;
2449 }
2450
2451 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2452 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 return -EINVAL;
2455 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302456 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002458 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 return -ENOMEM;
2460 }
2461 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002462 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 goto fail;
2464 }
2465 nla_memcpy(&pReqMsg->oui[0],
2466 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2467 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002468 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 pReqMsg->oui[1], pReqMsg->oui[2]);
2470 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302471 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002472 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 goto fail;
2474 }
2475 return 0;
2476fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302477 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 return -EINVAL;
2479}
2480
2481/**
2482 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2483 * @wiphy: pointer to wireless wiphy structure.
2484 * @wdev: pointer to wireless_dev structure.
2485 * @data: Pointer to the data to be passed via vendor interface
2486 * @data_len:Length of the data to be passed
2487 *
2488 * Set the MAC address that is to be used for scanning. This is an
2489 * SSR-protecting wrapper function.
2490 *
2491 * Return: Return the Success or Failure code.
2492 */
2493static int
2494wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2495 struct wireless_dev *wdev,
2496 const void *data,
2497 int data_len)
2498{
2499 int ret;
2500
2501 cds_ssr_protect(__func__);
2502 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2503 data, data_len);
2504 cds_ssr_unprotect(__func__);
2505
2506 return ret;
2507}
2508
2509/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302510 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2511 * @wiphy: pointer phy adapter
2512 * @wdev: pointer to wireless device structure
2513 * @data: pointer to data buffer
2514 * @data_len: length of data
2515 *
2516 * This routine will give concurrency matrix
2517 *
2518 * Return: int status code
2519 */
2520static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2521 struct wireless_dev *wdev,
2522 const void *data,
2523 int data_len)
2524{
2525 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2526 uint8_t i, feature_sets, max_feature_sets;
2527 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2528 struct sk_buff *reply_skb;
2529 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2530 int ret;
2531
2532 ENTER_DEV(wdev->netdev);
2533
2534 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2535 hdd_err("Command not allowed in FTM mode");
2536 return -EPERM;
2537 }
2538
2539 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302540 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302541 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302542
2543 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2544 data, data_len, NULL)) {
2545 hdd_err("Invalid ATTR");
2546 return -EINVAL;
2547 }
2548
2549 /* Parse and fetch max feature set */
2550 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2551 hdd_err("Attr max feature set size failed");
2552 return -EINVAL;
2553 }
2554 max_feature_sets = nla_get_u32(tb[
2555 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002556 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302557
2558 /* Fill feature combination matrix */
2559 feature_sets = 0;
2560 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002561 WIFI_FEATURE_P2P;
2562 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2563 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302564 /* Add more feature combinations here */
2565
2566 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002567 hdd_debug("Number of feature sets: %d", feature_sets);
2568 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302569 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002570 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302571
2572 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2573 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2574 if (!reply_skb) {
2575 hdd_err("Feature set matrix: buffer alloc fail");
2576 return -ENOMEM;
2577 }
2578
2579 if (nla_put_u32(reply_skb,
2580 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2581 feature_sets) ||
2582 nla_put(reply_skb,
2583 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2584 sizeof(u32) * feature_sets,
2585 feature_set_matrix)) {
2586 hdd_err("nla put fail");
2587 kfree_skb(reply_skb);
2588 return -EINVAL;
2589 }
2590 return cfg80211_vendor_cmd_reply(reply_skb);
2591}
2592
2593/**
2594 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2595 * @wiphy: pointer to wireless wiphy structure.
2596 * @wdev: pointer to wireless_dev structure.
2597 * @data: Pointer to the data to be passed via vendor interface
2598 * @data_len:Length of the data to be passed
2599 *
2600 * Retrieves the concurrency feature set matrix
2601 *
2602 * Return: 0 on success, negative errno on failure
2603 */
2604static int
2605wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2606 struct wireless_dev *wdev,
2607 const void *data,
2608 int data_len)
2609{
2610 int ret;
2611
2612 cds_ssr_protect(__func__);
2613 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2614 data, data_len);
2615 cds_ssr_unprotect(__func__);
2616
2617 return ret;
2618}
2619
2620/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002621 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2622 * @feature_flags: pointer to the byte array of features.
2623 * @feature: Feature to be turned ON in the byte array.
2624 *
2625 * Return: None
2626 *
2627 * This is called to turn ON or SET the feature flag for the requested feature.
2628 **/
2629#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002630static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2631 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002632{
2633 uint32_t index;
2634 uint8_t bit_mask;
2635
2636 index = feature / NUM_BITS_IN_BYTE;
2637 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2638 feature_flags[index] |= bit_mask;
2639}
2640
2641/**
2642 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2643 * @wiphy: pointer to wireless wiphy structure.
2644 * @wdev: pointer to wireless_dev structure.
2645 * @data: Pointer to the data to be passed via vendor interface
2646 * @data_len:Length of the data to be passed
2647 *
2648 * This is called when wlan driver needs to send supported feature set to
2649 * supplicant upon a request/query from the supplicant.
2650 *
2651 * Return: Return the Success or Failure code.
2652 **/
2653#define MAX_CONCURRENT_CHAN_ON_24G 2
2654#define MAX_CONCURRENT_CHAN_ON_5G 2
2655static int
2656__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2657 struct wireless_dev *wdev,
2658 const void *data, int data_len)
2659{
2660 struct sk_buff *skb = NULL;
2661 uint32_t dbs_capability = 0;
2662 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302663 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 int ret_val;
2665
2666 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2667 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2668
Jeff Johnson1f61b612016-02-12 16:28:33 -08002669 ENTER_DEV(wdev->netdev);
2670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2672 if (ret_val)
2673 return ret_val;
2674
Anurag Chouhan6d760662016-02-20 16:05:43 +05302675 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 hdd_err("Command not allowed in FTM mode");
2677 return -EPERM;
2678 }
2679
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002680 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002681 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 wlan_hdd_cfg80211_set_feature(feature_flags,
2683 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2684 }
2685
2686 wlan_hdd_cfg80211_set_feature(feature_flags,
2687 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002688 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 wlan_hdd_cfg80211_set_feature(feature_flags,
2690 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002691
2692 if (wma_is_p2p_lo_capable())
2693 wlan_hdd_cfg80211_set_feature(feature_flags,
2694 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2695
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2697 NLMSG_HDRLEN);
2698
2699 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002700 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002701 return -ENOMEM;
2702 }
2703
2704 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2705 sizeof(feature_flags), feature_flags))
2706 goto nla_put_failure;
2707
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002708 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2709 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302710 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002711 if (one_by_one_dbs)
2712 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2713
2714 if (two_by_two_dbs)
2715 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2716
2717 if (!one_by_one_dbs && !two_by_two_dbs)
2718 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2719 } else {
2720 hdd_err("wma_get_dbs_hw_mode failed");
2721 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2722 }
2723
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002724 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725
2726 if (nla_put_u32(skb,
2727 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2728 MAX_CONCURRENT_CHAN_ON_24G))
2729 goto nla_put_failure;
2730
2731 if (nla_put_u32(skb,
2732 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2733 MAX_CONCURRENT_CHAN_ON_5G))
2734 goto nla_put_failure;
2735
2736 return cfg80211_vendor_cmd_reply(skb);
2737
2738nla_put_failure:
2739 kfree_skb(skb);
2740 return -EINVAL;
2741}
2742
2743/**
2744 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2745 * @wiphy: pointer to wireless wiphy structure.
2746 * @wdev: pointer to wireless_dev structure.
2747 * @data: Pointer to the data to be passed via vendor interface
2748 * @data_len:Length of the data to be passed
2749 *
2750 * This is called when wlan driver needs to send supported feature set to
2751 * supplicant upon a request/query from the supplicant.
2752 *
2753 * Return: Return the Success or Failure code.
2754 */
2755static int
2756wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2757 struct wireless_dev *wdev,
2758 const void *data, int data_len)
2759{
2760 int ret;
2761
2762 cds_ssr_protect(__func__);
2763 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2764 data, data_len);
2765 cds_ssr_unprotect(__func__);
2766
2767 return ret;
2768}
2769
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302770#define PARAM_NUM_NW \
2771 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2772#define PARAM_SET_BSSID \
2773 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2774#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2775#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776
2777/**
2778 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2779 * @wiphy: The wiphy structure
2780 * @wdev: The wireless device
2781 * @data: Data passed by framework
2782 * @data_len: Parameters to be configured passed as data
2783 *
2784 * The roaming related parameters are configured by the framework
2785 * using this interface.
2786 *
2787 * Return: Return either success or failure code.
2788 */
2789static int
2790__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2791 struct wireless_dev *wdev, const void *data, int data_len)
2792{
2793 struct net_device *dev = wdev->netdev;
2794 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2795 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2796 uint8_t session_id;
2797 struct roam_ext_params roam_params;
2798 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302799 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2801 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2802 int rem, i;
2803 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002804 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 int ret;
2806
Jeff Johnson1f61b612016-02-12 16:28:33 -08002807 ENTER_DEV(dev);
2808
Anurag Chouhan6d760662016-02-20 16:05:43 +05302809 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 hdd_err("Command not allowed in FTM mode");
2811 return -EPERM;
2812 }
2813
2814 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302815 if (ret)
2816 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817
2818 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2819 data, data_len,
2820 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002821 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822 return -EINVAL;
2823 }
2824 /* Parse and fetch Command Type*/
2825 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002826 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002827 goto fail;
2828 }
2829 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302830 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2832 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002833 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 goto fail;
2835 }
2836 req_id = nla_get_u32(
2837 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002838 hdd_debug("Req Id (%d)", req_id);
2839 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 switch (cmd_type) {
2841 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2842 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302843 if (tb[PARAM_NUM_NW]) {
2844 count = nla_get_u32(
2845 tb[PARAM_NUM_NW]);
2846 } else {
2847 hdd_err("Number of networks is not provided");
2848 goto fail;
2849 }
2850
2851 if (count &&
2852 tb[PRAM_SSID_LIST]) {
2853 nla_for_each_nested(curr_attr,
2854 tb[PRAM_SSID_LIST], rem) {
2855 if (nla_parse(tb2,
2856 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2857 nla_data(curr_attr), nla_len(curr_attr),
2858 NULL)) {
2859 hdd_err("nla_parse failed");
2860 goto fail;
2861 }
2862 /* Parse and Fetch allowed SSID list*/
2863 if (!tb2[PARAM_LIST_SSID]) {
2864 hdd_err("attr allowed ssid failed");
2865 goto fail;
2866 }
2867 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2868 /*
2869 * Upper Layers include a null termination
2870 * character. Check for the actual permissible
2871 * length of SSID and also ensure not to copy
2872 * the NULL termination character to the driver
2873 * buffer.
2874 */
2875 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2876 ((buf_len - 1) <=
2877 SIR_MAC_MAX_SSID_LENGTH)) {
2878 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002879 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302880 tb2[PARAM_LIST_SSID], buf_len - 1);
2881 roam_params.ssid_allowed_list[i].length
2882 = buf_len - 1;
2883 hdd_debug("SSID[%d]: %.*s,length = %d",
2884 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885 roam_params.ssid_allowed_list[i].length,
2886 roam_params.ssid_allowed_list[i].ssId,
2887 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302888 i++;
2889 } else {
2890 hdd_err("Invalid buffer length");
2891 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 }
2893 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302894 if (i != count) {
2895 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2896 i, count);
2897 goto fail;
2898 }
2899
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002901 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902 roam_params.num_ssid_allowed_list);
2903 sme_update_roam_params(pHddCtx->hHal, session_id,
2904 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2905 break;
2906 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2907 /* Parse and fetch 5G Boost Threshold */
2908 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002909 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 goto fail;
2911 }
2912 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2913 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002914 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 roam_params.raise_rssi_thresh_5g);
2916 /* Parse and fetch 5G Penalty Threshold */
2917 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002918 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 goto fail;
2920 }
2921 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2922 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002923 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 roam_params.drop_rssi_thresh_5g);
2925 /* Parse and fetch 5G Boost Factor */
2926 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002927 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 goto fail;
2929 }
2930 roam_params.raise_factor_5g = nla_get_u32(
2931 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002932 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 roam_params.raise_factor_5g);
2934 /* Parse and fetch 5G Penalty factor */
2935 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002936 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 goto fail;
2938 }
2939 roam_params.drop_factor_5g = nla_get_u32(
2940 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002941 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 roam_params.drop_factor_5g);
2943 /* Parse and fetch 5G Max Boost */
2944 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002945 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 goto fail;
2947 }
2948 roam_params.max_raise_rssi_5g = nla_get_u32(
2949 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002950 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951 roam_params.max_raise_rssi_5g);
2952 /* Parse and fetch Rssi Diff */
2953 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002954 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955 goto fail;
2956 }
2957 roam_params.rssi_diff = nla_get_s32(
2958 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002959 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 roam_params.rssi_diff);
2961 /* Parse and fetch Alert Rssi Threshold */
2962 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002963 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002964 goto fail;
2965 }
2966 roam_params.alert_rssi_threshold = nla_get_u32(
2967 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002968 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 roam_params.alert_rssi_threshold);
2970 sme_update_roam_params(pHddCtx->hHal, session_id,
2971 roam_params,
2972 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2973 break;
2974 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2975 /* Parse and fetch Activate Good Rssi Roam */
2976 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002977 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978 goto fail;
2979 }
2980 roam_params.good_rssi_roam = nla_get_s32(
2981 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002982 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002983 roam_params.good_rssi_roam);
2984 sme_update_roam_params(pHddCtx->hHal, session_id,
2985 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2986 break;
2987 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2988 /* Parse and fetch number of preferred BSSID */
2989 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002990 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002991 goto fail;
2992 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002993 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002995 if (count > MAX_BSSID_FAVORED) {
2996 hdd_err("Preferred BSSID count %u exceeds max %u",
2997 count, MAX_BSSID_FAVORED);
2998 goto fail;
2999 }
3000 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 i = 0;
3002 nla_for_each_nested(curr_attr,
3003 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3004 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003005
3006 if (i == count) {
3007 hdd_warn("Ignoring excess Preferred BSSID");
3008 break;
3009 }
3010
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003011 if (nla_parse(tb2,
3012 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3013 nla_data(curr_attr), nla_len(curr_attr),
3014 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003015 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 goto fail;
3017 }
3018 /* Parse and fetch MAC address */
3019 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003020 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 goto fail;
3022 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003023 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303025 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003026 hdd_debug(MAC_ADDRESS_STR,
3027 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 /* Parse and fetch preference factor*/
3029 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003030 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 goto fail;
3032 }
3033 roam_params.bssid_favored_factor[i] = nla_get_u32(
3034 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003035 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003036 roam_params.bssid_favored_factor[i]);
3037 i++;
3038 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003039 if (i < count)
3040 hdd_warn("Num Preferred BSSID %u less than expected %u",
3041 i, count);
3042 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 sme_update_roam_params(pHddCtx->hHal, session_id,
3044 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3045 break;
3046 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3047 /* Parse and fetch number of blacklist BSSID */
3048 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003049 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 goto fail;
3051 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003052 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003054 if (count > MAX_BSSID_AVOID_LIST) {
3055 hdd_err("Blacklist BSSID count %u exceeds max %u",
3056 count, MAX_BSSID_AVOID_LIST);
3057 goto fail;
3058 }
3059 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303061
3062 if (count &&
3063 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3064 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3066 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003067
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303068 if (i == count) {
3069 hdd_warn("Ignoring excess Blacklist BSSID");
3070 break;
3071 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003072
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303073 if (nla_parse(tb2,
3074 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3075 nla_data(curr_attr), nla_len(curr_attr),
3076 NULL)) {
3077 hdd_err("nla_parse failed");
3078 goto fail;
3079 }
3080 /* Parse and fetch MAC address */
3081 if (!tb2[PARAM_SET_BSSID]) {
3082 hdd_err("attr blacklist addr failed");
3083 goto fail;
3084 }
3085 nla_memcpy(
3086 roam_params.bssid_avoid_list[i].bytes,
3087 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3088 hdd_debug(MAC_ADDRESS_STR,
3089 MAC_ADDR_ARRAY(
3090 roam_params.bssid_avoid_list[i].bytes));
3091 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003094 if (i < count)
3095 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3096 i, count);
3097 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 sme_update_roam_params(pHddCtx->hHal, session_id,
3099 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3100 break;
3101 }
3102 return 0;
3103fail:
3104 return -EINVAL;
3105}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303106#undef PARAM_NUM_NW
3107#undef PARAM_SET_BSSID
3108#undef PRAM_SSID_LIST
3109#undef PARAM_LIST_SSID
3110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111
3112/**
3113 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3114 * @wiphy: pointer to wireless wiphy structure.
3115 * @wdev: pointer to wireless_dev structure.
3116 * @data: Pointer to the data to be passed via vendor interface
3117 * @data_len:Length of the data to be passed
3118 *
3119 * Return: Return the Success or Failure code.
3120 */
3121static int
3122wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3123 struct wireless_dev *wdev,
3124 const void *data,
3125 int data_len)
3126{
3127 int ret;
3128
3129 cds_ssr_protect(__func__);
3130 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3131 data, data_len);
3132 cds_ssr_unprotect(__func__);
3133
3134 return ret;
3135}
3136
3137static const struct nla_policy
3138wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3139 +1] = {
3140 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3141};
3142
3143/**
3144 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3145 * @hdd_ctx: HDD context
3146 * @device_mode: device mode
3147 * Return: bool
3148 */
3149static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003150 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003151{
3152 hdd_adapter_t *adapter;
3153 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3154 hdd_ap_ctx_t *ap_ctx;
3155 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303156 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303158 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303161 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 adapter = adapter_node->pAdapter;
3163
3164 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003165 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 ap_ctx =
3167 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3168
3169 /*
3170 * if there is SAP already running on DFS channel,
3171 * do not disable scan on dfs channels. Note that
3172 * with SAP on DFS, there cannot be conurrency on
3173 * single radio. But then we can have multiple
3174 * radios !!
3175 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003176 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3177 hdd_ctx->hdd_pdev,
3178 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003179 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 return true;
3181 }
3182 }
3183
3184 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003185 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 sta_ctx =
3187 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3188
3189 /*
3190 * if STA is already connected on DFS channel,
3191 * do not disable scan on dfs channels
3192 */
3193 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003194 (CHANNEL_STATE_DFS ==
3195 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3196 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003197 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 return true;
3199 }
3200 }
3201
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303202 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 adapter_node,
3204 &next);
3205 adapter_node = next;
3206 }
3207
3208 return false;
3209}
3210
3211/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003212 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3213 * @hdd_ctx: HDD context within host driver
3214 * @adapter: Adapter pointer
3215 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3216 *
3217 * Loops through devices to see who is operating on DFS channels
3218 * and then disables/enables DFS channels by calling SME API.
3219 * Fails the disable request if any device is active on a DFS channel.
3220 *
3221 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003223
3224int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3225 hdd_adapter_t *adapter,
3226 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303229 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003231
3232 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3233 if (no_dfs_flag) {
3234 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003235 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236
3237 if (true == status)
3238 return -EOPNOTSUPP;
3239
3240 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003241 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242
3243 if (true == status)
3244 return -EOPNOTSUPP;
3245 }
3246
3247 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3248
3249 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3250
3251 /*
3252 * call the SME API to tunnel down the new channel list
3253 * to the firmware
3254 */
3255 status = sme_handle_dfs_chan_scan(
3256 h_hal, hdd_ctx->config->enableDFSChnlScan);
3257
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303258 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003259 ret_val = 0;
3260
3261 /*
3262 * Clear the SME scan cache also. Note that the
3263 * clearing of scan results is independent of session;
3264 * so no need to iterate over
3265 * all sessions
3266 */
3267 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303268 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003269 ret_val = -EPERM;
3270 }
3271
3272 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003273 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 ret_val = 0;
3275 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003276 return ret_val;
3277}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003279/**
3280 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3281 * @wiphy: corestack handler
3282 * @wdev: wireless device
3283 * @data: data
3284 * @data_len: data length
3285 * Return: success(0) or reason code for failure
3286 */
3287static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3288 struct wireless_dev *wdev,
3289 const void *data,
3290 int data_len)
3291{
3292 struct net_device *dev = wdev->netdev;
3293 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3294 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3295 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3296 int ret_val;
3297 uint32_t no_dfs_flag = 0;
3298
Jeff Johnson1f61b612016-02-12 16:28:33 -08003299 ENTER_DEV(dev);
3300
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003301 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303302 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003303 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003304
3305 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3306 data, data_len,
3307 wlan_hdd_set_no_dfs_flag_config_policy)) {
3308 hdd_err("invalid attr");
3309 return -EINVAL;
3310 }
3311
3312 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3313 hdd_err("attr dfs flag failed");
3314 return -EINVAL;
3315 }
3316
3317 no_dfs_flag = nla_get_u32(
3318 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3319
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003320 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003321
3322 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003323 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003324 return -EINVAL;
3325 }
3326
3327 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3328 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003329 return ret_val;
3330}
3331
3332/**
3333 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3334 *
3335 * @wiphy: wiphy device pointer
3336 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003337 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 * @data_len: Buffer length
3339 *
3340 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3341 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3342 *
3343 * Return: EOK or other error codes.
3344 */
3345
3346static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3347 struct wireless_dev *wdev,
3348 const void *data,
3349 int data_len)
3350{
3351 int ret;
3352
3353 cds_ssr_protect(__func__);
3354 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3355 data, data_len);
3356 cds_ssr_unprotect(__func__);
3357
3358 return ret;
3359}
3360
Manikandan Mohan80dea792016-04-28 16:36:48 -07003361static const struct nla_policy
3362wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3363 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3364};
3365
3366/**
3367 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3368 * @wiphy: wiphy device pointer
3369 * @wdev: wireless device pointer
3370 * @data: Vendor command data buffer
3371 * @data_len: Buffer length
3372 *
3373 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3374 * setup WISA Mode features.
3375 *
3376 * Return: Success(0) or reason code for failure
3377 */
3378static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3379 struct wireless_dev *wdev, const void *data, int data_len)
3380{
3381 struct net_device *dev = wdev->netdev;
3382 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3383 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3384 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3385 struct sir_wisa_params wisa;
3386 int ret_val;
3387 QDF_STATUS status;
3388 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003389 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3390 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003391
3392 ENTER_DEV(dev);
3393 ret_val = wlan_hdd_validate_context(hdd_ctx);
3394 if (ret_val)
3395 goto err;
3396
3397 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3398 hdd_err("Command not allowed in FTM mode");
3399 return -EPERM;
3400 }
3401
3402 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3403 wlan_hdd_wisa_cmd_policy)) {
3404 hdd_err("Invalid WISA cmd attributes");
3405 ret_val = -EINVAL;
3406 goto err;
3407 }
3408 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3409 hdd_err("Invalid WISA mode");
3410 ret_val = -EINVAL;
3411 goto err;
3412 }
3413
3414 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003415 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003416 wisa.mode = wisa_mode;
3417 wisa.vdev_id = adapter->sessionId;
3418 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003419 if (!QDF_IS_STATUS_SUCCESS(status)) {
3420 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003421 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003422 }
3423 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003424 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003425 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3426 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003427 adapter->sessionId),
3428 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003429err:
3430 EXIT();
3431 return ret_val;
3432}
3433
3434/**
3435 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3436 * @wiphy: corestack handler
3437 * @wdev: wireless device
3438 * @data: data
3439 * @data_len: data length
3440 *
3441 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3442 * setup WISA mode features.
3443 *
3444 * Return: Success(0) or reason code for failure
3445 */
3446static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3447 struct wireless_dev *wdev,
3448 const void *data,
3449 int data_len)
3450{
3451 int ret;
3452
3453 cds_ssr_protect(__func__);
3454 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3455 cds_ssr_unprotect(__func__);
3456
3457 return ret;
3458}
3459
Anurag Chouhan96919482016-07-13 16:36:57 +05303460/*
3461 * define short names for the global vendor params
3462 * used by __wlan_hdd_cfg80211_get_station_cmd()
3463 */
3464#define STATION_INVALID \
3465 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3466#define STATION_INFO \
3467 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3468#define STATION_ASSOC_FAIL_REASON \
3469 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3470#define STATION_MAX \
3471 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3472
3473static const struct nla_policy
3474hdd_get_station_policy[STATION_MAX + 1] = {
3475 [STATION_INFO] = {.type = NLA_FLAG},
3476 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3477};
3478
3479/**
3480 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3481 * @hdd_ctx: HDD context within host driver
3482 * @wdev: wireless device
3483 *
3484 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3485 * Validate cmd attributes and send the station info to upper layers.
3486 *
3487 * Return: Success(0) or reason code for failure
3488 */
3489static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3490 hdd_adapter_t *adapter)
3491{
3492 struct sk_buff *skb = NULL;
3493 uint32_t nl_buf_len;
3494 hdd_station_ctx_t *hdd_sta_ctx;
3495
3496 nl_buf_len = NLMSG_HDRLEN;
3497 nl_buf_len += sizeof(uint32_t);
3498 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3499
3500 if (!skb) {
3501 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3502 return -ENOMEM;
3503 }
3504
3505 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3506
3507 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3508 hdd_sta_ctx->conn_info.assoc_status_code)) {
3509 hdd_err("put fail");
3510 goto fail;
3511 }
3512 return cfg80211_vendor_cmd_reply(skb);
3513fail:
3514 if (skb)
3515 kfree_skb(skb);
3516 return -EINVAL;
3517}
3518
3519/**
3520 * hdd_map_auth_type() - transform auth type specific to
3521 * vendor command
3522 * @auth_type: csr auth type
3523 *
3524 * Return: Success(0) or reason code for failure
3525 */
3526static int hdd_convert_auth_type(uint32_t auth_type)
3527{
3528 uint32_t ret_val;
3529
3530 switch (auth_type) {
3531 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3532 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3533 break;
3534 case eCSR_AUTH_TYPE_SHARED_KEY:
3535 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3536 break;
3537 case eCSR_AUTH_TYPE_WPA:
3538 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3539 break;
3540 case eCSR_AUTH_TYPE_WPA_PSK:
3541 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3542 break;
3543 case eCSR_AUTH_TYPE_AUTOSWITCH:
3544 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3545 break;
3546 case eCSR_AUTH_TYPE_WPA_NONE:
3547 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3548 break;
3549 case eCSR_AUTH_TYPE_RSN:
3550 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3551 break;
3552 case eCSR_AUTH_TYPE_RSN_PSK:
3553 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3554 break;
3555 case eCSR_AUTH_TYPE_FT_RSN:
3556 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3557 break;
3558 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3559 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3560 break;
3561 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3562 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3563 break;
3564 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3565 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3566 break;
3567 case eCSR_AUTH_TYPE_CCKM_WPA:
3568 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3569 break;
3570 case eCSR_AUTH_TYPE_CCKM_RSN:
3571 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3572 break;
3573 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3574 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3575 break;
3576 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3577 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3578 break;
3579 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3580 case eCSR_AUTH_TYPE_FAILED:
3581 case eCSR_AUTH_TYPE_NONE:
3582 default:
3583 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3584 break;
3585 }
3586 return ret_val;
3587}
3588
3589/**
3590 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3591 * vendor command
3592 * @dot11mode: dot11mode
3593 *
3594 * Return: Success(0) or reason code for failure
3595 */
3596static int hdd_convert_dot11mode(uint32_t dot11mode)
3597{
3598 uint32_t ret_val;
3599
3600 switch (dot11mode) {
3601 case eCSR_CFG_DOT11_MODE_11A:
3602 ret_val = QCA_WLAN_802_11_MODE_11A;
3603 break;
3604 case eCSR_CFG_DOT11_MODE_11B:
3605 ret_val = QCA_WLAN_802_11_MODE_11B;
3606 break;
3607 case eCSR_CFG_DOT11_MODE_11G:
3608 ret_val = QCA_WLAN_802_11_MODE_11G;
3609 break;
3610 case eCSR_CFG_DOT11_MODE_11N:
3611 ret_val = QCA_WLAN_802_11_MODE_11N;
3612 break;
3613 case eCSR_CFG_DOT11_MODE_11AC:
3614 ret_val = QCA_WLAN_802_11_MODE_11AC;
3615 break;
3616 case eCSR_CFG_DOT11_MODE_AUTO:
3617 case eCSR_CFG_DOT11_MODE_ABG:
3618 default:
3619 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3620 }
3621 return ret_val;
3622}
3623
3624/**
3625 * hdd_add_tx_bitrate() - add tx bitrate attribute
3626 * @skb: pointer to sk buff
3627 * @hdd_sta_ctx: pointer to hdd station context
3628 * @idx: attribute index
3629 *
3630 * Return: Success(0) or reason code for failure
3631 */
3632static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3633 hdd_station_ctx_t *hdd_sta_ctx,
3634 int idx)
3635{
3636 struct nlattr *nla_attr;
3637 uint32_t bitrate, bitrate_compat;
3638
3639 nla_attr = nla_nest_start(skb, idx);
3640 if (!nla_attr)
3641 goto fail;
3642 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3643 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3644
3645 /* report 16-bit bitrate only if we can */
3646 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3647 if (bitrate > 0 &&
3648 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3649 hdd_err("put fail");
3650 goto fail;
3651 }
3652 if (bitrate_compat > 0 &&
3653 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3654 hdd_err("put fail");
3655 goto fail;
3656 }
3657 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3658 hdd_sta_ctx->conn_info.txrate.nss)) {
3659 hdd_err("put fail");
3660 goto fail;
3661 }
3662 nla_nest_end(skb, nla_attr);
3663 return 0;
3664fail:
3665 return -EINVAL;
3666}
3667
3668/**
3669 * hdd_add_sta_info() - add station info attribute
3670 * @skb: pointer to sk buff
3671 * @hdd_sta_ctx: pointer to hdd station context
3672 * @idx: attribute index
3673 *
3674 * Return: Success(0) or reason code for failure
3675 */
3676static int32_t hdd_add_sta_info(struct sk_buff *skb,
3677 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3678{
3679 struct nlattr *nla_attr;
3680
3681 nla_attr = nla_nest_start(skb, idx);
3682 if (!nla_attr)
3683 goto fail;
3684 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3685 (hdd_sta_ctx->conn_info.signal + 100))) {
3686 hdd_err("put fail");
3687 goto fail;
3688 }
3689 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3690 goto fail;
3691 nla_nest_end(skb, nla_attr);
3692 return 0;
3693fail:
3694 return -EINVAL;
3695}
3696
3697/**
3698 * hdd_add_survey_info() - add survey info attribute
3699 * @skb: pointer to sk buff
3700 * @hdd_sta_ctx: pointer to hdd station context
3701 * @idx: attribute index
3702 *
3703 * Return: Success(0) or reason code for failure
3704 */
3705static int32_t hdd_add_survey_info(struct sk_buff *skb,
3706 hdd_station_ctx_t *hdd_sta_ctx,
3707 int idx)
3708{
3709 struct nlattr *nla_attr;
3710
3711 nla_attr = nla_nest_start(skb, idx);
3712 if (!nla_attr)
3713 goto fail;
3714 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3715 hdd_sta_ctx->conn_info.freq) ||
3716 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3717 (hdd_sta_ctx->conn_info.noise + 100))) {
3718 hdd_err("put fail");
3719 goto fail;
3720 }
3721 nla_nest_end(skb, nla_attr);
3722 return 0;
3723fail:
3724 return -EINVAL;
3725}
3726
3727/**
3728 * hdd_add_link_standard_info() - add link info attribute
3729 * @skb: pointer to sk buff
3730 * @hdd_sta_ctx: pointer to hdd station context
3731 * @idx: attribute index
3732 *
3733 * Return: Success(0) or reason code for failure
3734 */
3735static int32_t
3736hdd_add_link_standard_info(struct sk_buff *skb,
3737 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3738{
3739 struct nlattr *nla_attr;
3740
3741 nla_attr = nla_nest_start(skb, idx);
3742 if (!nla_attr)
3743 goto fail;
3744 if (nla_put(skb,
3745 NL80211_ATTR_SSID,
3746 hdd_sta_ctx->conn_info.SSID.SSID.length,
3747 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3748 hdd_err("put fail");
3749 goto fail;
3750 }
3751 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3752 goto fail;
3753 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3754 goto fail;
3755 nla_nest_end(skb, nla_attr);
3756 return 0;
3757fail:
3758 return -EINVAL;
3759}
3760
3761/**
3762 * hdd_add_ap_standard_info() - add ap info attribute
3763 * @skb: pointer to sk buff
3764 * @hdd_sta_ctx: pointer to hdd station context
3765 * @idx: attribute index
3766 *
3767 * Return: Success(0) or reason code for failure
3768 */
3769static int32_t
3770hdd_add_ap_standard_info(struct sk_buff *skb,
3771 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3772{
3773 struct nlattr *nla_attr;
3774
3775 nla_attr = nla_nest_start(skb, idx);
3776 if (!nla_attr)
3777 goto fail;
3778 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3779 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3780 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3781 &hdd_sta_ctx->conn_info.vht_caps)) {
3782 hdd_err("put fail");
3783 goto fail;
3784 }
3785 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3786 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3787 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3788 &hdd_sta_ctx->conn_info.ht_caps)) {
3789 hdd_err("put fail");
3790 goto fail;
3791 }
3792 nla_nest_end(skb, nla_attr);
3793 return 0;
3794fail:
3795 return -EINVAL;
3796}
3797
3798/**
3799 * hdd_get_station_info() - send BSS information to supplicant
3800 * @hdd_ctx: pointer to hdd context
3801 * @adapter: pointer to adapter
3802 *
3803 * Return: 0 if success else error status
3804 */
3805static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3806 hdd_adapter_t *adapter)
3807{
3808 struct sk_buff *skb = NULL;
3809 uint8_t *tmp_hs20 = NULL;
3810 uint32_t nl_buf_len;
3811 hdd_station_ctx_t *hdd_sta_ctx;
3812
3813 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3814
3815 nl_buf_len = NLMSG_HDRLEN;
3816 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3817 sizeof(hdd_sta_ctx->conn_info.freq) +
3818 sizeof(hdd_sta_ctx->conn_info.noise) +
3819 sizeof(hdd_sta_ctx->conn_info.signal) +
3820 (sizeof(uint32_t) * 2) +
3821 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3822 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3823 sizeof(hdd_sta_ctx->conn_info.authType) +
3824 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3825 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3826 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3827 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3828 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3829 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3830 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3831 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3832 1);
3833 }
3834 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3835 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3836 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3837 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3838
3839
3840 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3841 if (!skb) {
3842 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3843 return -ENOMEM;
3844 }
3845
3846 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3847 LINK_INFO_STANDARD_NL80211_ATTR)) {
3848 hdd_err("put fail");
3849 goto fail;
3850 }
3851 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3852 AP_INFO_STANDARD_NL80211_ATTR)) {
3853 hdd_err("put fail");
3854 goto fail;
3855 }
3856 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3857 hdd_sta_ctx->conn_info.roam_count) ||
3858 nla_put_u32(skb, INFO_AKM,
3859 hdd_convert_auth_type(
3860 hdd_sta_ctx->conn_info.authType)) ||
3861 nla_put_u32(skb, WLAN802_11_MODE,
3862 hdd_convert_dot11mode(
3863 hdd_sta_ctx->conn_info.dot11Mode))) {
3864 hdd_err("put fail");
3865 goto fail;
3866 }
3867 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3868 if (nla_put(skb, HT_OPERATION,
3869 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3870 &hdd_sta_ctx->conn_info.ht_operation)) {
3871 hdd_err("put fail");
3872 goto fail;
3873 }
3874 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3875 if (nla_put(skb, VHT_OPERATION,
3876 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3877 &hdd_sta_ctx->conn_info.vht_operation)) {
3878 hdd_err("put fail");
3879 goto fail;
3880 }
3881 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3882 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3883 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3884 tmp_hs20 + 1)) {
3885 hdd_err("put fail");
3886 goto fail;
3887 }
3888
3889 return cfg80211_vendor_cmd_reply(skb);
3890fail:
3891 if (skb)
3892 kfree_skb(skb);
3893 return -EINVAL;
3894}
3895
3896/**
3897 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3898 * @wiphy: corestack handler
3899 * @wdev: wireless device
3900 * @data: data
3901 * @data_len: data length
3902 *
3903 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3904 * Validate cmd attributes and send the station info to upper layers.
3905 *
3906 * Return: Success(0) or reason code for failure
3907 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303908static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303909__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3910 struct wireless_dev *wdev,
3911 const void *data,
3912 int data_len)
3913{
3914 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3915 struct net_device *dev = wdev->netdev;
3916 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3917 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3918 int32_t status;
3919
3920 ENTER_DEV(dev);
3921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3922 hdd_err("Command not allowed in FTM mode");
3923 status = -EPERM;
3924 goto out;
3925 }
3926
3927 status = wlan_hdd_validate_context(hdd_ctx);
3928 if (0 != status)
3929 goto out;
3930
3931
3932 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3933 data, data_len, NULL);
3934 if (status) {
3935 hdd_err("Invalid ATTR");
3936 goto out;
3937 }
3938
3939 /* Parse and fetch Command Type*/
3940 if (tb[STATION_INFO]) {
3941 status = hdd_get_station_info(hdd_ctx, adapter);
3942 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3943 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3944 } else {
3945 hdd_err("get station info cmd type failed");
3946 status = -EINVAL;
3947 goto out;
3948 }
3949 EXIT();
3950out:
3951 return status;
3952}
3953
3954/**
3955 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3956 * @wiphy: corestack handler
3957 * @wdev: wireless device
3958 * @data: data
3959 * @data_len: data length
3960 *
3961 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3962 * Validate cmd attributes and send the station info to upper layers.
3963 *
3964 * Return: Success(0) or reason code for failure
3965 */
3966static int32_t
3967hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3968 struct wireless_dev *wdev,
3969 const void *data,
3970 int data_len)
3971{
3972 int ret;
3973
3974 cds_ssr_protect(__func__);
3975 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3976 cds_ssr_unprotect(__func__);
3977
3978 return ret;
3979}
3980
3981/*
3982 * undef short names defined for get station command
3983 * used by __wlan_hdd_cfg80211_get_station_cmd()
3984 */
3985#undef STATION_INVALID
3986#undef STATION_INFO
3987#undef STATION_ASSOC_FAIL_REASON
3988#undef STATION_MAX
3989
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3991/**
3992 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3993 * @wiphy: pointer to wireless wiphy structure.
3994 * @wdev: pointer to wireless_dev structure.
3995 * @data: Pointer to the Key data
3996 * @data_len:Length of the data passed
3997 *
3998 * This is called when wlan driver needs to save the keys received via
3999 * vendor specific command.
4000 *
4001 * Return: Return the Success or Failure code.
4002 */
4003static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4004 struct wireless_dev *wdev,
4005 const void *data, int data_len)
4006{
4007 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4008 struct net_device *dev = wdev->netdev;
4009 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4010 hdd_context_t *hdd_ctx_ptr;
4011 int status;
4012
Jeff Johnson1f61b612016-02-12 16:28:33 -08004013 ENTER_DEV(dev);
4014
Anurag Chouhan6d760662016-02-20 16:05:43 +05304015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004016 hdd_err("Command not allowed in FTM mode");
4017 return -EPERM;
4018 }
4019
4020 if ((data == NULL) || (data_len == 0) ||
4021 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004022 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 return -EINVAL;
4024 }
4025
4026 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4027 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004028 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029 return -EINVAL;
4030 }
4031
4032 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304033 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004034 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4036 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004037 true,
4038 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304039 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4040 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4042 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4043 return 0;
4044}
4045
4046/**
4047 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4048 * @wiphy: pointer to wireless wiphy structure.
4049 * @wdev: pointer to wireless_dev structure.
4050 * @data: Pointer to the Key data
4051 * @data_len:Length of the data passed
4052 *
4053 * This is called when wlan driver needs to save the keys received via
4054 * vendor specific command.
4055 *
4056 * Return: Return the Success or Failure code.
4057 */
4058static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4059 struct wireless_dev *wdev,
4060 const void *data, int data_len)
4061{
4062 int ret;
4063
4064 cds_ssr_protect(__func__);
4065 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4066 cds_ssr_unprotect(__func__);
4067
4068 return ret;
4069}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004070#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071
4072static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4073 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4074 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4075 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004076 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077};
4078
4079/**
4080 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4081 * @wiphy: pointer to wireless wiphy structure.
4082 * @wdev: pointer to wireless_dev structure.
4083 * @data: Pointer to the data to be passed via vendor interface
4084 * @data_len:Length of the data to be passed
4085 *
4086 * This is called when wlan driver needs to send wifi driver related info
4087 * (driver/fw version) to the user space application upon request.
4088 *
4089 * Return: Return the Success or Failure code.
4090 */
4091static int
4092__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4093 struct wireless_dev *wdev,
4094 const void *data, int data_len)
4095{
4096 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4097 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004098 tSirVersionString driver_version;
4099 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004101 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004102 struct sk_buff *reply_skb;
4103 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104
Jeff Johnson1f61b612016-02-12 16:28:33 -08004105 ENTER_DEV(wdev->netdev);
4106
Anurag Chouhan6d760662016-02-20 16:05:43 +05304107 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 hdd_err("Command not allowed in FTM mode");
4109 return -EPERM;
4110 }
4111
4112 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304113 if (status)
4114 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115
4116 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4117 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004118 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119 return -EINVAL;
4120 }
4121
4122 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004123 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004124 strlcpy(driver_version, QWLAN_VERSIONSTR,
4125 sizeof(driver_version));
4126 skb_len += strlen(driver_version) + 1;
4127 count++;
4128 }
4129
4130 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004131 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4133 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004134 snprintf(firmware_version, sizeof(firmware_version),
4135 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4136 skb_len += strlen(firmware_version) + 1;
4137 count++;
4138 }
4139
4140 if (count == 0) {
4141 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 return -EINVAL;
4143 }
4144
Ryan Hsu7ac88852016-04-28 10:20:34 -07004145 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4146 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4147
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004148 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004149 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 return -ENOMEM;
4151 }
4152
Ryan Hsu7ac88852016-04-28 10:20:34 -07004153 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4154 if (nla_put_string(reply_skb,
4155 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4156 driver_version))
4157 goto error_nla_fail;
4158 }
4159
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304160 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004161 if (nla_put_string(reply_skb,
4162 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4163 firmware_version))
4164 goto error_nla_fail;
4165 }
4166
4167 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4168 if (nla_put_u32(reply_skb,
4169 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4170 hdd_ctx->radio_index))
4171 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172 }
4173
4174 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004175
4176error_nla_fail:
4177 hdd_err("nla put fail");
4178 kfree_skb(reply_skb);
4179 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180}
4181
4182/**
4183 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4184 * @wiphy: pointer to wireless wiphy structure.
4185 * @wdev: pointer to wireless_dev structure.
4186 * @data: Pointer to the data to be passed via vendor interface
4187 * @data_len:Length of the data to be passed
4188 *
4189 * This is called when wlan driver needs to send wifi driver related info
4190 * (driver/fw version) to the user space application upon request.
4191 *
4192 * Return: Return the Success or Failure code.
4193 */
4194static int
4195wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4196 struct wireless_dev *wdev,
4197 const void *data, int data_len)
4198{
4199 int ret;
4200
4201 cds_ssr_protect(__func__);
4202 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4203 cds_ssr_unprotect(__func__);
4204
4205 return ret;
4206}
4207
4208/**
4209 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4210 * @wiphy: pointer to wireless wiphy structure.
4211 * @wdev: pointer to wireless_dev structure.
4212 * @data: Pointer to the data to be passed via vendor interface
4213 * @data_len:Length of the data to be passed
4214 *
4215 * This is called by userspace to know the supported logger features
4216 *
4217 * Return: Return the Success or Failure code.
4218 */
4219static int
4220__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4221 struct wireless_dev *wdev,
4222 const void *data, int data_len)
4223{
4224 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4225 int status;
4226 uint32_t features;
4227 struct sk_buff *reply_skb = NULL;
4228
Jeff Johnson1f61b612016-02-12 16:28:33 -08004229 ENTER_DEV(wdev->netdev);
4230
Anurag Chouhan6d760662016-02-20 16:05:43 +05304231 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004232 hdd_err("Command not allowed in FTM mode");
4233 return -EPERM;
4234 }
4235
4236 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304237 if (status)
4238 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004239
4240 features = 0;
4241
4242 if (hdd_is_memdump_supported())
4243 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4244 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4245 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4246 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4247
4248 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4249 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4250 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004251 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252 return -ENOMEM;
4253 }
4254
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004255 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4257 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004258 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259 kfree_skb(reply_skb);
4260 return -EINVAL;
4261 }
4262
4263 return cfg80211_vendor_cmd_reply(reply_skb);
4264}
4265
4266/**
4267 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4268 * @wiphy: pointer to wireless wiphy structure.
4269 * @wdev: pointer to wireless_dev structure.
4270 * @data: Pointer to the data to be passed via vendor interface
4271 * @data_len:Length of the data to be passed
4272 *
4273 * This is called by userspace to know the supported logger features
4274 *
4275 * Return: Return the Success or Failure code.
4276 */
4277static int
4278wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4279 struct wireless_dev *wdev,
4280 const void *data, int data_len)
4281{
4282 int ret;
4283
4284 cds_ssr_protect(__func__);
4285 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4286 data, data_len);
4287 cds_ssr_unprotect(__func__);
4288
4289 return ret;
4290}
4291
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004292#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293/**
4294 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304295 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 * @bssid: pointer to bssid of roamed AP.
4297 * @req_rsn_ie: Pointer to request RSN IE
4298 * @req_rsn_len: Length of the request RSN IE
4299 * @rsp_rsn_ie: Pointer to response RSN IE
4300 * @rsp_rsn_len: Length of the response RSN IE
4301 * @roam_info_ptr: Pointer to the roaming related information
4302 *
4303 * This is called when wlan driver needs to send the roaming and
4304 * authorization information after roaming.
4305 *
4306 * The information that would be sent is the request RSN IE, response
4307 * RSN IE and BSSID of the newly roamed AP.
4308 *
4309 * If the Authorized status is authenticated, then additional parameters
4310 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4311 * supplicant.
4312 *
4313 * The supplicant upon receiving this event would ignore the legacy
4314 * cfg80211_roamed call and use the entire information from this event.
4315 * The cfg80211_roamed should still co-exist since the kernel will
4316 * make use of the parameters even if the supplicant ignores it.
4317 *
4318 * Return: Return the Success or Failure code.
4319 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304320int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004321 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4322 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4323{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304324 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004326 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004327 ENTER();
4328
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304329 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004330 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004332 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004333 !roam_info_ptr->roamSynchInProgress)
4334 return 0;
4335
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004336 /*
4337 * The user space has issued a disconnect when roaming is in
4338 * progress. The disconnect should be honored gracefully.
4339 * If the roaming is complete and the roam event is sent
4340 * back to the user space, it will get confused as it is
4341 * expecting a disconnect event. So, do not send the event
4342 * and handle the disconnect later.
4343 */
4344 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004345 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004346 return 0;
4347 }
4348
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304350 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4352 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4353 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004354 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4356 GFP_KERNEL);
4357
4358 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004359 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 return -EINVAL;
4361 }
4362
4363 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4364 ETH_ALEN, bssid) ||
4365 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4366 req_rsn_len, req_rsn_ie) ||
4367 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4368 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004369 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370 goto nla_put_failure;
4371 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004372 if (roam_info_ptr->synchAuthStatus ==
4373 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004374 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004375 if (nla_put_u8(skb,
4376 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4377 hdd_err("nla put fail");
4378 goto nla_put_failure;
4379 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004380 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4381 /* if FT or CCKM connection: dont send replay counter */
4382 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4383 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4384 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4385 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4386 nla_put(skb,
4387 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4388 SIR_REPLAY_CTR_LEN,
4389 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004390 hdd_err("non FT/non CCKM connection");
4391 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004392 goto nla_put_failure;
4393 }
4394 if (nla_put(skb,
4395 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4396 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4397 nla_put(skb,
4398 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4399 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4400 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 goto nla_put_failure;
4402 }
4403 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004404 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4406 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004407 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 goto nla_put_failure;
4409 }
4410 }
4411
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304412 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4413 roam_info_ptr->synchAuthStatus,
4414 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004415
4416 /*
4417 * Add subnet change status if subnet has changed
4418 * 0 = unchanged
4419 * 1 = changed
4420 * 2 = unknown
4421 */
4422 if (roam_info_ptr->subnet_change_status) {
4423 if (nla_put_u8(skb,
4424 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4425 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004426 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004427 goto nla_put_failure;
4428 }
4429 }
4430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431 cfg80211_vendor_event(skb, GFP_KERNEL);
4432 return 0;
4433
4434nla_put_failure:
4435 kfree_skb(skb);
4436 return -EINVAL;
4437}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004438#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439
4440static const struct nla_policy
4441wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4442
4443 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4444 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4445 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304446 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304447 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4448 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004449 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4450 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4451 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4452 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4453 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304454 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004455};
4456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304458 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4459 *
4460 * @adapter: Pointer to HDD adapter
4461 * @ie_data: Pointer to Scan IEs buffer
4462 * @ie_len: Length of Scan IEs
4463 *
4464 * Return: 0 on success; error number otherwise
4465 */
4466static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4467 uint8_t *ie_data, uint8_t ie_len)
4468{
4469 hdd_scaninfo_t *scan_info = NULL;
4470 scan_info = &adapter->scan_info;
4471
4472 if (scan_info->default_scan_ies) {
4473 qdf_mem_free(scan_info->default_scan_ies);
4474 scan_info->default_scan_ies = NULL;
4475 }
4476
4477 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4478 if (!scan_info->default_scan_ies)
4479 return -ENOMEM;
4480
4481 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4482 scan_info->default_scan_ies_len = ie_len;
4483 return 0;
4484}
4485
4486/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004487 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4488 * vendor command
4489 *
4490 * @wiphy: wiphy device pointer
4491 * @wdev: wireless device pointer
4492 * @data: Vendor command data buffer
4493 * @data_len: Buffer length
4494 *
4495 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4496 *
4497 * Return: Error code.
4498 */
4499static int
4500__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4501 struct wireless_dev *wdev,
4502 const void *data,
4503 int data_len)
4504{
4505 struct net_device *dev = wdev->netdev;
4506 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4507 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4508 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4509 int ret_val = 0;
4510 u32 modulated_dtim;
4511 u16 stats_avg_factor;
4512 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304513 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004514 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004515 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304516 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304517 int attr_len;
4518 int access_policy = 0;
4519 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4520 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304521 uint16_t scan_ie_len = 0;
4522 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304523 struct sir_set_tx_rx_aggregation_size request;
4524 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004525 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004526 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004527 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304528 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304529
Jeff Johnson1f61b612016-02-12 16:28:33 -08004530 ENTER_DEV(dev);
4531
Anurag Chouhan6d760662016-02-20 16:05:43 +05304532 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 hdd_err("Command not allowed in FTM mode");
4534 return -EPERM;
4535 }
4536
4537 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304538 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004539 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540
4541 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4542 data, data_len,
4543 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004544 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004545 return -EINVAL;
4546 }
4547
Krunal Sonie3531942016-04-12 17:43:53 -07004548 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4549 ftm_capab = nla_get_u32(tb[
4550 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4551 hdd_ctx->config->fine_time_meas_cap =
4552 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4553 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304554 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004555 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004556 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4557 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004558 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004559 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4560 hdd_ctx->config->fine_time_meas_cap);
4561 }
4562
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4564 modulated_dtim = nla_get_u32(
4565 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4566
4567 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4568 adapter->sessionId,
4569 modulated_dtim);
4570
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304571 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004572 ret_val = -EPERM;
4573 }
4574
Kapil Gupta6213c012016-09-02 19:39:09 +05304575 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4576 qpower = nla_get_u8(
4577 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4578 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4579 ret_val = -EINVAL;
4580 }
4581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4583 stats_avg_factor = nla_get_u16(
4584 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4585 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4586 adapter->sessionId,
4587 stats_avg_factor);
4588
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304589 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004590 ret_val = -EPERM;
4591 }
4592
4593
4594 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4595 guard_time = nla_get_u32(
4596 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4597 status = sme_configure_guard_time(hdd_ctx->hHal,
4598 adapter->sessionId,
4599 guard_time);
4600
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304601 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004602 ret_val = -EPERM;
4603 }
4604
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304605 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4606 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4607 attr_len = nla_len(
4608 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4609 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004610 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304611 attr_len);
4612 return -EINVAL;
4613 }
4614
4615 nla_memcpy(&vendor_ie,
4616 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4617 attr_len);
4618 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004619 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304620 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304621 }
4622
4623 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4624 access_policy = (int) nla_get_u32(
4625 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4626 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4627 (access_policy >
4628 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004629 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304630 access_policy);
4631 return -EINVAL;
4632 }
4633 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004634 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304635 access_policy);
4636 }
4637
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004638 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4639 retry = nla_get_u8(tb[
4640 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4641 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4642 CFG_NON_AGG_RETRY_MAX : retry;
4643 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4644 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4645 retry, PDEV_CMD);
4646 }
4647
4648 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4649 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4650 retry = retry > CFG_AGG_RETRY_MAX ?
4651 CFG_AGG_RETRY_MAX : retry;
4652
4653 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4654 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4655 CFG_AGG_RETRY_MIN : retry;
4656 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4657 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4658 retry, PDEV_CMD);
4659 }
4660
4661 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4662 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4663 retry = retry > CFG_MGMT_RETRY_MAX ?
4664 CFG_MGMT_RETRY_MAX : retry;
4665 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4666 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4667 retry, PDEV_CMD);
4668 }
4669
4670 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4671 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4672 retry = retry > CFG_CTRL_RETRY_MAX ?
4673 CFG_CTRL_RETRY_MAX : retry;
4674 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4675 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4676 retry, PDEV_CMD);
4677 }
4678
4679 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4680 delay = nla_get_u8(tb[
4681 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4682 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4683 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004684 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004685 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4686 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004687 abs_delay, PDEV_CMD);
4688 }
4689
4690 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4691 abs_delay = nla_get_u8(tb[
4692 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4693 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4694 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4695 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004696 }
4697
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304698 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4699 tx_fail_count = nla_get_u32(
4700 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4701 if (tx_fail_count) {
4702 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4703 adapter->sessionId, tx_fail_count);
4704 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004705 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304706 status);
4707 return -EINVAL;
4708 }
4709 }
4710 }
4711
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304712 if (vendor_ie_present && access_policy_present) {
4713 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4714 access_policy =
4715 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304716 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304717 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304718 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304719
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004720 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304721 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4722 adapter->sessionId, &vendor_ie[0],
4723 access_policy);
4724 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004725 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304726 return -EINVAL;
4727 }
4728 }
4729
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304730 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4731 set_value = nla_get_u8(
4732 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004733 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304734 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4735 }
4736
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304737 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4738 scan_ie_len = nla_len(
4739 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004740 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304741 scan_ie_len, adapter->sessionId,
4742 adapter->device_mode);
4743 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4744 scan_ie = (uint8_t *) nla_data(tb
4745 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304746
4747 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4748 scan_ie_len))
4749 hdd_err("Failed to save default scan IEs");
4750
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304751 if (adapter->device_mode == QDF_STA_MODE) {
4752 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4753 adapter->sessionId, scan_ie,
4754 scan_ie_len);
4755 if (QDF_STATUS_SUCCESS != status)
4756 ret_val = -EPERM;
4757 }
4758 } else
4759 ret_val = -EPERM;
4760 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304761
4762 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4763 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4764 /* if one is specified, both must be specified */
4765 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4766 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4767 hdd_err("Both TX and RX MPDU Aggregation required");
4768 return -EINVAL;
4769 }
4770
4771 request.tx_aggregation_size = nla_get_u8(
4772 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4773 request.rx_aggregation_size = nla_get_u8(
4774 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4775 request.vdev_id = adapter->sessionId;
4776
4777 if (request.tx_aggregation_size >=
4778 CFG_TX_AGGREGATION_SIZE_MIN &&
4779 request.tx_aggregation_size <=
4780 CFG_TX_AGGREGATION_SIZE_MAX &&
4781 request.rx_aggregation_size >=
4782 CFG_RX_AGGREGATION_SIZE_MIN &&
4783 request.rx_aggregation_size <=
4784 CFG_RX_AGGREGATION_SIZE_MAX) {
4785 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4786 if (qdf_status != QDF_STATUS_SUCCESS) {
4787 hdd_err("failed to set aggr sizes err %d",
4788 qdf_status);
4789 ret_val = -EPERM;
4790 }
4791 } else {
4792 hdd_err("TX %d RX %d MPDU aggr size not in range",
4793 request.tx_aggregation_size,
4794 request.rx_aggregation_size);
4795 ret_val = -EINVAL;
4796 }
4797 }
4798
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304799 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4800 uint8_t ignore_assoc_disallowed;
4801
4802 ignore_assoc_disallowed
4803 = nla_get_u8(tb[
4804 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004805 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304806 ignore_assoc_disallowed);
4807 if ((ignore_assoc_disallowed <
4808 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4809 (ignore_assoc_disallowed >
4810 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4811 return -EPERM;
4812
4813 sme_update_session_param(hdd_ctx->hHal,
4814 adapter->sessionId,
4815 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4816 ignore_assoc_disallowed);
4817 }
4818
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 return ret_val;
4820}
4821
4822/**
4823 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4824 * vendor command
4825 *
4826 * @wiphy: wiphy device pointer
4827 * @wdev: wireless device pointer
4828 * @data: Vendor command data buffer
4829 * @data_len: Buffer length
4830 *
4831 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4832 *
4833 * Return: EOK or other error codes.
4834 */
4835static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4836 struct wireless_dev *wdev,
4837 const void *data,
4838 int data_len)
4839{
4840 int ret;
4841
4842 cds_ssr_protect(__func__);
4843 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4844 data, data_len);
4845 cds_ssr_unprotect(__func__);
4846
4847 return ret;
4848}
4849
4850static const struct
4851nla_policy
4852qca_wlan_vendor_wifi_logger_start_policy
4853[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4854 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4855 = {.type = NLA_U32 },
4856 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4857 = {.type = NLA_U32 },
4858 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4859 = {.type = NLA_U32 },
4860};
4861
4862/**
4863 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4864 * or disable the collection of packet statistics from the firmware
4865 * @wiphy: WIPHY structure pointer
4866 * @wdev: Wireless device structure pointer
4867 * @data: Pointer to the data received
4868 * @data_len: Length of the data received
4869 *
4870 * This function enables or disables the collection of packet statistics from
4871 * the firmware
4872 *
4873 * Return: 0 on success and errno on failure
4874 */
4875static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4876 struct wireless_dev *wdev,
4877 const void *data,
4878 int data_len)
4879{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304880 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4882 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4883 struct sir_wifi_start_log start_log;
4884
Jeff Johnson1f61b612016-02-12 16:28:33 -08004885 ENTER_DEV(wdev->netdev);
4886
Anurag Chouhan6d760662016-02-20 16:05:43 +05304887 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 hdd_err("Command not allowed in FTM mode");
4889 return -EPERM;
4890 }
4891
4892 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304893 if (status)
4894 return status;
4895
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304896 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4897 hdd_err("Driver Modules are closed, can not start logger");
4898 return -EINVAL;
4899 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900
4901 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4902 data, data_len,
4903 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004904 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 return -EINVAL;
4906 }
4907
4908 /* Parse and fetch ring id */
4909 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
4913 start_log.ring_id = nla_get_u32(
4914 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004915 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916
4917 /* Parse and fetch verbose level */
4918 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004919 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920 return -EINVAL;
4921 }
4922 start_log.verbose_level = nla_get_u32(
4923 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004924 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925
4926 /* Parse and fetch flag */
4927 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004928 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 return -EINVAL;
4930 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304931 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004933 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304935 /* size is buff size which can be set using iwpriv command*/
4936 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304937 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4940
4941 if (start_log.ring_id == RING_ID_WAKELOCK) {
4942 /* Start/stop wakelock events */
4943 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4944 cds_set_wakelock_logging(true);
4945 else
4946 cds_set_wakelock_logging(false);
4947 return 0;
4948 }
4949
4950 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304951 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004952 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953 status);
4954 return -EINVAL;
4955 }
4956 return 0;
4957}
4958
4959/**
4960 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4961 * or disable the collection of packet statistics from the firmware
4962 * @wiphy: WIPHY structure pointer
4963 * @wdev: Wireless device structure pointer
4964 * @data: Pointer to the data received
4965 * @data_len: Length of the data received
4966 *
4967 * This function is used to enable or disable the collection of packet
4968 * statistics from the firmware
4969 *
4970 * Return: 0 on success and errno on failure
4971 */
4972static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4973 struct wireless_dev *wdev,
4974 const void *data,
4975 int data_len)
4976{
4977 int ret = 0;
4978
4979 cds_ssr_protect(__func__);
4980 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4981 wdev, data, data_len);
4982 cds_ssr_unprotect(__func__);
4983
4984 return ret;
4985}
4986
4987static const struct
4988nla_policy
4989qca_wlan_vendor_wifi_logger_get_ring_data_policy
4990[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4991 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4992 = {.type = NLA_U32 },
4993};
4994
4995/**
4996 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4997 * @wiphy: WIPHY structure pointer
4998 * @wdev: Wireless device structure pointer
4999 * @data: Pointer to the data received
5000 * @data_len: Length of the data received
5001 *
5002 * This function is used to flush or retrieve the per packet statistics from
5003 * the driver
5004 *
5005 * Return: 0 on success and errno on failure
5006 */
5007static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5008 struct wireless_dev *wdev,
5009 const void *data,
5010 int data_len)
5011{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305012 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013 uint32_t ring_id;
5014 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5015 struct nlattr *tb
5016 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5017
Jeff Johnson1f61b612016-02-12 16:28:33 -08005018 ENTER_DEV(wdev->netdev);
5019
Anurag Chouhan6d760662016-02-20 16:05:43 +05305020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 hdd_err("Command not allowed in FTM mode");
5022 return -EPERM;
5023 }
5024
5025 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305026 if (status)
5027 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028
5029 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5030 data, data_len,
5031 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005032 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033 return -EINVAL;
5034 }
5035
5036 /* Parse and fetch ring id */
5037 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005038 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039 return -EINVAL;
5040 }
5041
5042 ring_id = nla_get_u32(
5043 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5044
5045 if (ring_id == RING_ID_PER_PACKET_STATS) {
5046 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005047 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305048 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5049 /*
5050 * As part of DRIVER ring ID, flush both driver and fw logs.
5051 * For other Ring ID's driver doesn't have any rings to flush
5052 */
5053 hdd_notice("Bug report triggered by framework");
5054
5055 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5056 WLAN_LOG_INDICATOR_FRAMEWORK,
5057 WLAN_LOG_REASON_CODE_UNUSED,
5058 true, false);
5059 if (QDF_STATUS_SUCCESS != status) {
5060 hdd_err("Failed to trigger bug report");
5061 return -EINVAL;
5062 }
5063 } else {
5064 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5065 WLAN_LOG_INDICATOR_FRAMEWORK,
5066 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005067 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005068 return 0;
5069}
5070
5071/**
5072 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5073 * @wiphy: WIPHY structure pointer
5074 * @wdev: Wireless device structure pointer
5075 * @data: Pointer to the data received
5076 * @data_len: Length of the data received
5077 *
5078 * This function is used to flush or retrieve the per packet statistics from
5079 * the driver
5080 *
5081 * Return: 0 on success and errno on failure
5082 */
5083static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5084 struct wireless_dev *wdev,
5085 const void *data,
5086 int data_len)
5087{
5088 int ret = 0;
5089
5090 cds_ssr_protect(__func__);
5091 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5092 wdev, data, data_len);
5093 cds_ssr_unprotect(__func__);
5094
5095 return ret;
5096}
5097
5098#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5099/**
5100 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5101 * @hdd_ctx: HDD context
5102 * @request_id: [input] request id
5103 * @pattern_id: [output] pattern id
5104 *
5105 * This function loops through request id to pattern id array
5106 * if the slot is available, store the request id and return pattern id
5107 * if entry exists, return the pattern id
5108 *
5109 * Return: 0 on success and errno on failure
5110 */
5111static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5112 uint32_t request_id,
5113 uint8_t *pattern_id)
5114{
5115 uint32_t i;
5116
5117 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5118 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5119 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5120 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5121 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5122 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5123 return 0;
5124 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5125 request_id) {
5126 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5127 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5128 return 0;
5129 }
5130 }
5131 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5132 return -EINVAL;
5133}
5134
5135/**
5136 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5137 * @hdd_ctx: HDD context
5138 * @request_id: [input] request id
5139 * @pattern_id: [output] pattern id
5140 *
5141 * This function loops through request id to pattern id array
5142 * reset request id to 0 (slot available again) and
5143 * return pattern id
5144 *
5145 * Return: 0 on success and errno on failure
5146 */
5147static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5148 uint32_t request_id,
5149 uint8_t *pattern_id)
5150{
5151 uint32_t i;
5152
5153 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5154 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5155 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5156 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5157 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5158 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5159 return 0;
5160 }
5161 }
5162 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5163 return -EINVAL;
5164}
5165
5166
5167/*
5168 * define short names for the global vendor params
5169 * used by __wlan_hdd_cfg80211_offloaded_packets()
5170 */
5171#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5172#define PARAM_REQUEST_ID \
5173 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5174#define PARAM_CONTROL \
5175 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5176#define PARAM_IP_PACKET \
5177 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5178#define PARAM_SRC_MAC_ADDR \
5179 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5180#define PARAM_DST_MAC_ADDR \
5181 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5182#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5183
5184/**
5185 * wlan_hdd_add_tx_ptrn() - add tx pattern
5186 * @adapter: adapter pointer
5187 * @hdd_ctx: hdd context
5188 * @tb: nl attributes
5189 *
5190 * This function reads the NL attributes and forms a AddTxPtrn message
5191 * posts it to SME.
5192 *
5193 */
5194static int
5195wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5196 struct nlattr **tb)
5197{
5198 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305199 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200 uint32_t request_id, ret, len;
5201 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305202 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 uint16_t eth_type = htons(ETH_P_IP);
5204
5205 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005206 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207 return -ENOTSUPP;
5208 }
5209
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305210 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005212 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005213 return -ENOMEM;
5214 }
5215
5216 /* Parse and fetch request Id */
5217 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005218 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219 goto fail;
5220 }
5221
5222 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5223 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005224 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225 return -EINVAL;
5226 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005227 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228
5229 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005230 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 goto fail;
5232 }
5233 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005234 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005236 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237 goto fail;
5238 }
5239
5240 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005241 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005242 goto fail;
5243 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005244 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305245 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005246 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005247 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248
Anurag Chouhanc5548422016-02-24 18:33:27 +05305249 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005250 &adapter->macAddressCurrent)) {
5251 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 goto fail;
5253 }
5254
5255 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005256 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 goto fail;
5258 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305259 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005260 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005261 MAC_ADDR_ARRAY(dst_addr.bytes));
5262
5263 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005264 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265 goto fail;
5266 }
5267 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005268 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005269
5270 if (add_req->ucPtrnSize < 0 ||
5271 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5272 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005273 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005274 add_req->ucPtrnSize);
5275 goto fail;
5276 }
5277
5278 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305279 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305280 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305281 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305282 QDF_MAC_ADDR_SIZE);
5283 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305284 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 len += 2;
5286
5287 /*
5288 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5289 * ------------------------------------------------------------
5290 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5291 * ------------------------------------------------------------
5292 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305293 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005294 nla_data(tb[PARAM_IP_PACKET]),
5295 add_req->ucPtrnSize);
5296 add_req->ucPtrnSize += len;
5297
5298 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5299 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005300 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301 goto fail;
5302 }
5303 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005304 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005305
5306 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305307 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005308 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309 goto fail;
5310 }
5311
5312 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305313 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 return 0;
5315
5316fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305317 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005318 return -EINVAL;
5319}
5320
5321/**
5322 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5323 * @adapter: adapter pointer
5324 * @hdd_ctx: hdd context
5325 * @tb: nl attributes
5326 *
5327 * This function reads the NL attributes and forms a DelTxPtrn message
5328 * posts it to SME.
5329 *
5330 */
5331static int
5332wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5333 struct nlattr **tb)
5334{
5335 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305336 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005337 uint32_t request_id, ret;
5338 uint8_t pattern_id = 0;
5339
5340 /* Parse and fetch request Id */
5341 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005342 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 return -EINVAL;
5344 }
5345 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5346 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005347 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 return -EINVAL;
5349 }
5350
5351 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5352 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005353 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 return -EINVAL;
5355 }
5356
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305357 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005359 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005360 return -ENOMEM;
5361 }
5362
Anurag Chouhanc5548422016-02-24 18:33:27 +05305363 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005364 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005365 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005366 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 request_id, del_req->ucPtrnId);
5368
5369 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305370 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005371 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 goto fail;
5373 }
5374
5375 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305376 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 return 0;
5378
5379fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305380 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381 return -EINVAL;
5382}
5383
5384
5385/**
5386 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5387 * @wiphy: Pointer to wireless phy
5388 * @wdev: Pointer to wireless device
5389 * @data: Pointer to data
5390 * @data_len: Data length
5391 *
5392 * Return: 0 on success, negative errno on failure
5393 */
5394static int
5395__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5396 struct wireless_dev *wdev,
5397 const void *data,
5398 int data_len)
5399{
5400 struct net_device *dev = wdev->netdev;
5401 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5402 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5403 struct nlattr *tb[PARAM_MAX + 1];
5404 uint8_t control;
5405 int ret;
5406 static const struct nla_policy policy[PARAM_MAX + 1] = {
5407 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5408 [PARAM_CONTROL] = { .type = NLA_U32 },
5409 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305410 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305412 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 [PARAM_PERIOD] = { .type = NLA_U32 },
5414 };
5415
Jeff Johnson1f61b612016-02-12 16:28:33 -08005416 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417
Anurag Chouhan6d760662016-02-20 16:05:43 +05305418 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005419 hdd_err("Command not allowed in FTM mode");
5420 return -EPERM;
5421 }
5422
5423 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305424 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426
5427 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005428 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 return -ENOTSUPP;
5430 }
5431
5432 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005433 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 return -EINVAL;
5435 }
5436
5437 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005438 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 return -EINVAL;
5440 }
5441 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005442 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443
5444 if (control == WLAN_START_OFFLOADED_PACKETS)
5445 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005446 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005448
5449 hdd_err("Invalid control: %d", control);
5450
5451 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452}
5453
5454/*
5455 * done with short names for the global vendor params
5456 * used by __wlan_hdd_cfg80211_offloaded_packets()
5457 */
5458#undef PARAM_MAX
5459#undef PARAM_REQUEST_ID
5460#undef PARAM_CONTROL
5461#undef PARAM_IP_PACKET
5462#undef PARAM_SRC_MAC_ADDR
5463#undef PARAM_DST_MAC_ADDR
5464#undef PARAM_PERIOD
5465
5466/**
5467 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5468 * @wiphy: wiphy structure pointer
5469 * @wdev: Wireless device structure pointer
5470 * @data: Pointer to the data received
5471 * @data_len: Length of @data
5472 *
5473 * Return: 0 on success; errno on failure
5474 */
5475static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5476 struct wireless_dev *wdev,
5477 const void *data,
5478 int data_len)
5479{
5480 int ret = 0;
5481
5482 cds_ssr_protect(__func__);
5483 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5484 wdev, data, data_len);
5485 cds_ssr_unprotect(__func__);
5486
5487 return ret;
5488}
5489#endif
5490
5491/*
5492 * define short names for the global vendor params
5493 * used by __wlan_hdd_cfg80211_monitor_rssi()
5494 */
5495#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5496#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5497#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5498#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5499#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5500
5501/**
5502 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5503 * @wiphy: Pointer to wireless phy
5504 * @wdev: Pointer to wireless device
5505 * @data: Pointer to data
5506 * @data_len: Data length
5507 *
5508 * Return: 0 on success, negative errno on failure
5509 */
5510static int
5511__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5512 struct wireless_dev *wdev,
5513 const void *data,
5514 int data_len)
5515{
5516 struct net_device *dev = wdev->netdev;
5517 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5518 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5519 struct nlattr *tb[PARAM_MAX + 1];
5520 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305521 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 int ret;
5523 uint32_t control;
5524 static const struct nla_policy policy[PARAM_MAX + 1] = {
5525 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5526 [PARAM_CONTROL] = { .type = NLA_U32 },
5527 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5528 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5529 };
5530
Jeff Johnson1f61b612016-02-12 16:28:33 -08005531 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305533 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5534 hdd_err("invalid session id: %d", adapter->sessionId);
5535 return -EINVAL;
5536 }
5537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305539 if (ret)
5540 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541
5542 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005543 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 return -ENOTSUPP;
5545 }
5546
5547 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005548 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 return -EINVAL;
5550 }
5551
5552 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005553 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005554 return -EINVAL;
5555 }
5556
5557 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005558 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 return -EINVAL;
5560 }
5561
5562 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5563 req.session_id = adapter->sessionId;
5564 control = nla_get_u32(tb[PARAM_CONTROL]);
5565
5566 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5567 req.control = true;
5568 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005569 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 return -EINVAL;
5571 }
5572
5573 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 return -EINVAL;
5576 }
5577
5578 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5579 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5580
5581 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005582 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583 req.min_rssi, req.max_rssi);
5584 return -EINVAL;
5585 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005586 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005587 req.min_rssi, req.max_rssi);
5588
5589 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5590 req.control = false;
5591 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005592 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 return -EINVAL;
5594 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005595 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005596 req.request_id, req.session_id, req.control);
5597
5598 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305599 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005600 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005601 return -EINVAL;
5602 }
5603
5604 return 0;
5605}
5606
5607/*
5608 * done with short names for the global vendor params
5609 * used by __wlan_hdd_cfg80211_monitor_rssi()
5610 */
5611#undef PARAM_MAX
5612#undef PARAM_CONTROL
5613#undef PARAM_REQUEST_ID
5614#undef PARAM_MAX_RSSI
5615#undef PARAM_MIN_RSSI
5616
5617/**
5618 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5619 * @wiphy: wiphy structure pointer
5620 * @wdev: Wireless device structure pointer
5621 * @data: Pointer to the data received
5622 * @data_len: Length of @data
5623 *
5624 * Return: 0 on success; errno on failure
5625 */
5626static int
5627wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5628 const void *data, int data_len)
5629{
5630 int ret;
5631
5632 cds_ssr_protect(__func__);
5633 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5634 cds_ssr_unprotect(__func__);
5635
5636 return ret;
5637}
5638
5639/**
5640 * hdd_rssi_threshold_breached() - rssi breached NL event
5641 * @hddctx: HDD context
5642 * @data: rssi breached event data
5643 *
5644 * This function reads the rssi breached event %data and fill in the skb with
5645 * NL attributes and send up the NL event.
5646 *
5647 * Return: none
5648 */
5649void hdd_rssi_threshold_breached(void *hddctx,
5650 struct rssi_breach_event *data)
5651{
5652 hdd_context_t *hdd_ctx = hddctx;
5653 struct sk_buff *skb;
5654
5655 ENTER();
5656
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305657 if (wlan_hdd_validate_context(hdd_ctx))
5658 return;
5659 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005660 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661 return;
5662 }
5663
5664 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5665 NULL,
5666 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5667 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5668 GFP_KERNEL);
5669
5670 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005671 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 return;
5673 }
5674
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005675 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005676 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005677 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5679
5680 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5681 data->request_id) ||
5682 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5683 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5684 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5685 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005686 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005687 goto fail;
5688 }
5689
5690 cfg80211_vendor_event(skb, GFP_KERNEL);
5691 return;
5692
5693fail:
5694 kfree_skb(skb);
5695 return;
5696}
5697
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305698static const struct nla_policy
5699ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5700 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5701};
5702
5703/**
5704 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5705 * @wiphy: Pointer to wireless phy
5706 * @wdev: Pointer to wireless device
5707 * @data: Pointer to data
5708 * @data_len: Length of @data
5709 *
5710 * Return: 0 on success, negative errno on failure
5711 */
5712static int
5713__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5714 struct wireless_dev *wdev,
5715 const void *data, int data_len)
5716{
5717 int status;
5718 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5719 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005720 struct net_device *dev = wdev->netdev;
5721 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305722
5723 ENTER_DEV(wdev->netdev);
5724
5725 status = wlan_hdd_validate_context(pHddCtx);
5726 if (0 != status)
5727 return status;
5728 if (!pHddCtx->config->fhostNSOffload) {
5729 hdd_err("ND Offload not supported");
5730 return -EINVAL;
5731 }
5732
5733 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5734 (struct nlattr *)data,
5735 data_len, ns_offload_set_policy)) {
5736 hdd_err("nla_parse failed");
5737 return -EINVAL;
5738 }
5739
5740 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5741 hdd_err("ND Offload flag attribute not present");
5742 return -EINVAL;
5743 }
5744
5745 pHddCtx->ns_offload_enable =
5746 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5747
Dustin Brownd8279d22016-09-07 14:52:57 -07005748 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305749 if (pHddCtx->ns_offload_enable)
5750 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5751 else
5752 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005753
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305754 return 0;
5755}
5756
5757/**
5758 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5759 * @wiphy: pointer to wireless wiphy structure.
5760 * @wdev: pointer to wireless_dev structure.
5761 * @data: Pointer to the data to be passed via vendor interface
5762 * @data_len:Length of the data to be passed
5763 *
5764 * Return: Return the Success or Failure code.
5765 */
5766static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5767 struct wireless_dev *wdev,
5768 const void *data, int data_len)
5769{
5770 int ret;
5771
5772 cds_ssr_protect(__func__);
5773 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5774 cds_ssr_unprotect(__func__);
5775
5776 return ret;
5777}
5778
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5780 * @wiphy: Pointer to wireless phy
5781 * @wdev: Pointer to wireless device
5782 * @data: Pointer to data
5783 * @data_len: Data length
5784 *
5785 * This function return the preferred frequency list generated by the policy
5786 * manager.
5787 *
5788 * Return: success or failure code
5789 */
5790static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5791 struct wireless_dev
5792 *wdev, const void *data,
5793 int data_len)
5794{
5795 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5796 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305797 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305798 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305800 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005801 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005802 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5803 struct sk_buff *reply_skb;
5804
Jeff Johnson1f61b612016-02-12 16:28:33 -08005805 ENTER_DEV(wdev->netdev);
5806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005807 ret = wlan_hdd_validate_context(hdd_ctx);
5808 if (ret)
5809 return -EINVAL;
5810
5811 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5812 data, data_len, NULL)) {
5813 hdd_err("Invalid ATTR");
5814 return -EINVAL;
5815 }
5816
5817 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5818 hdd_err("attr interface type failed");
5819 return -EINVAL;
5820 }
5821
5822 intf_mode = nla_get_u32(tb
5823 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5824
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005825 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005826 hdd_err("Invalid interface type");
5827 return -EINVAL;
5828 }
5829
5830 hdd_debug("Userspace requested pref freq list");
5831
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005832 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5833 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305834 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305835 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836 hdd_err("Get pcl failed");
5837 return -EINVAL;
5838 }
5839
5840 /* convert channel number to frequency */
5841 for (i = 0; i < pcl_len; i++) {
5842 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5843 freq_list[i] =
5844 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005845 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005846 else
5847 freq_list[i] =
5848 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005849 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 }
5851
5852 /* send the freq_list back to supplicant */
5853 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5854 sizeof(u32) *
5855 pcl_len +
5856 NLMSG_HDRLEN);
5857
5858 if (!reply_skb) {
5859 hdd_err("Allocate reply_skb failed");
5860 return -EINVAL;
5861 }
5862
5863 if (nla_put_u32(reply_skb,
5864 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5865 intf_mode) ||
5866 nla_put(reply_skb,
5867 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5868 sizeof(uint32_t) * pcl_len,
5869 freq_list)) {
5870 hdd_err("nla put fail");
5871 kfree_skb(reply_skb);
5872 return -EINVAL;
5873 }
5874
5875 return cfg80211_vendor_cmd_reply(reply_skb);
5876}
5877
5878/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5879 * @wiphy: Pointer to wireless phy
5880 * @wdev: Pointer to wireless device
5881 * @data: Pointer to data
5882 * @data_len: Data length
5883 *
5884 * This function return the preferred frequency list generated by the policy
5885 * manager.
5886 *
5887 * Return: success or failure code
5888 */
5889static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5890 struct wireless_dev
5891 *wdev, const void *data,
5892 int data_len)
5893{
5894 int ret = 0;
5895
5896 cds_ssr_protect(__func__);
5897 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5898 data, data_len);
5899 cds_ssr_unprotect(__func__);
5900
5901 return ret;
5902}
5903
5904/**
5905 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5906 * @wiphy: Pointer to wireless phy
5907 * @wdev: Pointer to wireless device
5908 * @data: Pointer to data
5909 * @data_len: Data length
5910 *
5911 * Return: 0 on success, negative errno on failure
5912 */
5913static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5914 struct wireless_dev *wdev,
5915 const void *data,
5916 int data_len)
5917{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305918 struct net_device *ndev = wdev->netdev;
5919 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5921 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005922 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005923 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5924 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005925
Jeff Johnson1f61b612016-02-12 16:28:33 -08005926 ENTER_DEV(ndev);
5927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 ret = wlan_hdd_validate_context(hdd_ctx);
5929 if (ret)
5930 return ret;
5931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005932 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5933 data, data_len, NULL)) {
5934 hdd_err("Invalid ATTR");
5935 return -EINVAL;
5936 }
5937
5938 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5939 hdd_err("attr interface type failed");
5940 return -EINVAL;
5941 }
5942
5943 intf_mode = nla_get_u32(tb
5944 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5945
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005946 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005947 hdd_err("Invalid interface type");
5948 return -EINVAL;
5949 }
5950
5951 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5952 hdd_err("attr probable freq failed");
5953 return -EINVAL;
5954 }
5955
5956 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5957 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5958
5959 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005960 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005961 channel_hint, HW_MODE_20_MHZ)) {
5962 hdd_err("Set channel hint failed due to concurrency check");
5963 return -EINVAL;
5964 }
5965
Krunal Soni09e55032016-06-07 10:06:55 -07005966 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5967 hdd_warn("Remain On Channel Pending");
5968
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005969 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005970 if (!QDF_IS_STATUS_SUCCESS(ret))
5971 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005973 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5974 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005975 SIR_UPDATE_REASON_SET_OPER_CHAN);
5976 if (QDF_STATUS_E_FAILURE == ret) {
5977 /* return in the failure case */
5978 hdd_err("ERROR: connections update failed!!");
5979 return -EINVAL;
5980 }
5981
5982 if (QDF_STATUS_SUCCESS == ret) {
5983 /*
5984 * Success is the only case for which we expect hw mode
5985 * change to take place, hence we need to wait.
5986 * For any other return value it should be a pass
5987 * through
5988 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005989 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005990 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5991 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005992 return -EINVAL;
5993 }
5994
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005995 }
5996
5997 return 0;
5998}
5999
6000/**
6001 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6002 * @wiphy: Pointer to wireless phy
6003 * @wdev: Pointer to wireless device
6004 * @data: Pointer to data
6005 * @data_len: Data length
6006 *
6007 * Return: 0 on success, negative errno on failure
6008 */
6009static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6010 struct wireless_dev *wdev,
6011 const void *data,
6012 int data_len)
6013{
6014 int ret = 0;
6015
6016 cds_ssr_protect(__func__);
6017 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6018 data, data_len);
6019 cds_ssr_unprotect(__func__);
6020
6021 return ret;
6022}
6023
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306024static const struct
6025nla_policy
6026qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6027 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6028};
6029
6030/**
6031 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6032 * @wiphy: WIPHY structure pointer
6033 * @wdev: Wireless device structure pointer
6034 * @data: Pointer to the data received
6035 * @data_len: Length of the data received
6036 *
6037 * This function is used to get link properties like nss, rate flags and
6038 * operating frequency for the active connection with the given peer.
6039 *
6040 * Return: 0 on success and errno on failure
6041 */
6042static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6043 struct wireless_dev *wdev,
6044 const void *data,
6045 int data_len)
6046{
6047 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6048 struct net_device *dev = wdev->netdev;
6049 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6050 hdd_station_ctx_t *hdd_sta_ctx;
6051 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306052 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306053 uint32_t sta_id;
6054 struct sk_buff *reply_skb;
6055 uint32_t rate_flags = 0;
6056 uint8_t nss;
6057 uint8_t final_rate_flags = 0;
6058 uint32_t freq;
6059
Jeff Johnson1f61b612016-02-12 16:28:33 -08006060 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306061
Anurag Chouhan6d760662016-02-20 16:05:43 +05306062 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306063 hdd_err("Command not allowed in FTM mode");
6064 return -EPERM;
6065 }
6066
6067 if (0 != wlan_hdd_validate_context(hdd_ctx))
6068 return -EINVAL;
6069
6070 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6071 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006072 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306073 return -EINVAL;
6074 }
6075
6076 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006077 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306078 adapter->device_mode);
6079 return -EINVAL;
6080 }
6081
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306082 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306083 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006084 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306085 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6086
Krunal Sonib4326f22016-03-10 13:05:51 -08006087 if (adapter->device_mode == QDF_STA_MODE ||
6088 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306089 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6090 if ((hdd_sta_ctx->conn_info.connState !=
6091 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306092 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306093 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006094 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306095 MAC_ADDR_ARRAY(peer_mac));
6096 return -EINVAL;
6097 }
6098
6099 nss = hdd_sta_ctx->conn_info.nss;
6100 freq = cds_chan_to_freq(
6101 hdd_sta_ctx->conn_info.operationChannel);
6102 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006103 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6104 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306105
6106 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6107 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306108 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306109 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306110 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306111 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306112 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306113 break;
6114 }
6115
6116 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006117 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306118 MAC_ADDR_ARRAY(peer_mac));
6119 return -EINVAL;
6120 }
6121
6122 nss = adapter->aStaInfo[sta_id].nss;
6123 freq = cds_chan_to_freq(
6124 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6125 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6126 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006127 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306128 MAC_ADDR_ARRAY(peer_mac));
6129 return -EINVAL;
6130 }
6131
6132 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6133 if (rate_flags & eHAL_TX_RATE_VHT80) {
6134 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006135#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306136 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006137#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306138 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6139 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006140#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306141 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006142#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306143 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6144 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6145 } else if (rate_flags &
6146 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6147 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006148#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306149 if (rate_flags & eHAL_TX_RATE_HT40)
6150 final_rate_flags |=
6151 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006152#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306153 }
6154
6155 if (rate_flags & eHAL_TX_RATE_SGI) {
6156 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6157 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6158 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6159 }
6160 }
6161
6162 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6163 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6164
6165 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006166 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306167 return -EINVAL;
6168 }
6169
6170 if (nla_put_u8(reply_skb,
6171 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6172 nss) ||
6173 nla_put_u8(reply_skb,
6174 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6175 final_rate_flags) ||
6176 nla_put_u32(reply_skb,
6177 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6178 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006179 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306180 kfree_skb(reply_skb);
6181 return -EINVAL;
6182 }
6183
6184 return cfg80211_vendor_cmd_reply(reply_skb);
6185}
6186
6187/**
6188 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6189 * properties.
6190 * @wiphy: WIPHY structure pointer
6191 * @wdev: Wireless device structure pointer
6192 * @data: Pointer to the data received
6193 * @data_len: Length of the data received
6194 *
6195 * This function is used to get link properties like nss, rate flags and
6196 * operating frequency for the active connection with the given peer.
6197 *
6198 * Return: 0 on success and errno on failure
6199 */
6200static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6201 struct wireless_dev *wdev,
6202 const void *data,
6203 int data_len)
6204{
6205 int ret = 0;
6206
6207 cds_ssr_protect(__func__);
6208 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6209 wdev, data, data_len);
6210 cds_ssr_unprotect(__func__);
6211
6212 return ret;
6213}
6214
Peng Xu278d0122015-09-24 16:34:17 -07006215static const struct
6216nla_policy
6217qca_wlan_vendor_ota_test_policy
6218[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6219 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6220};
6221
6222/**
6223 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6224 * @wiphy: Pointer to wireless phy
6225 * @wdev: Pointer to wireless device
6226 * @data: Pointer to data
6227 * @data_len: Data length
6228 *
6229 * Return: 0 on success, negative errno on failure
6230 */
6231static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6232 struct wireless_dev *wdev,
6233 const void *data,
6234 int data_len)
6235{
6236 struct net_device *dev = wdev->netdev;
6237 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6238 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6239 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6240 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6241 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306242 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006243 uint32_t current_roam_state;
6244
Jeff Johnson1f61b612016-02-12 16:28:33 -08006245 ENTER_DEV(dev);
6246
Anurag Chouhan6d760662016-02-20 16:05:43 +05306247 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006248 hdd_err("Command not allowed in FTM mode");
6249 return -EPERM;
6250 }
6251
6252 if (0 != wlan_hdd_validate_context(hdd_ctx))
6253 return -EINVAL;
6254
6255 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6256 data, data_len,
6257 qca_wlan_vendor_ota_test_policy)) {
6258 hdd_err("invalid attr");
6259 return -EINVAL;
6260 }
6261
6262 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6263 hdd_err("attr ota test failed");
6264 return -EINVAL;
6265 }
6266
6267 ota_enable = nla_get_u8(
6268 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6269
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006270 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006271 if (ota_enable != 1) {
6272 hdd_err("Invalid value, only enable test mode is supported!");
6273 return -EINVAL;
6274 }
6275
6276 current_roam_state =
6277 sme_get_current_roam_state(hal, adapter->sessionId);
6278 status = sme_stop_roaming(hal, adapter->sessionId,
6279 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306280 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006281 hdd_err("Enable/Disable roaming failed");
6282 return -EINVAL;
6283 }
6284
6285 status = sme_ps_enable_disable(hal, adapter->sessionId,
6286 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306287 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006288 hdd_err("Enable/Disable power save failed");
6289 /* restore previous roaming setting */
6290 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6291 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6292 status = sme_start_roaming(hal, adapter->sessionId,
6293 eCsrHddIssued);
6294 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6295 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6296 status = sme_stop_roaming(hal, adapter->sessionId,
6297 eCsrHddIssued);
6298
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306299 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006300 hdd_err("Restoring roaming state failed");
6301
6302 return -EINVAL;
6303 }
6304
6305
6306 return 0;
6307}
6308
6309/**
6310 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6311 * @wiphy: Pointer to wireless phy
6312 * @wdev: Pointer to wireless device
6313 * @data: Pointer to data
6314 * @data_len: Data length
6315 *
6316 * Return: 0 on success, negative errno on failure
6317 */
6318static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6319 struct wireless_dev *wdev,
6320 const void *data,
6321 int data_len)
6322{
6323 int ret = 0;
6324
6325 cds_ssr_protect(__func__);
6326 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6327 cds_ssr_unprotect(__func__);
6328
6329 return ret;
6330}
6331
Peng Xu4d67c8f2015-10-16 16:02:26 -07006332/**
6333 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6334 * @wiphy: Pointer to wireless phy
6335 * @wdev: Pointer to wireless device
6336 * @data: Pointer to data
6337 * @data_len: Data length
6338 *
6339 * Return: 0 on success, negative errno on failure
6340 */
6341static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6342 struct wireless_dev *wdev,
6343 const void *data,
6344 int data_len)
6345{
6346 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6347 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006348 hdd_adapter_t *adapter;
6349 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006350 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6351 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006352 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006353
Jeff Johnson1f61b612016-02-12 16:28:33 -08006354 ENTER_DEV(dev);
6355
Peng Xu4d67c8f2015-10-16 16:02:26 -07006356 ret = wlan_hdd_validate_context(hdd_ctx);
6357 if (ret)
6358 return ret;
6359
6360 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6361
6362 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6363 data, data_len, NULL)) {
6364 hdd_err("Invalid ATTR");
6365 return -EINVAL;
6366 }
6367
6368 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6369 hdd_err("attr tx power scale failed");
6370 return -EINVAL;
6371 }
6372
6373 scale_value = nla_get_u8(tb
6374 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6375
6376 if (scale_value > MAX_TXPOWER_SCALE) {
6377 hdd_err("Invalid tx power scale level");
6378 return -EINVAL;
6379 }
6380
Peng Xu62c8c432016-05-09 15:23:02 -07006381 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006382
Peng Xu62c8c432016-05-09 15:23:02 -07006383 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006384 hdd_err("Set tx power scale failed");
6385 return -EINVAL;
6386 }
6387
6388 return 0;
6389}
6390
6391/**
6392 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6393 * @wiphy: Pointer to wireless phy
6394 * @wdev: Pointer to wireless device
6395 * @data: Pointer to data
6396 * @data_len: Data length
6397 *
6398 * Return: 0 on success, negative errno on failure
6399 */
6400static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6401 struct wireless_dev *wdev,
6402 const void *data,
6403 int data_len)
6404{
Peng Xu62c8c432016-05-09 15:23:02 -07006405 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006406
6407 cds_ssr_protect(__func__);
6408 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6409 data, data_len);
6410 cds_ssr_unprotect(__func__);
6411
6412 return ret;
6413}
6414
6415/**
6416 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6417 * @wiphy: Pointer to wireless phy
6418 * @wdev: Pointer to wireless device
6419 * @data: Pointer to data
6420 * @data_len: Data length
6421 *
6422 * Return: 0 on success, negative errno on failure
6423 */
6424static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6425 struct wireless_dev *wdev,
6426 const void *data,
6427 int data_len)
6428{
6429 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6430 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006431 hdd_adapter_t *adapter;
6432 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006433 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6434 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006435 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006436
Jeff Johnson1f61b612016-02-12 16:28:33 -08006437 ENTER_DEV(dev);
6438
Peng Xu4d67c8f2015-10-16 16:02:26 -07006439 ret = wlan_hdd_validate_context(hdd_ctx);
6440 if (ret)
6441 return ret;
6442
6443 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6444
6445 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6446 data, data_len, NULL)) {
6447 hdd_err("Invalid ATTR");
6448 return -EINVAL;
6449 }
6450
6451 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6452 hdd_err("attr tx power decrease db value failed");
6453 return -EINVAL;
6454 }
6455
6456 scale_value = nla_get_u8(tb
6457 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6458
Peng Xu62c8c432016-05-09 15:23:02 -07006459 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6460 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006461
Peng Xu62c8c432016-05-09 15:23:02 -07006462 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006463 hdd_err("Set tx power decrease db failed");
6464 return -EINVAL;
6465 }
6466
6467 return 0;
6468}
6469
6470/**
6471 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6472 * @wiphy: Pointer to wireless phy
6473 * @wdev: Pointer to wireless device
6474 * @data: Pointer to data
6475 * @data_len: Data length
6476 *
6477 * Return: 0 on success, negative errno on failure
6478 */
6479static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6480 struct wireless_dev *wdev,
6481 const void *data,
6482 int data_len)
6483{
Peng Xu62c8c432016-05-09 15:23:02 -07006484 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006485
6486 cds_ssr_protect(__func__);
6487 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6488 data, data_len);
6489 cds_ssr_unprotect(__func__);
6490
6491 return ret;
6492}
Peng Xu8fdaa492016-06-22 10:20:47 -07006493
6494/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306495 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6496 * @wiphy: Pointer to wireless phy
6497 * @wdev: Pointer to wireless device
6498 * @data: Pointer to data
6499 * @data_len: Data length
6500 *
6501 * Processes the conditional channel switch request and invokes the helper
6502 * APIs to process the channel switch request.
6503 *
6504 * Return: 0 on success, negative errno on failure
6505 */
6506static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6507 struct wireless_dev *wdev,
6508 const void *data,
6509 int data_len)
6510{
6511 int ret;
6512 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6513 struct net_device *dev = wdev->netdev;
6514 hdd_adapter_t *adapter;
6515 struct nlattr
6516 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6517 uint32_t freq_len, i;
6518 uint32_t *freq;
6519 uint8_t chans[QDF_MAX_NUM_CHAN];
6520
6521 ENTER_DEV(dev);
6522
6523 ret = wlan_hdd_validate_context(hdd_ctx);
6524 if (ret)
6525 return ret;
6526
6527 if (!hdd_ctx->config->enableDFSMasterCap) {
6528 hdd_err("DFS master capability is not present in the driver");
6529 return -EINVAL;
6530 }
6531
6532 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6533 hdd_err("Command not allowed in FTM mode");
6534 return -EPERM;
6535 }
6536
6537 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6538 if (adapter->device_mode != QDF_SAP_MODE) {
6539 hdd_err("Invalid device mode %d", adapter->device_mode);
6540 return -EINVAL;
6541 }
6542
6543 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6544 data, data_len, NULL)) {
6545 hdd_err("Invalid ATTR");
6546 return -EINVAL;
6547 }
6548
6549 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6550 hdd_err("Frequency list is missing");
6551 return -EINVAL;
6552 }
6553
6554 freq_len = nla_len(
6555 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6556 sizeof(uint32_t);
6557
6558 if (freq_len > QDF_MAX_NUM_CHAN) {
6559 hdd_err("insufficient space to hold channels");
6560 return -ENOMEM;
6561 }
6562
6563 hdd_debug("freq_len=%d", freq_len);
6564
6565 freq = nla_data(
6566 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6567
6568
6569 for (i = 0; i < freq_len; i++) {
6570 if (freq[i] == 0)
6571 chans[i] = 0;
6572 else
6573 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6574
6575 hdd_debug("freq[%d]=%d", i, freq[i]);
6576 }
6577
6578 /*
6579 * The input frequency list from user space is designed to be a
6580 * priority based frequency list. This is only to accommodate any
6581 * future request. But, current requirement is only to perform CAC
6582 * on a single channel. So, the first entry from the list is picked.
6583 *
6584 * If channel is zero, any channel in the available outdoor regulatory
6585 * domain will be selected.
6586 */
6587 ret = wlan_hdd_request_pre_cac(chans[0]);
6588 if (ret) {
6589 hdd_err("pre cac request failed with reason:%d", ret);
6590 return ret;
6591 }
6592
6593 return 0;
6594}
6595
6596/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006597 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6598 * @wiphy: Pointer to wireless phy
6599 * @wdev: Pointer to wireless device
6600 * @data: Pointer to data
6601 * @data_len: Data length
6602 *
6603 * This function is to process the p2p listen offload start vendor
6604 * command. It parses the input parameters and invoke WMA API to
6605 * send the command to firmware.
6606 *
6607 * Return: 0 on success, negative errno on failure
6608 */
6609static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6610 struct wireless_dev *wdev,
6611 const void *data,
6612 int data_len)
6613{
6614 int ret;
6615 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6616 struct net_device *dev = wdev->netdev;
6617 hdd_adapter_t *adapter;
6618 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6619 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006620
6621 ENTER_DEV(dev);
6622
6623 ret = wlan_hdd_validate_context(hdd_ctx);
6624 if (ret)
6625 return ret;
6626
6627 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6628 hdd_err("Command not allowed in FTM mode");
6629 return -EPERM;
6630 }
6631
6632 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6633 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6634 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6635 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6636 hdd_err("Invalid device mode %d", adapter->device_mode);
6637 return -EINVAL;
6638 }
6639
6640 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6641 data, data_len, NULL)) {
6642 hdd_err("Invalid ATTR");
6643 return -EINVAL;
6644 }
6645
6646 memset(&params, 0, sizeof(params));
6647
6648 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6649 params.ctl_flags = 1; /* set to default value */
6650 else
6651 params.ctl_flags = nla_get_u32(tb
6652 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6653
6654 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6655 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6656 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6657 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6658 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6659 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6660 hdd_err("Attribute parsing failed");
6661 return -EINVAL;
6662 }
6663
6664 params.vdev_id = adapter->sessionId;
6665 params.freq = nla_get_u32(tb
6666 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6667 if ((params.freq != 2412) && (params.freq != 2437) &&
6668 (params.freq != 2462)) {
6669 hdd_err("Invalid listening channel: %d", params.freq);
6670 return -EINVAL;
6671 }
6672
6673 params.period = nla_get_u32(tb
6674 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6675 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6676 hdd_err("Invalid period: %d", params.period);
6677 return -EINVAL;
6678 }
6679
6680 params.interval = nla_get_u32(tb
6681 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6682 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6683 hdd_err("Invalid interval: %d", params.interval);
6684 return -EINVAL;
6685 }
6686
6687 params.count = nla_get_u32(tb
6688 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006689 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006690 hdd_err("Invalid count: %d", params.count);
6691 return -EINVAL;
6692 }
6693
6694 params.device_types = nla_data(tb
6695 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6696 if (params.device_types == NULL) {
6697 hdd_err("Invalid device types");
6698 return -EINVAL;
6699 }
6700
6701 params.dev_types_len = nla_len(tb
6702 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6703 if (params.dev_types_len < 8) {
6704 hdd_err("Invalid device type length: %d", params.dev_types_len);
6705 return -EINVAL;
6706 }
6707
6708 params.probe_resp_tmplt = nla_data(tb
6709 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6710 if (params.probe_resp_tmplt == NULL) {
6711 hdd_err("Invalid probe response template");
6712 return -EINVAL;
6713 }
6714
6715 params.probe_resp_len = nla_len(tb
6716 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6717 if (params.probe_resp_len == 0) {
6718 hdd_err("Invalid probe resp template length: %d",
6719 params.probe_resp_len);
6720 return -EINVAL;
6721 }
6722
6723 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6724 params.freq, params.period, params.interval, params.count);
6725
Wu Gao9a704f42017-03-10 18:42:11 +08006726 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006727}
6728
6729
6730/**
6731 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6732 * @wiphy: Pointer to wireless phy
6733 * @wdev: Pointer to wireless device
6734 * @data: Pointer to data
6735 * @data_len: Data length
6736 *
6737 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6738 * to process p2p listen offload start vendor command.
6739 *
6740 * Return: 0 on success, negative errno on failure
6741 */
6742static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6743 struct wireless_dev *wdev,
6744 const void *data,
6745 int data_len)
6746{
6747 int ret = 0;
6748
6749 cds_ssr_protect(__func__);
6750 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6751 data, data_len);
6752 cds_ssr_unprotect(__func__);
6753
6754 return ret;
6755}
6756
6757/**
6758 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6759 * @wiphy: Pointer to wireless phy
6760 * @wdev: Pointer to wireless device
6761 * @data: Pointer to data
6762 * @data_len: Data length
6763 *
6764 * This function is to process the p2p listen offload stop vendor
6765 * command. It invokes WMA API to send command to firmware.
6766 *
6767 * Return: 0 on success, negative errno on failure
6768 */
6769static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6770 struct wireless_dev *wdev,
6771 const void *data,
6772 int data_len)
6773{
Peng Xu8fdaa492016-06-22 10:20:47 -07006774 hdd_adapter_t *adapter;
6775 struct net_device *dev = wdev->netdev;
6776
6777 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6778 hdd_err("Command not allowed in FTM mode");
6779 return -EPERM;
6780 }
6781
6782 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6783 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6784 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6785 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6786 hdd_err("Invalid device mode");
6787 return -EINVAL;
6788 }
6789
Wu Gao9a704f42017-03-10 18:42:11 +08006790 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006791}
6792
6793/**
6794 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6795 * @wiphy: Pointer to wireless phy
6796 * @wdev: Pointer to wireless device
6797 * @data: Pointer to data
6798 * @data_len: Data length
6799 *
6800 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6801 * to process p2p listen offload stop vendor command.
6802 *
6803 * Return: 0 on success, negative errno on failure
6804 */
6805static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6806 struct wireless_dev *wdev,
6807 const void *data,
6808 int data_len)
6809{
6810 int ret = 0;
6811
6812 cds_ssr_protect(__func__);
6813 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6814 data, data_len);
6815 cds_ssr_unprotect(__func__);
6816
6817 return ret;
6818}
6819
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306820/**
6821 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6822 * @wiphy: Pointer to wireless phy
6823 * @wdev: Pointer to wireless device
6824 * @data: Pointer to data
6825 * @data_len: Data length
6826 *
6827 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6828 * to process the conditional channel switch request.
6829 *
6830 * Return: 0 on success, negative errno on failure
6831 */
6832static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6833 struct wireless_dev *wdev,
6834 const void *data,
6835 int data_len)
6836{
6837 int ret;
6838
6839 cds_ssr_protect(__func__);
6840 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6841 data, data_len);
6842 cds_ssr_unprotect(__func__);
6843
6844 return ret;
6845}
6846
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306847/*
6848 * define short names for the global vendor params
6849 * used by __wlan_hdd_cfg80211_bpf_offload()
6850 */
6851#define BPF_INVALID \
6852 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6853#define BPF_SET_RESET \
6854 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6855#define BPF_VERSION \
6856 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6857#define BPF_FILTER_ID \
6858 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6859#define BPF_PACKET_SIZE \
6860 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6861#define BPF_CURRENT_OFFSET \
6862 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6863#define BPF_PROGRAM \
6864 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6865#define BPF_MAX \
6866 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006867
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306868static const struct nla_policy
6869wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6870 [BPF_SET_RESET] = {.type = NLA_U32},
6871 [BPF_VERSION] = {.type = NLA_U32},
6872 [BPF_FILTER_ID] = {.type = NLA_U32},
6873 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6874 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6875 [BPF_PROGRAM] = {.type = NLA_U8},
6876};
6877
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006878struct bpf_offload_priv {
6879 struct sir_bpf_get_offload bpf_get_offload;
6880};
6881
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306882/**
6883 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006884 * @context: opaque context originally passed to SME. HDD always passes
6885 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306886 * @bpf_get_offload: struct for get offload
6887 *
6888 * This function receives the response/data from the lower layer and
6889 * checks to see if the thread is still waiting then post the results to
6890 * upper layer, if the request has timed out then ignore.
6891 *
6892 * Return: None
6893 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006894static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006895 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306896{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006897 struct hdd_request *request;
6898 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306899
6900 ENTER();
6901
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006902 request = hdd_request_get(context);
6903 if (!request) {
6904 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306905 return;
6906 }
6907
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006908 priv = hdd_request_priv(request);
6909 priv->bpf_get_offload = *data;
6910 hdd_request_complete(request);
6911 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306912}
6913
6914/**
6915 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6916 * @hdd_context: hdd_context
6917 * @bpf_get_offload: struct for get offload
6918 *
6919 * Return: 0 on success, error number otherwise.
6920 */
6921static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6922 struct sir_bpf_get_offload *bpf_get_offload)
6923{
6924 struct sk_buff *skb;
6925 uint32_t nl_buf_len;
6926
6927 ENTER();
6928
6929 nl_buf_len = NLMSG_HDRLEN;
6930 nl_buf_len +=
6931 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6932 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6933
6934 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6935 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006936 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306937 return -ENOMEM;
6938 }
6939
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006940 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306941 bpf_get_offload->bpf_version,
6942 bpf_get_offload->max_bytes_for_bpf_inst);
6943
6944 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6945 bpf_get_offload->max_bytes_for_bpf_inst) ||
6946 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006947 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306948 goto nla_put_failure;
6949 }
6950
6951 cfg80211_vendor_cmd_reply(skb);
6952 EXIT();
6953 return 0;
6954
6955nla_put_failure:
6956 kfree_skb(skb);
6957 return -EINVAL;
6958}
6959
6960/**
6961 * hdd_get_bpf_offload - Get BPF offload Capabilities
6962 * @hdd_ctx: Hdd context
6963 *
6964 * Return: 0 on success, errno on failure
6965 */
6966static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6967{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306968 QDF_STATUS status;
6969 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006970 void *cookie;
6971 struct hdd_request *request;
6972 struct bpf_offload_priv *priv;
6973 static const struct hdd_request_params params = {
6974 .priv_size = sizeof(*priv),
6975 .timeout_ms = WLAN_WAIT_TIME_BPF,
6976 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306977
6978 ENTER();
6979
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006980 request = hdd_request_alloc(&params);
6981 if (!request) {
6982 hdd_err("Unable to allocate request");
6983 return -EINVAL;
6984 }
6985 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306986
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006987 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6988 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006989 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306990 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006991 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006992 ret = qdf_status_to_os_return(status);
6993 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306994 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006995 ret = hdd_request_wait_for_response(request);
6996 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006997 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006998 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306999 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007000 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307001 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007002 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307003 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007004 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307005
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007006cleanup:
7007 /*
7008 * either we never sent a request to SME, we sent a request to
7009 * SME and timed out, or we sent a request to SME, received a
7010 * response from SME, and posted the response to userspace.
7011 * regardless we are done with the request.
7012 */
7013 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307014 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007015
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307016 return ret;
7017}
7018
7019/**
7020 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7021 * @hdd_ctx: Hdd context
7022 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307023 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307024 *
7025 * Return: 0 on success; errno on failure
7026 */
7027static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7028 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307029 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307030{
7031 struct sir_bpf_set_offload *bpf_set_offload;
7032 QDF_STATUS status;
7033 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307034 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307035
7036 ENTER();
7037
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307038 if (adapter->device_mode == QDF_STA_MODE ||
7039 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7040 if (!hdd_conn_is_connected(
7041 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7042 hdd_err("Not in Connected state!");
7043 return -ENOTSUPP;
7044 }
7045 }
7046
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307047 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7048 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007049 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307050 return -ENOMEM;
7051 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307052
7053 /* Parse and fetch bpf packet size */
7054 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007055 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307056 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307057 goto fail;
7058 }
7059 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7060
7061 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007062 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307063 goto post_sme;
7064 }
7065
7066 /* Parse and fetch bpf program */
7067 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007068 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307069 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307070 goto fail;
7071 }
7072
7073 prog_len = nla_len(tb[BPF_PROGRAM]);
7074 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307075
7076 if (bpf_set_offload->program == NULL) {
7077 hdd_err("qdf_mem_malloc failed for bpf offload program");
7078 ret = -ENOMEM;
7079 goto fail;
7080 }
7081
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307082 bpf_set_offload->current_length = prog_len;
7083 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307084 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307085
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007086 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007087 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307088 bpf_set_offload->program, prog_len);
7089
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307090 /* Parse and fetch filter Id */
7091 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007092 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307093 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307094 goto fail;
7095 }
7096 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7097
7098 /* Parse and fetch current offset */
7099 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007100 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307101 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307102 goto fail;
7103 }
7104 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7105
7106post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007107 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 +05307108 bpf_set_offload->session_id,
7109 bpf_set_offload->version,
7110 bpf_set_offload->filter_id,
7111 bpf_set_offload->total_length,
7112 bpf_set_offload->current_length,
7113 bpf_set_offload->current_offset);
7114
7115 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7116 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007117 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307118 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307119 goto fail;
7120 }
7121 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307122
7123fail:
7124 if (bpf_set_offload->current_length)
7125 qdf_mem_free(bpf_set_offload->program);
7126 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307127 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307128}
7129
7130/**
7131 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7132 * @wiphy: wiphy structure pointer
7133 * @wdev: Wireless device structure pointer
7134 * @data: Pointer to the data received
7135 * @data_len: Length of @data
7136 *
7137 * Return: 0 on success; errno on failure
7138 */
7139static int
7140__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7141 struct wireless_dev *wdev,
7142 const void *data, int data_len)
7143{
7144 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7145 struct net_device *dev = wdev->netdev;
7146 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7147 struct nlattr *tb[BPF_MAX + 1];
7148 int ret_val, packet_filter_subcmd;
7149
7150 ENTER();
7151
7152 ret_val = wlan_hdd_validate_context(hdd_ctx);
7153 if (ret_val)
7154 return ret_val;
7155
7156 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007157 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307158 return -EINVAL;
7159 }
7160
7161 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007162 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307163 return -ENOTSUPP;
7164 }
7165
7166 if (nla_parse(tb, BPF_MAX, data, data_len,
7167 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007168 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307169 return -EINVAL;
7170 }
7171
7172 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007173 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307174 return -EINVAL;
7175 }
7176
7177 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7178
7179 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7180 return hdd_get_bpf_offload(hdd_ctx);
7181 else
7182 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307183 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307184}
7185
7186/**
7187 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7188 * @wiphy: wiphy structure pointer
7189 * @wdev: Wireless device structure pointer
7190 * @data: Pointer to the data received
7191 * @data_len: Length of @data
7192 *
7193 * Return: 0 on success; errno on failure
7194 */
7195
7196static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7197 struct wireless_dev *wdev,
7198 const void *data, int data_len)
7199{
7200 int ret;
7201
7202 cds_ssr_protect(__func__);
7203 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7204 cds_ssr_unprotect(__func__);
7205
7206 return ret;
7207}
7208
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307209/**
7210 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7211 * @pre_cac_adapter: AP adapter used for pre cac
7212 * @status: Status (true or false)
7213 * @handle: Global handle
7214 *
7215 * Sets the status of pre cac i.e., whether the pre cac is active or not
7216 *
7217 * Return: Zero on success, non-zero on failure
7218 */
7219static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7220 bool status, tHalHandle handle)
7221{
7222 QDF_STATUS ret;
7223
7224 ret = wlan_sap_set_pre_cac_status(
7225 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7226 if (QDF_IS_STATUS_ERROR(ret))
7227 return -EINVAL;
7228
7229 return 0;
7230}
7231
7232/**
7233 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7234 * @ap_adapter: AP adapter
7235 * @chan_before_pre_cac: Channel
7236 *
7237 * Saves the channel which the AP was beaconing on before moving to the pre
7238 * cac channel. If radar is detected on the pre cac channel, this saved
7239 * channel will be used for AP operations.
7240 *
7241 * Return: Zero on success, non-zero on failure
7242 */
7243static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7244 uint8_t chan_before_pre_cac)
7245{
7246 QDF_STATUS ret;
7247
7248 ret = wlan_sap_set_chan_before_pre_cac(
7249 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7250 if (QDF_IS_STATUS_ERROR(ret))
7251 return -EINVAL;
7252
7253 return 0;
7254}
7255
7256/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307257 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7258 * are in nol list from provided channel list
7259 * @adapter: AP adapter
7260 * @channel_count: channel count
7261 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307262 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307263 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307264 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307265static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7266 uint32_t *channel_count,
7267 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307268{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307269 uint8_t i, j;
7270 uint32_t nol_len = 0;
7271 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7272 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7273 uint32_t chan_count;
7274 bool found;
7275 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307276
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307277 if (!hdd_ctx) {
7278 hdd_err("hdd ctx not found");
7279 *channel_count = 0;
7280 return;
7281 }
7282
7283 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7284 hdd_err("invalid channel count %d", *channel_count);
7285 return;
7286 }
7287
7288 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7289 if (nol_len == 0)
7290 return;
7291
7292 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7293 chan_count = *channel_count;
7294 qdf_mem_zero(channel_list, chan_count);
7295 *channel_count = 0;
7296
7297 for (i = 0 ; i < chan_count; i++) {
7298 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7299 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7300 continue;
7301 found = false;
7302 for (j = 0; j < nol_len; j++) {
7303 if (tmp_chan_list[i] == nol[j]) {
7304 found = true;
7305 hdd_notice("skipped channel %d due to nol",
7306 nol[j]);
7307 break;
7308 }
7309 }
7310 if (!found) {
7311 channel_list[*channel_count] = tmp_chan_list[i];
7312 *channel_count = *channel_count + 1;
7313 }
7314 }
7315}
7316
7317int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7318 uint32_t *channel_count,
7319 uint8_t *channel_list)
7320{
7321 tsap_Config_t *sap_config;
7322
7323 sap_config = &adapter->sessionCtx.ap.sapConfig;
7324
7325 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7326 sap_config->acs_cfg.ch_list_count);
7327 *channel_count = sap_config->acs_cfg.ch_list_count;
7328 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7329
7330 if (*channel_count == 0) {
7331 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307332 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307333 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307334
7335 return 0;
7336}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307337
7338/**
7339 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7340 * @hdd_ctx: HDD context
7341 * @ap_adapter: AP adapter
7342 * @channel: Channel requested by userspace
7343 * @pre_cac_chan: Pointer to the pre CAC channel
7344 *
7345 * Validates the channel provided by userspace. If user provided channel 0,
7346 * a valid outdoor channel must be selected from the regulatory channel.
7347 *
7348 * Return: Zero on success and non zero value on error
7349 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007350static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7351 hdd_adapter_t *ap_adapter,
7352 uint8_t channel,
7353 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307354{
7355 uint32_t i, j;
7356 QDF_STATUS status;
7357 int ret;
7358 uint8_t nol[QDF_MAX_NUM_CHAN];
7359 uint32_t nol_len = 0, weight_len = 0;
7360 bool found;
7361 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7362 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7363 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7364
7365 if (0 == channel) {
7366 /* Channel is not obtained from PCL because PCL may not have
7367 * the entire channel list. For example: if SAP is up on
7368 * channel 6 and PCL is queried for the next SAP interface,
7369 * if SCC is preferred, the PCL will contain only the channel
7370 * 6. But, we are in need of a DFS channel. So, going with the
7371 * first channel from the valid channel list.
7372 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007373 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7374 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307375 if (QDF_IS_STATUS_ERROR(status)) {
7376 hdd_err("Failed to get channel list");
7377 return -EINVAL;
7378 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007379 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307380 pcl_weights, weight_len);
7381 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7382 for (i = 0; i < len; i++) {
7383 found = false;
7384 for (j = 0; j < nol_len; j++) {
7385 if (channel_list[i] == nol[j]) {
7386 found = true;
7387 break;
7388 }
7389 }
7390 if (found)
7391 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007392 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7393 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307394 *pre_cac_chan = channel_list[i];
7395 break;
7396 }
7397 }
7398 if (*pre_cac_chan == 0) {
7399 hdd_err("unable to find outdoor channel");
7400 return -EINVAL;
7401 }
7402 } else {
7403 /* Only when driver selects a channel, check is done for
7404 * unnsafe and NOL channels. When user provides a fixed channel
7405 * the user is expected to take care of this.
7406 */
7407 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007408 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307409 hdd_err("Invalid channel for pre cac:%d", channel);
7410 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307411 }
Jeff Johnson68755312017-02-10 11:46:55 -08007412
7413 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307414 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007415 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307416 return 0;
7417}
7418
7419/**
7420 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7421 * @channel: Channel option provided by userspace
7422 *
7423 * Sets the driver to the required hardware mode and start an adapater for
7424 * pre CAC which will mimic an AP.
7425 *
7426 * Return: Zero on success, non-zero value on error
7427 */
7428int wlan_hdd_request_pre_cac(uint8_t channel)
7429{
Krunal Sonib37bb352016-12-20 14:12:21 -08007430 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307431 hdd_context_t *hdd_ctx;
7432 int ret;
7433 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7434 hdd_ap_ctx_t *hdd_ap_ctx;
7435 QDF_STATUS status;
7436 struct wiphy *wiphy;
7437 struct net_device *dev;
7438 struct cfg80211_chan_def chandef;
7439 enum nl80211_channel_type channel_type;
7440 uint32_t freq;
7441 struct ieee80211_channel *chan;
7442 tHalHandle handle;
7443 bool val;
7444
7445 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7446 if (0 != wlan_hdd_validate_context(hdd_ctx))
7447 return -EINVAL;
7448
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007449 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307450 hdd_err("pre cac not allowed in concurrency");
7451 return -EINVAL;
7452 }
7453
7454 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7455 if (!ap_adapter) {
7456 hdd_err("unable to get SAP adapter");
7457 return -EINVAL;
7458 }
7459
7460 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7461 if (!handle) {
7462 hdd_err("Invalid handle");
7463 return -EINVAL;
7464 }
7465
7466 val = wlan_sap_is_pre_cac_active(handle);
7467 if (val) {
7468 hdd_err("pre cac is already in progress");
7469 return -EINVAL;
7470 }
7471
7472 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7473 if (!hdd_ap_ctx) {
7474 hdd_err("SAP context is NULL");
7475 return -EINVAL;
7476 }
7477
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007478 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7479 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307480 hdd_err("SAP is already on DFS channel:%d",
7481 hdd_ap_ctx->operatingChannel);
7482 return -EINVAL;
7483 }
7484
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007485 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307486 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7487 hdd_ap_ctx->operatingChannel);
7488 return -EINVAL;
7489 }
7490
Krunal Sonib37bb352016-12-20 14:12:21 -08007491 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7492 if (!mac_addr) {
7493 hdd_err("can't add virtual intf: Not getting valid mac addr");
7494 return -EINVAL;
7495 }
7496
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007497 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307498
7499 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7500 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007501 if (ret != 0) {
7502 hdd_err("can't validate pre-cac channel");
7503 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307504 }
7505
7506 hdd_debug("starting pre cac SAP adapter");
7507
7508 /* Starting a SAP adapter:
7509 * Instead of opening an adapter, we could just do a SME open session
7510 * for AP type. But, start BSS would still need an adapter.
7511 * So, this option is not taken.
7512 *
7513 * hdd open adapter is going to register this precac interface with
7514 * user space. This interface though exposed to user space will be in
7515 * DOWN state. Consideration was done to avoid this registration to the
7516 * user space. But, as part of SAP operations multiple events are sent
7517 * to user space. Some of these events received from unregistered
7518 * interface was causing crashes. So, retaining the registration.
7519 *
7520 * So, this interface would remain registered and will remain in DOWN
7521 * state for the CAC duration. We will add notes in the feature
7522 * announcement to not use this temporary interface for any activity
7523 * from user space.
7524 */
7525 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007526 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307527 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307528 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007529 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307530 }
7531
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307532 /*
7533 * This interface is internally created by the driver. So, no interface
7534 * up comes for this interface from user space and hence starting
7535 * the adapter internally.
7536 */
7537 if (hdd_start_adapter(pre_cac_adapter)) {
7538 hdd_err("error starting the pre cac adapter");
7539 goto close_pre_cac_adapter;
7540 }
7541
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307542 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7543
7544 wiphy = hdd_ctx->wiphy;
7545 dev = pre_cac_adapter->dev;
7546
7547 /* Since this is only a dummy interface lets us use the IEs from the
7548 * other active SAP interface. In regular scenarios, these IEs would
7549 * come from the user space entity
7550 */
7551 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7552 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7553 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7554 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307555 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307556 }
7557 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7558 ap_adapter->sessionCtx.ap.beacon,
7559 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7560 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7561 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7562 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7563 ap_adapter->sessionCtx.ap.sapConfig.authType;
7564
7565 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7566 * to operate on the same bandwidth as that of the 2.4GHz operations.
7567 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7568 */
7569 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7570 case CH_WIDTH_20MHZ:
7571 channel_type = NL80211_CHAN_HT20;
7572 break;
7573 case CH_WIDTH_40MHZ:
7574 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7575 ap_adapter->sessionCtx.ap.sapConfig.channel)
7576 channel_type = NL80211_CHAN_HT40PLUS;
7577 else
7578 channel_type = NL80211_CHAN_HT40MINUS;
7579 break;
7580 default:
7581 channel_type = NL80211_CHAN_NO_HT;
7582 break;
7583 }
7584
7585 freq = cds_chan_to_freq(pre_cac_chan);
7586 chan = __ieee80211_get_channel(wiphy, freq);
7587 if (!chan) {
7588 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307589 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307590 }
7591
7592 cfg80211_chandef_create(&chandef, chan, channel_type);
7593
7594 hdd_debug("orig width:%d channel_type:%d freq:%d",
7595 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7596 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007597 /*
7598 * Doing update after opening and starting pre-cac adapter will make
7599 * sure that driver won't do hardware mode change if there are any
7600 * initial hick-ups or issues in pre-cac adapter's configuration.
7601 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7602 * connection update should result in DBS mode
7603 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007604 status = policy_mgr_update_and_wait_for_connection_update(
7605 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007606 ap_adapter->sessionId,
7607 pre_cac_chan,
7608 SIR_UPDATE_REASON_PRE_CAC);
7609 if (QDF_IS_STATUS_ERROR(status)) {
7610 hdd_err("error in moving to DBS mode");
7611 goto stop_close_pre_cac_adapter;
7612 }
7613
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307614
7615 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7616 if (0 != ret) {
7617 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307618 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307619 }
7620
7621 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7622 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007623 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307624 if (QDF_IS_STATUS_ERROR(status)) {
7625 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307626 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307627 }
7628
7629 /*
7630 * The pre cac status is set here. But, it would not be reset explicitly
7631 * anywhere, since after the pre cac success/failure, the pre cac
7632 * adapter itself would be removed.
7633 */
7634 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7635 if (0 != ret) {
7636 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307637 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307638 }
7639
7640 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7641 hdd_ap_ctx->operatingChannel);
7642 if (0 != ret) {
7643 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307644 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307645 }
7646
7647 ap_adapter->pre_cac_chan = pre_cac_chan;
7648
7649 return 0;
7650
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307651stop_close_pre_cac_adapter:
7652 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307653 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7654 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307655close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307656 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007657release_intf_addr_and_return_failure:
7658 /*
7659 * Release the interface address as the adapter
7660 * failed to start, if you don't release then next
7661 * adapter which is trying to come wouldn't get valid
7662 * mac address. Remember we have limited pool of mac addresses
7663 */
7664 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307665 return -EINVAL;
7666}
7667
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307668static const struct nla_policy
7669wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7670 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7671};
7672
Agrawal Ashish65634612016-08-18 13:24:32 +05307673static const struct nla_policy
7674wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7675 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7676 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7677};
7678
7679/**
7680 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7681 * @wiphy: Pointer to wireless phy
7682 * @wdev: Pointer to wireless device
7683 * @data: Pointer to data
7684 * @data_len: Length of @data
7685 *
7686 * This function parses the incoming NL vendor command data attributes and
7687 * updates the SAP context about channel_hint and DFS mode.
7688 * If channel_hint is set, SAP will choose that channel
7689 * as operating channel.
7690 *
7691 * If DFS mode is enabled, driver will include DFS channels
7692 * in ACS else driver will skip DFS channels.
7693 *
7694 * Return: 0 on success, negative errno on failure
7695 */
7696static int
7697__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7698 struct wireless_dev *wdev,
7699 const void *data, int data_len)
7700{
7701 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7702 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7703 int ret;
7704 struct acs_dfs_policy *acs_policy;
7705 int mode = DFS_MODE_NONE;
7706 int channel_hint = 0;
7707
7708 ENTER_DEV(wdev->netdev);
7709
7710 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7711 hdd_err("Command not allowed in FTM mode");
7712 return -EINVAL;
7713 }
7714
7715 ret = wlan_hdd_validate_context(hdd_ctx);
7716 if (0 != ret)
7717 return ret;
7718
7719 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7720 data, data_len,
7721 wlan_hdd_set_acs_dfs_config_policy)) {
7722 hdd_err("invalid attr");
7723 return -EINVAL;
7724 }
7725
7726 acs_policy = &hdd_ctx->acs_policy;
7727 /*
7728 * SCM sends this attribute to restrict SAP from choosing
7729 * DFS channels from ACS.
7730 */
7731 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7732 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7733
7734 if (!IS_DFS_MODE_VALID(mode)) {
7735 hdd_err("attr acs dfs mode is not valid");
7736 return -EINVAL;
7737 }
7738 acs_policy->acs_dfs_mode = mode;
7739
7740 /*
7741 * SCM sends this attribute to provide an active channel,
7742 * to skip redundant ACS between drivers, and save driver start up time
7743 */
7744 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7745 channel_hint = nla_get_u8(
7746 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7747
7748 if (!IS_CHANNEL_VALID(channel_hint)) {
7749 hdd_err("acs channel is not valid");
7750 return -EINVAL;
7751 }
7752 acs_policy->acs_channel = channel_hint;
7753
7754 return 0;
7755}
7756
7757/**
7758 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7759 * @wiphy: wiphy structure pointer
7760 * @wdev: Wireless device structure pointer
7761 * @data: Pointer to the data received
7762 * @data_len: Length of @data
7763 *
7764 * This function parses the incoming NL vendor command data attributes and
7765 * updates the SAP context about channel_hint and DFS mode.
7766 *
7767 * Return: 0 on success; errno on failure
7768 */
7769static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7770 struct wireless_dev *wdev,
7771 const void *data, int data_len)
7772{
7773 int ret;
7774
7775 cds_ssr_protect(__func__);
7776 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7777 cds_ssr_unprotect(__func__);
7778
7779 return ret;
7780}
7781
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307782/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307783 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7784 * @mode : cfg80211 dfs mode
7785 *
7786 * Return: return csr sta roam dfs mode else return NONE
7787 */
7788static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7789 enum dfs_mode mode)
7790{
7791 switch (mode) {
7792 case DFS_MODE_ENABLE:
7793 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7794 break;
7795 case DFS_MODE_DISABLE:
7796 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7797 break;
7798 case DFS_MODE_DEPRIORITIZE:
7799 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7800 break;
7801 default:
7802 hdd_err("STA Roam policy dfs mode is NONE");
7803 return CSR_STA_ROAM_POLICY_NONE;
7804 }
7805}
7806
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307807/*
7808 * hdd_get_sap_operating_band: Get current operating channel
7809 * for sap.
7810 * @hdd_ctx: hdd context
7811 *
7812 * Return : Corresponding band for SAP operating channel
7813 */
7814uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7815{
7816 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7817 QDF_STATUS status;
7818 hdd_adapter_t *adapter;
7819 uint8_t operating_channel = 0;
7820 uint8_t sap_operating_band = 0;
7821 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7822 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7823 adapter = adapter_node->pAdapter;
7824
7825 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7826 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7827 &next);
7828 adapter_node = next;
7829 continue;
7830 }
7831 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7832 if (IS_24G_CH(operating_channel))
7833 sap_operating_band = eCSR_BAND_24;
7834 else if (IS_5G_CH(operating_channel))
7835 sap_operating_band = eCSR_BAND_5G;
7836 else
7837 sap_operating_band = eCSR_BAND_ALL;
7838 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7839 &next);
bings373b99b2017-01-23 10:35:08 +08007840 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307841 }
7842 return sap_operating_band;
7843}
7844
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307845static const struct nla_policy
7846wlan_hdd_set_sta_roam_config_policy[
7847QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7848 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7849 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7850};
7851
7852/**
7853 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7854 * for station connection or roaming.
7855 * @wiphy: Pointer to wireless phy
7856 * @wdev: Pointer to wireless device
7857 * @data: Pointer to data
7858 * @data_len: Length of @data
7859 *
7860 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7861 * channels needs to be skipped in scanning or not.
7862 * If dfs_mode is disabled, driver will not scan DFS channels.
7863 * If skip_unsafe_channels is set, driver will skip unsafe channels
7864 * in Scanning.
7865 *
7866 * Return: 0 on success, negative errno on failure
7867 */
7868static int
7869__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7870 struct wireless_dev *wdev,
7871 const void *data, int data_len)
7872{
7873 struct net_device *dev = wdev->netdev;
7874 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7875 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7876 struct nlattr *tb[
7877 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7878 int ret;
7879 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7880 enum dfs_mode mode = DFS_MODE_NONE;
7881 bool skip_unsafe_channels = false;
7882 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307883 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307884
7885 ENTER_DEV(dev);
7886
7887 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7888 hdd_err("Command not allowed in FTM mode");
7889 return -EINVAL;
7890 }
7891
7892 ret = wlan_hdd_validate_context(hdd_ctx);
7893 if (0 != ret)
7894 return ret;
7895 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7896 data, data_len,
7897 wlan_hdd_set_sta_roam_config_policy)) {
7898 hdd_err("invalid attr");
7899 return -EINVAL;
7900 }
7901 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7902 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7903 if (!IS_DFS_MODE_VALID(mode)) {
7904 hdd_err("attr sta roam dfs mode policy is not valid");
7905 return -EINVAL;
7906 }
7907
7908 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7909
7910 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7911 skip_unsafe_channels = nla_get_u8(
7912 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307913 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307914 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307915 skip_unsafe_channels, adapter->sessionId,
7916 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307917
7918 if (!QDF_IS_STATUS_SUCCESS(status)) {
7919 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7920 return -EINVAL;
7921 }
7922 return 0;
7923}
7924
7925/**
7926 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7927 * connection and roaming for station.
7928 * @wiphy: wiphy structure pointer
7929 * @wdev: Wireless device structure pointer
7930 * @data: Pointer to the data received
7931 * @data_len: Length of @data
7932 *
7933 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7934 * channels needs to be skipped in scanning or not.
7935 * If dfs_mode is disabled, driver will not scan DFS channels.
7936 * If skip_unsafe_channels is set, driver will skip unsafe channels
7937 * in Scanning.
7938 * Return: 0 on success; errno on failure
7939 */
7940static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7941 struct wireless_dev *wdev,
7942 const void *data, int data_len)
7943{
7944 int ret;
7945
7946 cds_ssr_protect(__func__);
7947 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7948 cds_ssr_unprotect(__func__);
7949
7950 return ret;
7951}
7952
Agrawal Ashish467dde42016-09-08 18:44:22 +05307953#ifdef FEATURE_WLAN_CH_AVOID
7954/**
7955 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7956 * is on unsafe channel.
7957 * @wiphy: wiphy structure pointer
7958 * @wdev: Wireless device structure pointer
7959 * @data: Pointer to the data received
7960 * @data_len: Length of @data
7961 *
7962 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7963 * on any of unsafe channels.
7964 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7965 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7966 *
7967 * Return: 0 on success; errno on failure
7968 */
7969static int
7970__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7971 struct wireless_dev *wdev,
7972 const void *data, int data_len)
7973{
7974 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7975 int ret;
7976 uint16_t unsafe_channel_count;
7977 int unsafe_channel_index;
7978 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7979
7980 ENTER_DEV(wdev->netdev);
7981
7982 if (!qdf_ctx) {
7983 cds_err("qdf_ctx is NULL");
7984 return -EINVAL;
7985 }
7986
7987 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7988 hdd_err("Command not allowed in FTM mode");
7989 return -EINVAL;
7990 }
7991
7992 ret = wlan_hdd_validate_context(hdd_ctx);
7993 if (0 != ret)
7994 return ret;
7995 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7996 &(hdd_ctx->unsafe_channel_count),
7997 sizeof(hdd_ctx->unsafe_channel_list));
7998
7999 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8000 (uint16_t)NUM_CHANNELS);
8001 for (unsafe_channel_index = 0;
8002 unsafe_channel_index < unsafe_channel_count;
8003 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008004 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308005 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8006 }
8007 hdd_unsafe_channel_restart_sap(hdd_ctx);
8008 return 0;
8009}
8010
8011/**
8012 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8013 * is on unsafe channel.
8014 * @wiphy: wiphy structure pointer
8015 * @wdev: Wireless device structure pointer
8016 * @data: Pointer to the data received
8017 * @data_len: Length of @data
8018 *
8019 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8020 * on any of unsafe channels.
8021 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8022 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8023 *
8024 * Return: 0 on success; errno on failure
8025 */
8026static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8027 struct wireless_dev *wdev,
8028 const void *data, int data_len)
8029{
8030 int ret;
8031
8032 cds_ssr_protect(__func__);
8033 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8034 cds_ssr_unprotect(__func__);
8035
8036 return ret;
8037}
8038
8039#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308040/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308041 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8042 * SAP is on unsafe channel.
8043 * @wiphy: wiphy structure pointer
8044 * @wdev: Wireless device structure pointer
8045 * @data: Pointer to the data received
8046 * @data_len: Length of @data
8047 *
8048 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8049 * driver.
8050 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8051 * will initiate restart of sap.
8052 *
8053 * Return: 0 on success; errno on failure
8054 */
8055static int
8056__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8057 struct wireless_dev *wdev,
8058 const void *data, int data_len)
8059{
8060 struct net_device *ndev = wdev->netdev;
8061 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8062 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8063 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8064 uint8_t config_channel = 0;
8065 hdd_ap_ctx_t *ap_ctx;
8066 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308067 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308068
8069 ENTER();
8070
8071 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008072 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308073 return -EINVAL;
8074 }
8075
8076 ret = wlan_hdd_validate_context(hdd_ctx);
8077 if (0 != ret)
8078 return -EINVAL;
8079
8080 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8081 data, data_len,
8082 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008083 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308084 return -EINVAL;
8085 }
8086
8087 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8088 if (!test_bit(SOFTAP_BSS_STARTED,
8089 &hostapd_adapter->event_flags)) {
8090 hdd_err("SAP is not started yet. Restart sap will be invalid");
8091 return -EINVAL;
8092 }
8093
8094 config_channel =
8095 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8096
8097 if (!((IS_24G_CH(config_channel)) ||
8098 (IS_5G_CH(config_channel)))) {
8099 hdd_err("Channel %d is not valid to restart SAP",
8100 config_channel);
8101 return -ENOTSUPP;
8102 }
8103
8104 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8105 ap_ctx->sapConfig.channel = config_channel;
8106 ap_ctx->sapConfig.ch_params.ch_width =
8107 ap_ctx->sapConfig.ch_width_orig;
8108
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008109 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8110 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308111 ap_ctx->sapConfig.sec_ch,
8112 &ap_ctx->sapConfig.ch_params);
8113
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008114 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308115 }
8116
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308117 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8118 uint32_t freq_len, i;
8119 uint32_t *freq;
8120 uint8_t chans[QDF_MAX_NUM_CHAN];
8121
8122 hdd_debug("setting mandatory freq/chan list");
8123
8124 freq_len = nla_len(
8125 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8126 sizeof(uint32_t);
8127
8128 if (freq_len > QDF_MAX_NUM_CHAN) {
8129 hdd_err("insufficient space to hold channels");
8130 return -ENOMEM;
8131 }
8132
8133 freq = nla_data(
8134 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8135
8136 hdd_debug("freq_len=%d", freq_len);
8137
8138 for (i = 0; i < freq_len; i++) {
8139 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8140 hdd_debug("freq[%d]=%d", i, freq[i]);
8141 }
8142
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008143 status = policy_mgr_set_sap_mandatory_channels(
8144 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308145 if (QDF_IS_STATUS_ERROR(status))
8146 return -EINVAL;
8147 }
8148
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308149 return 0;
8150}
8151
8152/**
8153 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8154 * @wiphy: wiphy structure pointer
8155 * @wdev: Wireless device structure pointer
8156 * @data: Pointer to the data received
8157 * @data_len: Length of @data
8158 *
8159 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8160 * driver.
8161 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8162 * will initiate restart of sap.
8163 *
8164 * Return: 0 on success; errno on failure
8165 */
8166static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8167 struct wireless_dev *wdev,
8168 const void *data, int data_len)
8169{
8170 int ret;
8171
8172 cds_ssr_protect(__func__);
8173 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8174 wdev, data, data_len);
8175 cds_ssr_unprotect(__func__);
8176
8177 return ret;
8178}
8179
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308180#undef BPF_INVALID
8181#undef BPF_SET_RESET
8182#undef BPF_VERSION
8183#undef BPF_ID
8184#undef BPF_PACKET_SIZE
8185#undef BPF_CURRENT_OFFSET
8186#undef BPF_PROGRAM
8187#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308188
8189/**
8190 * define short names for the global vendor params
8191 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8192 */
8193#define PARAM_TOTAL_CMD_EVENT_WAKE \
8194 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8195#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8196 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8197#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8198 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8199#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8200 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8201#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8202 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8203#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8204 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8205#define PARAM_TOTAL_RX_DATA_WAKE \
8206 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8207#define PARAM_RX_UNICAST_CNT \
8208 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8209#define PARAM_RX_MULTICAST_CNT \
8210 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8211#define PARAM_RX_BROADCAST_CNT \
8212 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8213#define PARAM_ICMP_PKT \
8214 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8215#define PARAM_ICMP6_PKT \
8216 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8217#define PARAM_ICMP6_RA \
8218 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8219#define PARAM_ICMP6_NA \
8220 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8221#define PARAM_ICMP6_NS \
8222 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8223#define PARAM_ICMP4_RX_MULTICAST_CNT \
8224 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8225#define PARAM_ICMP6_RX_MULTICAST_CNT \
8226 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8227#define PARAM_OTHER_RX_MULTICAST_CNT \
8228 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308229#define PARAM_RSSI_BREACH_CNT \
8230 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8231#define PARAM_LOW_RSSI_CNT \
8232 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8233#define PARAM_GSCAN_CNT \
8234 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8235#define PARAM_PNO_COMPLETE_CNT \
8236 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8237#define PARAM_PNO_MATCH_CNT \
8238 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8239
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308240
8241
8242/**
8243 * hdd_send_wakelock_stats() - API to send wakelock stats
8244 * @ctx: context to be passed to callback
8245 * @data: data passed to callback
8246 *
8247 * This function is used to send wake lock stats to HAL layer
8248 *
8249 * Return: 0 on success, error number otherwise.
8250 */
8251static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8252 const struct sir_wake_lock_stats *data)
8253{
8254 struct sk_buff *skb;
8255 uint32_t nl_buf_len;
8256 uint32_t total_rx_data_wake, rx_multicast_cnt;
8257 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308258 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308259
8260 ENTER();
8261
8262 nl_buf_len = NLMSG_HDRLEN;
8263 nl_buf_len +=
8264 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8265 (NLMSG_HDRLEN + sizeof(uint32_t));
8266
8267 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8268
8269 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008270 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308271 return -ENOMEM;
8272 }
8273
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008274 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308275 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008276 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308277 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008278 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308279 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008280 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308281 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008282 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308283 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008284 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308285 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008286 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008288 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8289 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308290 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008291 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308292 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008293 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308294 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008295 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308296 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008297 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308298 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008299 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308300 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308301
8302 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308303 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308304
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308305 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308306 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308307
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308308 rx_multicast_cnt =
8309 data->wow_ipv4_mcast_wake_up_count +
8310 ipv6_rx_multicast_addr_cnt;
8311
8312 total_rx_data_wake =
8313 data->wow_ucast_wake_up_count +
8314 data->wow_bcast_wake_up_count +
8315 rx_multicast_cnt;
8316
8317 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8318 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8319 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8320 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8321 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8322 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8323 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8324 total_rx_data_wake) ||
8325 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8326 data->wow_ucast_wake_up_count) ||
8327 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8328 rx_multicast_cnt) ||
8329 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8330 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308331 nla_put_u32(skb, PARAM_ICMP_PKT,
8332 data->wow_icmpv4_count) ||
8333 nla_put_u32(skb, PARAM_ICMP6_PKT,
8334 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308335 nla_put_u32(skb, PARAM_ICMP6_RA,
8336 data->wow_ipv6_mcast_ra_stats) ||
8337 nla_put_u32(skb, PARAM_ICMP6_NA,
8338 data->wow_ipv6_mcast_na_stats) ||
8339 nla_put_u32(skb, PARAM_ICMP6_NS,
8340 data->wow_ipv6_mcast_ns_stats) ||
8341 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8342 data->wow_ipv4_mcast_wake_up_count) ||
8343 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8344 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308345 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8346 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8347 data->wow_rssi_breach_wake_up_count) ||
8348 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8349 data->wow_low_rssi_wake_up_count) ||
8350 nla_put_u32(skb, PARAM_GSCAN_CNT,
8351 data->wow_gscan_wake_up_count) ||
8352 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8353 data->wow_pno_complete_wake_up_count) ||
8354 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8355 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008356 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308357 goto nla_put_failure;
8358 }
8359
8360 cfg80211_vendor_cmd_reply(skb);
8361
8362 EXIT();
8363 return 0;
8364
8365nla_put_failure:
8366 kfree_skb(skb);
8367 return -EINVAL;
8368}
8369
8370/**
8371 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8372 * @wiphy: wiphy pointer
8373 * @wdev: pointer to struct wireless_dev
8374 * @data: pointer to incoming NL vendor data
8375 * @data_len: length of @data
8376 *
8377 * This function parses the incoming NL vendor command data attributes and
8378 * invokes the SME Api and blocks on a completion variable.
8379 * WMA copies required data and invokes callback
8380 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8381 *
8382 * Return: 0 on success; error number otherwise.
8383 */
8384static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8385 struct wireless_dev *wdev,
8386 const void *data,
8387 int data_len)
8388{
8389 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8390 int status, ret;
8391 struct sir_wake_lock_stats wake_lock_stats;
8392 QDF_STATUS qdf_status;
8393
8394 ENTER();
8395
8396 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008397 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308398 return -EINVAL;
8399 }
8400
8401 status = wlan_hdd_validate_context(hdd_ctx);
8402 if (0 != status)
8403 return -EINVAL;
8404
8405 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8406 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008407 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308408 return -EINVAL;
8409 }
8410
8411 ret = hdd_send_wakelock_stats(hdd_ctx,
8412 &wake_lock_stats);
8413 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008414 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308415
8416 EXIT();
8417 return ret;
8418}
8419
8420/**
8421 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8422 * @wiphy: wiphy pointer
8423 * @wdev: pointer to struct wireless_dev
8424 * @data: pointer to incoming NL vendor data
8425 * @data_len: length of @data
8426 *
8427 * This function parses the incoming NL vendor command data attributes and
8428 * invokes the SME Api and blocks on a completion variable.
8429 * WMA copies required data and invokes callback
8430 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8431 *
8432 * Return: 0 on success; error number otherwise.
8433 */
8434static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8435 struct wireless_dev *wdev,
8436 const void *data, int data_len)
8437{
8438 int ret;
8439
8440 cds_ssr_protect(__func__);
8441 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8442 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008443 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308444
8445 return ret;
8446}
8447
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308448/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308449 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8450 * @wiphy: wiphy structure pointer
8451 * @wdev: Wireless device structure pointer
8452 * @data: Pointer to the data received
8453 * @data_len: Length of @data
8454 *
8455 * This function reads wmi max bus size and fill in the skb with
8456 * NL attributes and send up the NL event.
8457 * Return: 0 on success; errno on failure
8458 */
8459static int
8460__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8461 struct wireless_dev *wdev,
8462 const void *data, int data_len)
8463{
8464 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8465 int ret_val;
8466 struct sk_buff *skb;
8467 uint32_t nl_buf_len;
8468
8469 ENTER();
8470
8471 ret_val = wlan_hdd_validate_context(hdd_ctx);
8472 if (ret_val)
8473 return ret_val;
8474
8475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8476 hdd_err("Command not allowed in FTM mode");
8477 return -EINVAL;
8478 }
8479
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008480 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308481
8482 nl_buf_len = NLMSG_HDRLEN;
8483 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8484
8485 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8486 if (!skb) {
8487 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8488 return -ENOMEM;
8489 }
8490
8491 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8492 hdd_ctx->wmi_max_len)) {
8493 hdd_err("nla put failure");
8494 goto nla_put_failure;
8495 }
8496
8497 cfg80211_vendor_cmd_reply(skb);
8498
8499 EXIT();
8500
8501 return 0;
8502
8503nla_put_failure:
8504 kfree_skb(skb);
8505 return -EINVAL;
8506}
8507
8508/**
8509 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8510 * @wiphy: wiphy structure pointer
8511 * @wdev: Wireless device structure pointer
8512 * @data: Pointer to the data received
8513 * @data_len: Length of @data
8514 *
8515 * Return: 0 on success; errno on failure
8516 */
8517static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8518 struct wireless_dev *wdev,
8519 const void *data, int data_len)
8520{
8521 int ret;
8522
8523 cds_ssr_protect(__func__);
8524 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8525 cds_ssr_unprotect(__func__);
8526
8527 return ret;
8528}
8529
8530/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308531 *__wlan_hdd_cfg80211_setband() - set band
8532 * @wiphy: Pointer to wireless phy
8533 * @wdev: Pointer to wireless device
8534 * @data: Pointer to data
8535 * @data_len: Length of @data
8536 *
8537 * Return: 0 on success, negative errno on failure
8538 */
8539static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8540 struct wireless_dev *wdev,
8541 const void *data, int data_len)
8542{
8543 struct net_device *dev = wdev->netdev;
8544 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8545 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8546 int ret;
8547 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8548 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8549
8550 ENTER();
8551
8552 ret = wlan_hdd_validate_context(hdd_ctx);
8553 if (ret)
8554 return ret;
8555
8556 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8557 hdd_err(FL("Invalid ATTR"));
8558 return -EINVAL;
8559 }
8560
8561 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8562 hdd_err(FL("attr SETBAND_VALUE failed"));
8563 return -EINVAL;
8564 }
8565
8566 ret = hdd_set_band(dev,
8567 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8568
8569 EXIT();
8570 return ret;
8571}
8572
8573/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308574 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8575 * @adapter: hdd adapter
8576 * @channel: channel number
8577 *
8578 * return: QDF status based on success or failure
8579 */
8580static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8581 int channel, int chan_bw)
8582{
8583 if (QDF_STATUS_SUCCESS !=
8584 wlan_hdd_validate_operation_channel(adapter, channel))
8585 return QDF_STATUS_E_FAILURE;
8586 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8587 channel,
8588 PHY_SINGLE_CHANNEL_CENTERED))) {
8589 hdd_notice("channel %d is in nol", channel);
8590 return -EINVAL;
8591 }
8592
8593 if ((wlansap_is_channel_leaking_in_nol(
8594 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8595 channel, chan_bw))) {
8596 hdd_notice("channel %d is leaking in nol", channel);
8597 return -EINVAL;
8598 }
8599
8600 return 0;
8601
8602}
8603
Kapil Gupta8878ad92017-02-13 11:56:04 +05308604static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8605 tsap_Config_t *sap_config,
8606 struct hdd_vendor_chan_info *channel_list)
8607{
8608 sap_config->channel = channel_list->pri_ch;
8609
8610 sap_config->ch_params.center_freq_seg0 =
8611 channel_list->vht_seg0_center_ch;
8612 sap_config->ch_params.center_freq_seg1 =
8613 channel_list->vht_seg1_center_ch;
8614
8615 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8616 sap_config->ch_params.ch_width = channel_list->chan_width;
8617 if (sap_config->channel >= 36)
8618 sap_config->ch_width_orig =
8619 hdd_ctx->config->vhtChannelWidth;
8620 else
8621 sap_config->ch_width_orig =
8622 hdd_ctx->config->nChannelBondingMode24GHz ?
8623 eHT_CHANNEL_WIDTH_40MHZ :
8624 eHT_CHANNEL_WIDTH_20MHZ;
8625
8626 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8627 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8628 sap_config->acs_cfg.vht_seg0_center_ch =
8629 channel_list->vht_seg0_center_ch;
8630 sap_config->acs_cfg.vht_seg1_center_ch =
8631 channel_list->vht_seg1_center_ch;
8632 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8633}
8634
8635static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8636 uint8_t channel_cnt,
8637 struct hdd_vendor_chan_info *channel_list)
8638{
8639 tsap_Config_t *sap_config;
8640 hdd_ap_ctx_t *hdd_ap_ctx;
8641 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8642 QDF_STATUS status = QDF_STATUS_SUCCESS;
8643
8644 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8645 sap_config = &adapter->sessionCtx.ap.sapConfig;
8646
8647 if (QDF_TIMER_STATE_RUNNING ==
8648 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8649 ap.vendor_acs_timer)) {
8650 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8651 }
8652
8653 if (channel_list && channel_list->pri_ch == 0) {
8654 /* Check mode, set default channel */
8655 channel_list->pri_ch = 6;
8656 /*
8657 * sap_select_default_oper_chan(hdd_ctx->hHal,
8658 * sap_config->acs_cfg.hw_mode);
8659 */
8660 }
8661
8662 switch (reason) {
8663 /* SAP init case */
8664 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8665 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8666 /* Update Hostapd */
8667 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8668 break;
8669
8670 /* DFS detected on current channel */
8671 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8672 wlan_sap_update_next_channel(
8673 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8674 channel_list->pri_ch,
8675 channel_list->chan_width);
8676 status = sme_update_new_channel_event(
8677 WLAN_HDD_GET_HAL_CTX(adapter),
8678 adapter->sessionId);
8679 break;
8680
8681 /* LTE coex event on current channel */
8682 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8683 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8684 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8685 hdd_ap_ctx->sapConfig.ch_width_orig =
8686 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008687 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308688 break;
8689
8690 default:
8691 hdd_info("invalid reason for timer invoke");
8692 }
8693 qdf_mem_free(channel_list);
8694 EXIT();
8695 return status;
8696}
8697
8698/**
8699 * Define short name for vendor channel set config
8700 */
8701#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8702#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8703#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8704#define SET_CHAN_PRIMARY_CHANNEL \
8705 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8706#define SET_CHAN_SECONDARY_CHANNEL \
8707 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8708#define SET_CHAN_SEG0_CENTER_CHANNEL \
8709 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8710#define SET_CHAN_SEG1_CENTER_CHANNEL \
8711 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8712#define SET_CHAN_CHANNEL_WIDTH \
8713 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8714#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8715
8716/**
8717 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8718 * @channel_list: pointer to hdd_vendor_chan_info
8719 * @reason: channel change reason
8720 * @channel_cnt: channel count
8721 * @data: data
8722 * @data_len: data len
8723 *
8724 * Return: 0 on success, negative errno on failure
8725 */
8726static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8727 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8728 const void *data, int data_len)
8729{
8730 int rem, i = 0;
8731 struct nlattr *tb[SET_CHAN_MAX + 1];
8732 struct nlattr *tb2[SET_CHAN_MAX + 1];
8733 struct nlattr *curr_attr;
8734 struct hdd_vendor_chan_info *channel_list;
8735
8736 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8737 hdd_err("Invalid ATTR");
8738 return -EINVAL;
8739 }
8740
8741 if (tb[SET_CHAN_REASON])
8742 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8743
8744 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8745 *channel_cnt = nla_get_u8(tb[
8746 SET_CHAN_CHANNEL_COUNT]);
8747 hdd_info("channel count %d", *channel_cnt);
8748 }
8749
8750 if (!(*channel_cnt)) {
8751 hdd_err("channel count is %d", *channel_cnt);
8752 return -EINVAL;
8753 }
8754
8755 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8756 (*channel_cnt));
8757
8758 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8759 if (nla_parse(tb2,
8760 SET_CHAN_MAX,
8761 nla_data(curr_attr), nla_len(curr_attr),
8762 NULL)) {
8763 hdd_err("nla_parse failed");
8764 return -EINVAL;
8765 }
8766 /* Parse and Fetch allowed SSID list*/
8767 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8768 channel_list[i].pri_ch =
8769 nla_get_u8(
8770 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8771 }
8772 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8773 channel_list[i].ht_sec_ch =
8774 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8775 }
8776 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8777 channel_list[i].vht_seg0_center_ch =
8778 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8779 }
8780 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8781 channel_list[i].vht_seg1_center_ch =
8782 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8783 }
8784 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8785 channel_list[i].chan_width =
8786 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8787 }
8788 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8789 i, channel_list[i].pri_ch,
8790 channel_list[i].ht_sec_ch,
8791 channel_list[i].vht_seg0_center_ch,
8792 channel_list[i].vht_seg1_center_ch,
8793 channel_list[i].chan_width);
8794 i++;
8795 if (i > *channel_cnt)
8796 break;
8797 }
8798 *chan_list_ptr = channel_list;
8799
8800 return 0;
8801}
8802
8803/**
8804 * Undef short names for vendor set channel configuration
8805 */
8806#undef SET_CHAN_REASON
8807#undef SET_CHAN_CHANNEL_COUNT
8808#undef SET_CHAN_CHAN_LIST
8809#undef SET_CHAN_PRIMARY_CHANNEL
8810#undef SET_CHAN_SECONDARY_CHANNEL
8811#undef SET_CHAN_SEG0_CENTER_CHANNEL
8812#undef SET_CHAN_SEG1_CENTER_CHANNEL
8813#undef SET_CHAN_CHANNEL_WIDTH
8814#undef SET_CHAN_MAX
8815
8816/**
8817 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8818 * @wiphy: Pointer to wireless phy
8819 * @wdev: Pointer to wireless device
8820 * @data: Pointer to data
8821 * @data_len: Length of @data
8822 *
8823 * Return: 0 on success, negative errno on failure
8824 */
8825static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8826 struct wireless_dev *wdev,
8827 const void *data, int data_len)
8828{
8829 int ret_val;
8830 QDF_STATUS qdf_status;
8831 uint8_t channel_cnt = 0, reason = -1;
8832 struct hdd_vendor_chan_info *channel_list = NULL;
8833 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8834 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8835
8836 ENTER();
8837
8838 ret_val = wlan_hdd_validate_context(hdd_ctx);
8839 if (ret_val)
8840 return ret_val;
8841
8842 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8843 hdd_err("Command not allowed in FTM mode");
8844 return -EINVAL;
8845 }
8846
8847 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8848 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8849 else {
8850 hdd_err("already timeout happened for acs");
8851 return -EINVAL;
8852 }
8853
8854 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8855 &channel_cnt, data, data_len);
8856 if (ret_val)
8857 return ret_val;
8858
8859 /* Validate channel to be set */
8860 while (channel_cnt && channel_list) {
8861 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8862 channel_list->pri_ch,
8863 channel_list->chan_width);
8864 if (qdf_status == QDF_STATUS_SUCCESS)
8865 break;
8866 channel_cnt--;
8867 channel_list++;
8868 }
8869 if ((channel_cnt <= 0) || !channel_list) {
8870 hdd_err("no available channel/chanlist %p", channel_list);
8871 return -EINVAL;
8872 }
8873
8874 qdf_status = hdd_update_acs_channel(adapter, reason,
8875 channel_cnt, channel_list);
8876 return qdf_status_to_os_return(qdf_status);
8877}
8878
8879/**
8880 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8881 * @wiphy: Pointer to wireless phy
8882 * @wdev: Pointer to wireless device
8883 * @data: Pointer to data
8884 * @data_len: Length of @data
8885 *
8886 * Return: 0 on success, negative errno on failure
8887 */
8888static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8889 struct wireless_dev *wdev,
8890 const void *data, int data_len)
8891{
8892 int ret;
8893
8894 cds_ssr_protect(__func__);
8895 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8896 data_len);
8897 cds_ssr_protect(__func__);
8898
8899 return ret;
8900}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308901
8902/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308903 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8904 * @wiphy: wiphy structure pointer
8905 * @wdev: Wireless device structure pointer
8906 * @data: Pointer to the data received
8907 * @data_len: Length of @data
8908 *
8909 * Return: 0 on success; errno on failure
8910 */
8911static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8912 struct wireless_dev *wdev,
8913 const void *data, int data_len)
8914{
8915 int ret;
8916
8917 cds_ssr_protect(__func__);
8918 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8919 cds_ssr_unprotect(__func__);
8920
8921 return ret;
8922}
8923
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008924/**
8925 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8926 * @nl80211_value: Vendor command attribute value
8927 * @wmi_value: Pointer to return converted WMI return value
8928 *
8929 * Convert NL80211 vendor command value for SAR limit set to WMI value
8930 * Return: 0 on success, -1 on invalid value
8931 */
8932static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8933 u32 *wmi_value)
8934{
8935 int ret = 0;
8936
8937 switch (nl80211_value) {
8938 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8939 *wmi_value = WMI_SAR_FEATURE_OFF;
8940 break;
8941 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8942 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8943 break;
8944 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8945 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8946 break;
8947 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8948 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8949 break;
8950 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8951 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8952 break;
8953 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8954 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8955 break;
8956 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8957 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8958 break;
8959 default:
8960 ret = -1;
8961 }
8962 return ret;
8963}
8964
8965/**
8966 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8967 * @nl80211_value: Vendor command attribute value
8968 * @wmi_value: Pointer to return converted WMI return value
8969 *
8970 * Convert NL80211 vendor command value for SAR BAND to WMI value
8971 * Return: 0 on success, -1 on invalid value
8972 */
8973static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8974{
8975 int ret = 0;
8976
8977 switch (nl80211_value) {
8978 case NL80211_BAND_2GHZ:
8979 *wmi_value = WMI_SAR_2G_ID;
8980 break;
8981 case NL80211_BAND_5GHZ:
8982 *wmi_value = WMI_SAR_5G_ID;
8983 break;
8984 default:
8985 ret = -1;
8986 }
8987 return ret;
8988}
8989
8990/**
8991 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8992 * @nl80211_value: Vendor command attribute value
8993 * @wmi_value: Pointer to return converted WMI return value
8994 *
8995 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8996 * Return: 0 on success, -1 on invalid value
8997 */
8998static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8999 u32 *wmi_value)
9000{
9001 int ret = 0;
9002
9003 switch (nl80211_value) {
9004 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9005 *wmi_value = WMI_SAR_MOD_CCK;
9006 break;
9007 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9008 *wmi_value = WMI_SAR_MOD_OFDM;
9009 break;
9010 default:
9011 ret = -1;
9012 }
9013 return ret;
9014}
9015
9016
9017/**
9018 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9019 * @wiphy: Pointer to wireless phy
9020 * @wdev: Pointer to wireless device
9021 * @data: Pointer to data
9022 * @data_len: Length of @data
9023 *
9024 * This function is used to setup Specific Absorption Rate limit specs.
9025 *
9026 * Return: 0 on success, negative errno on failure
9027 */
9028static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9029 struct wireless_dev *wdev,
9030 const void *data, int data_len)
9031{
9032 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9033 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9034 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9035 *sar_spec_list;
9036 struct sar_limit_cmd_params sar_limit_cmd = {0};
9037 int ret = -EINVAL, i = 0, rem = 0;
9038
9039 ENTER();
9040
9041 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9042 hdd_err("Command not allowed in FTM mode");
9043 return -EPERM;
9044 }
9045
9046 if (wlan_hdd_validate_context(hdd_ctx))
9047 return -EINVAL;
9048
9049 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9050 data, data_len, NULL)) {
9051 hdd_err("Invalid SAR attributes");
9052 return -EINVAL;
9053 }
9054
9055 /* Vendor command manadates all SAR Specs in single call */
9056 sar_limit_cmd.commit_limits = 1;
9057 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9058 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9059 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9060 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9061 &sar_limit_cmd.sar_enable) < 0) {
9062 hdd_err("Invalid SAR Enable attr");
9063 goto fail;
9064 }
9065 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009066 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009067
9068 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9069 sar_limit_cmd.num_limit_rows = nla_get_u32(
9070 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009071 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009072 sar_limit_cmd.num_limit_rows);
9073 }
9074 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9075 hdd_err("SAR Spec list exceed supported size");
9076 goto fail;
9077 }
9078 if (sar_limit_cmd.num_limit_rows == 0)
9079 goto send_sar_limits;
9080 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9081 struct sar_limit_cmd_row) *
9082 sar_limit_cmd.num_limit_rows);
9083 if (!sar_limit_cmd.sar_limit_row_list) {
9084 ret = -ENOMEM;
9085 goto fail;
9086 }
9087 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9088 hdd_err("Invalid SAR SPECs list");
9089 goto fail;
9090 }
9091
9092 nla_for_each_nested(sar_spec_list,
9093 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9094 if (i == sar_limit_cmd.num_limit_rows) {
9095 hdd_warn("SAR Cmd has excess SPECs in list");
9096 break;
9097 }
9098
9099 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9100 nla_data(sar_spec_list), nla_len(sar_spec_list),
9101 NULL)) {
9102 hdd_err("nla_parse failed for SAR Spec list");
9103 goto fail;
9104 }
9105 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9106 if (sar_spec[
9107 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9108 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9109 nla_get_u32(sar_spec[
9110 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9111 } else {
9112 hdd_err("SAR Spec does not have power limit value");
9113 goto fail;
9114 }
9115
9116 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9117 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9118 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9119 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9120 < 0) {
9121 hdd_err("Invalid SAR Band attr");
9122 goto fail;
9123 }
9124 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9125 WMI_SAR_BAND_ID_VALID_MASK;
9126 }
9127 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9128 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9129 nla_get_u32(sar_spec[
9130 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9131 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9132 WMI_SAR_CHAIN_ID_VALID_MASK;
9133 }
9134 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9135 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9136 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9137 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9138 < 0) {
9139 hdd_err("Invalid SAR Modulation attr");
9140 goto fail;
9141 }
9142 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9143 WMI_SAR_MOD_ID_VALID_MASK;
9144 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009145 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009146 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9147 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9148 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9149 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9150 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9151 i++;
9152 }
9153
9154 if (i < sar_limit_cmd.num_limit_rows) {
9155 hdd_warn("SAR Cmd has less SPECs in list");
9156 sar_limit_cmd.num_limit_rows = i;
9157 }
9158
9159send_sar_limits:
9160 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9161 QDF_STATUS_SUCCESS)
9162 ret = 0;
9163fail:
9164 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9165 return ret;
9166}
9167
9168/**
9169 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9170 * @wiphy: Pointer to wireless phy
9171 * @wdev: Pointer to wireless device
9172 * @data: Pointer to data
9173 * @data_len: Length of @data
9174 *
9175 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9176 *
9177 * Return: 0 on success, negative errno on failure
9178 */
9179static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9180 struct wireless_dev *wdev,
9181 const void *data,
9182 int data_len)
9183{
9184 int ret;
9185
9186 cds_ssr_protect(__func__);
9187 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9188 data_len);
9189 cds_ssr_unprotect(__func__);
9190
9191 return ret;
9192}
9193
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309194static const struct
9195nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9196 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9197 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9198 .len = QDF_MAC_ADDR_SIZE},
9199};
9200
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309201void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9202{
9203 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9204 hdd_adapter_t *adapter;
9205
9206 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9207 if (!adapter) {
9208 hdd_err("adapter NULL");
9209 return;
9210 }
9211
9212 adapter->lfr_fw_status.is_disabled = rso_status->status;
9213 complete(&adapter->lfr_fw_status.disable_lfr_event);
9214}
9215
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309216/**
9217 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9218 * @wiphy: Pointer to wireless phy
9219 * @wdev: Pointer to wireless device
9220 * @data: Pointer to data
9221 * @data_len: Length of @data
9222 *
9223 * This function is used to enable/disable roaming using vendor commands
9224 *
9225 * Return: 0 on success, negative errno on failure
9226 */
9227static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9228 struct wireless_dev *wdev,
9229 const void *data, int data_len)
9230{
9231 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9232 struct net_device *dev = wdev->netdev;
9233 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9234 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309235 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309236 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309237 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309238 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309239
9240 ENTER_DEV(dev);
9241
9242 ret = wlan_hdd_validate_context(hdd_ctx);
9243 if (0 != ret)
9244 return ret;
9245
9246 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9247 hdd_err("Command not allowed in FTM mode");
9248 return -EINVAL;
9249 }
9250
9251 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9252 qca_wlan_vendor_attr);
9253 if (ret) {
9254 hdd_err("Invalid ATTR");
9255 return -EINVAL;
9256 }
9257
9258 /* Parse and fetch Enable flag */
9259 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9260 hdd_err("attr enable failed");
9261 return -EINVAL;
9262 }
9263
9264 is_fast_roam_enabled = nla_get_u32(
9265 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009266 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009267 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309268
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009269 if (!adapter->fast_roaming_allowed) {
9270 hdd_err("fast roaming not allowed on %s interface",
9271 adapter->dev->name);
9272 return -EINVAL;
9273 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309274 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309275 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309276 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309277 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309278 if (qdf_status != QDF_STATUS_SUCCESS)
9279 hdd_err("sme_config_fast_roaming failed with status=%d",
9280 qdf_status);
9281 ret = qdf_status_to_os_return(qdf_status);
9282
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309283 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9284 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9285 /*
9286 * wait only for LFR disable in fw as LFR enable
9287 * is always success
9288 */
9289 rc = wait_for_completion_timeout(
9290 &adapter->lfr_fw_status.disable_lfr_event,
9291 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9292 if (!rc) {
9293 hdd_err("Timed out waiting for RSO CMD status");
9294 return -ETIMEDOUT;
9295 }
9296
9297 if (!adapter->lfr_fw_status.is_disabled) {
9298 hdd_err("Roam disable attempt in FW fails");
9299 return -EBUSY;
9300 }
9301 }
9302
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309303 EXIT();
9304 return ret;
9305}
9306
9307/**
9308 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9309 * @wiphy: Pointer to wireless phy
9310 * @wdev: Pointer to wireless device
9311 * @data: Pointer to data
9312 * @data_len: Length of @data
9313 *
9314 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9315 *
9316 * Return: 0 on success, negative errno on failure
9317 */
9318static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9319 struct wireless_dev *wdev,
9320 const void *data, int data_len)
9321{
9322 int ret;
9323
9324 cds_ssr_protect(__func__);
9325 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9326 cds_ssr_unprotect(__func__);
9327
9328 return ret;
9329}
9330
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309331static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9332 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9333 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9334 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9335 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9336};
9337
9338/**
9339 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9340 * @wiphy: Pointer to wireless phy
9341 * @wdev: Pointer to wireless device
9342 * @data: Pointer to data
9343 * @data_len: Length of @data
9344 *
9345 * Return: 0 on success, negative errno on failure
9346 */
9347static int
9348__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9349 struct wireless_dev *wdev,
9350 const void *data,
9351 int data_len)
9352{
9353 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9354 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9355 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9356 struct nlattr *apth;
9357 int rem;
9358 int ret = 1;
9359 int print_idx = -1;
9360 int module_id = -1;
9361 int bit_mask = -1;
9362 int status;
9363
9364 ENTER();
9365
9366 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9367 hdd_err("Command not allowed in FTM mode");
9368 return -EINVAL;
9369 }
9370
9371 ret = wlan_hdd_validate_context(hdd_ctx);
9372 if (ret != 0)
9373 return -EINVAL;
9374
9375 print_idx = qdf_get_pidx();
9376 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9377 hdd_err("Invalid print controle object index");
9378 return -EINVAL;
9379 }
9380
9381 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9382 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9383 hdd_err("Invalid attr");
9384 return -EINVAL;
9385 }
9386
9387 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9388 hdd_err("attr trace level param failed");
9389 return -EINVAL;
9390 }
9391
9392 nla_for_each_nested(apth,
9393 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9394 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9395 nla_data(apth), nla_len(apth), NULL)) {
9396 hdd_err("Invalid attr");
9397 return -EINVAL;
9398 }
9399
9400 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9401 hdd_err("attr Module ID failed");
9402 return -EINVAL;
9403 }
9404 module_id = nla_get_u32
9405 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9406
9407 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9408 hdd_err("attr Verbose mask failed");
9409 return -EINVAL;
9410 }
9411 bit_mask = nla_get_u32
9412 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9413
9414 status = hdd_qdf_trace_enable(module_id, bit_mask);
9415
9416 if (status != 0)
9417 hdd_err("can not set verbose mask %d for the category %d",
9418 bit_mask, module_id);
9419 }
9420
9421 EXIT();
9422 return ret;
9423}
9424
9425/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309426 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9427 * @wiphy: Pointer to wireless phy
9428 * @wdev: Pointer to wireless device
9429 * @data: Pointer to data
9430 * @data_len: Length of @data
9431 *
9432 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9433 *
9434 * Return: 0 on success, negative errno on failure
9435 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309436
9437static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9438 struct wireless_dev *wdev,
9439 const void *data,
9440 int data_len)
9441{
9442 int ret;
9443
9444 cds_ssr_protect(__func__);
9445 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9446 cds_ssr_unprotect(__func__);
9447
9448 return ret;
9449}
9450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009451const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9452 {
9453 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9454 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9455 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309456 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009457 .doit = is_driver_dfs_capable
9458 },
9459
9460#ifdef WLAN_FEATURE_NAN
9461 {
9462 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9463 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9464 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9465 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9466 .doit = wlan_hdd_cfg80211_nan_request
9467 },
9468#endif
9469
9470#ifdef WLAN_FEATURE_STATS_EXT
9471 {
9472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9473 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9474 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9475 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9476 .doit = wlan_hdd_cfg80211_stats_ext_request
9477 },
9478#endif
9479#ifdef FEATURE_WLAN_EXTSCAN
9480 {
9481 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9482 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9483 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9484 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9485 .doit = wlan_hdd_cfg80211_extscan_start
9486 },
9487 {
9488 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9489 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9490 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9491 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9492 .doit = wlan_hdd_cfg80211_extscan_stop
9493 },
9494 {
9495 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9496 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9497 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9498 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9499 },
9500 {
9501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9504 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9505 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9506 },
9507 {
9508 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9509 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9510 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9511 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9512 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9513 },
9514 {
9515 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9516 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9517 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9518 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9519 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9520 },
9521 {
9522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9525 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9526 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9527 },
9528 {
9529 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9530 .info.subcmd =
9531 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9532 .flags =
9533 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9534 WIPHY_VENDOR_CMD_NEED_RUNNING,
9535 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9536 },
9537 {
9538 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9539 .info.subcmd =
9540 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9541 .flags =
9542 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9543 WIPHY_VENDOR_CMD_NEED_RUNNING,
9544 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9545 },
9546 {
9547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9550 WIPHY_VENDOR_CMD_NEED_NETDEV |
9551 WIPHY_VENDOR_CMD_NEED_RUNNING,
9552 .doit = wlan_hdd_cfg80211_set_epno_list
9553 },
9554#endif /* FEATURE_WLAN_EXTSCAN */
9555
9556#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9557 {
9558 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9559 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9560 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9561 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9562 .doit = wlan_hdd_cfg80211_ll_stats_clear
9563 },
9564
9565 {
9566 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9567 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9568 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9569 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9570 .doit = wlan_hdd_cfg80211_ll_stats_set
9571 },
9572
9573 {
9574 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9575 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9576 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9577 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9578 .doit = wlan_hdd_cfg80211_ll_stats_get
9579 },
9580#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9581#ifdef FEATURE_WLAN_TDLS
9582 {
9583 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9584 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9585 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9586 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9587 .doit = wlan_hdd_cfg80211_exttdls_enable
9588 },
9589 {
9590 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9591 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9592 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9593 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9594 .doit = wlan_hdd_cfg80211_exttdls_disable
9595 },
9596 {
9597 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9598 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9599 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9600 .doit = wlan_hdd_cfg80211_exttdls_get_status
9601 },
9602#endif
9603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9607 .doit = wlan_hdd_cfg80211_get_supported_features
9608 },
9609 {
9610 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9611 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9612 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9613 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9614 },
9615 {
9616 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9617 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9618 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309619 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009620 },
9621 {
9622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9625 WIPHY_VENDOR_CMD_NEED_NETDEV,
9626 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9627 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009628 {
9629 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9630 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9632 WIPHY_VENDOR_CMD_NEED_NETDEV,
9633 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9634 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009635 {
9636 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309637 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9638 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9639 WIPHY_VENDOR_CMD_NEED_NETDEV |
9640 WIPHY_VENDOR_CMD_NEED_RUNNING,
9641 .doit = hdd_cfg80211_get_station_cmd
9642 },
9643 {
9644 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009645 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9646 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9647 WIPHY_VENDOR_CMD_NEED_NETDEV |
9648 WIPHY_VENDOR_CMD_NEED_RUNNING,
9649 .doit = wlan_hdd_cfg80211_do_acs
9650 },
9651
9652 {
9653 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9654 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9655 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9656 WIPHY_VENDOR_CMD_NEED_NETDEV,
9657 .doit = wlan_hdd_cfg80211_get_features
9658 },
9659#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9660 {
9661 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9662 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9664 WIPHY_VENDOR_CMD_NEED_NETDEV |
9665 WIPHY_VENDOR_CMD_NEED_RUNNING,
9666 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9667 },
9668#endif
9669#ifdef FEATURE_WLAN_EXTSCAN
9670 {
9671 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9672 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9673 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9674 WIPHY_VENDOR_CMD_NEED_NETDEV |
9675 WIPHY_VENDOR_CMD_NEED_RUNNING,
9676 .doit = wlan_hdd_cfg80211_set_passpoint_list
9677 },
9678 {
9679 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9680 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9681 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9682 WIPHY_VENDOR_CMD_NEED_NETDEV |
9683 WIPHY_VENDOR_CMD_NEED_RUNNING,
9684 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9685 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686#endif /* FEATURE_WLAN_EXTSCAN */
9687 {
9688 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9689 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9690 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9691 WIPHY_VENDOR_CMD_NEED_NETDEV,
9692 .doit = wlan_hdd_cfg80211_get_wifi_info
9693 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009694#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695 {
9696 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9697 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9698 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9699 WIPHY_VENDOR_CMD_NEED_NETDEV |
9700 WIPHY_VENDOR_CMD_NEED_RUNNING,
9701 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9702 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009703#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009704 {
9705 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9706 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9707 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9708 WIPHY_VENDOR_CMD_NEED_NETDEV,
9709 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9710 },
9711 {
9712 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9713 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9714 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9715 WIPHY_VENDOR_CMD_NEED_NETDEV,
9716 .doit = wlan_hdd_cfg80211_wifi_logger_start
9717 },
9718 {
9719 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9720 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9721 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9722 WIPHY_VENDOR_CMD_NEED_NETDEV,
9723 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9724 },
9725 {
9726 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9727 .info.subcmd =
9728 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9729 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9730 WIPHY_VENDOR_CMD_NEED_NETDEV |
9731 WIPHY_VENDOR_CMD_NEED_RUNNING,
9732 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9733 },
9734 {
9735 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9736 .info.subcmd =
9737 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9738 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9739 WIPHY_VENDOR_CMD_NEED_NETDEV |
9740 WIPHY_VENDOR_CMD_NEED_RUNNING,
9741 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9742 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009743#ifdef WLAN_FEATURE_TSF
9744 {
9745 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9746 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9747 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9748 WIPHY_VENDOR_CMD_NEED_NETDEV |
9749 WIPHY_VENDOR_CMD_NEED_RUNNING,
9750 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9751 },
9752#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009753#ifdef FEATURE_WLAN_TDLS
9754 {
9755 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9756 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9757 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9758 WIPHY_VENDOR_CMD_NEED_NETDEV |
9759 WIPHY_VENDOR_CMD_NEED_RUNNING,
9760 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9761 },
9762#endif
9763#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9764 {
9765 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9766 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9767 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9768 WIPHY_VENDOR_CMD_NEED_NETDEV |
9769 WIPHY_VENDOR_CMD_NEED_RUNNING,
9770 .doit = wlan_hdd_cfg80211_offloaded_packets
9771 },
9772#endif
9773 {
9774 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9775 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9776 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9777 WIPHY_VENDOR_CMD_NEED_NETDEV |
9778 WIPHY_VENDOR_CMD_NEED_RUNNING,
9779 .doit = wlan_hdd_cfg80211_monitor_rssi
9780 },
9781 {
9782 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309783 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9784 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9785 WIPHY_VENDOR_CMD_NEED_NETDEV |
9786 WIPHY_VENDOR_CMD_NEED_RUNNING,
9787 .doit = wlan_hdd_cfg80211_set_ns_offload
9788 },
9789 {
9790 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9792 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9793 WIPHY_VENDOR_CMD_NEED_NETDEV |
9794 WIPHY_VENDOR_CMD_NEED_RUNNING,
9795 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9796 },
9797#ifdef WLAN_FEATURE_MEMDUMP
9798 {
9799 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9800 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9801 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9802 WIPHY_VENDOR_CMD_NEED_NETDEV |
9803 WIPHY_VENDOR_CMD_NEED_RUNNING,
9804 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9805 },
9806#endif /* WLAN_FEATURE_MEMDUMP */
9807 {
9808 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9809 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9810 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9811 WIPHY_VENDOR_CMD_NEED_NETDEV |
9812 WIPHY_VENDOR_CMD_NEED_RUNNING,
9813 .doit = wlan_hdd_cfg80211_vendor_scan
9814 },
9815
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309816 /* Vendor abort scan */
9817 {
9818 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9819 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9821 WIPHY_VENDOR_CMD_NEED_NETDEV |
9822 WIPHY_VENDOR_CMD_NEED_RUNNING,
9823 .doit = wlan_hdd_vendor_abort_scan
9824 },
9825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009826 /* OCB commands */
9827 {
9828 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9829 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9830 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9831 WIPHY_VENDOR_CMD_NEED_NETDEV |
9832 WIPHY_VENDOR_CMD_NEED_RUNNING,
9833 .doit = wlan_hdd_cfg80211_ocb_set_config
9834 },
9835 {
9836 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9837 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9838 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9839 WIPHY_VENDOR_CMD_NEED_NETDEV |
9840 WIPHY_VENDOR_CMD_NEED_RUNNING,
9841 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9842 },
9843 {
9844 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9845 .info.subcmd =
9846 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9847 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9848 WIPHY_VENDOR_CMD_NEED_NETDEV |
9849 WIPHY_VENDOR_CMD_NEED_RUNNING,
9850 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9851 },
9852 {
9853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9856 WIPHY_VENDOR_CMD_NEED_NETDEV |
9857 WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9859 },
9860 {
9861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9864 WIPHY_VENDOR_CMD_NEED_NETDEV |
9865 WIPHY_VENDOR_CMD_NEED_RUNNING,
9866 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9867 },
9868 {
9869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9872 WIPHY_VENDOR_CMD_NEED_NETDEV |
9873 WIPHY_VENDOR_CMD_NEED_RUNNING,
9874 .doit = wlan_hdd_cfg80211_dcc_get_stats
9875 },
9876 {
9877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9880 WIPHY_VENDOR_CMD_NEED_NETDEV |
9881 WIPHY_VENDOR_CMD_NEED_RUNNING,
9882 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9883 },
9884 {
9885 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9886 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9887 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9888 WIPHY_VENDOR_CMD_NEED_NETDEV |
9889 WIPHY_VENDOR_CMD_NEED_RUNNING,
9890 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9891 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309892 {
9893 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9894 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9895 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9896 WIPHY_VENDOR_CMD_NEED_NETDEV |
9897 WIPHY_VENDOR_CMD_NEED_RUNNING,
9898 .doit = wlan_hdd_cfg80211_get_link_properties
9899 },
Peng Xu278d0122015-09-24 16:34:17 -07009900 {
Peng Xud2220962016-07-11 17:59:17 -07009901 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009902 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9903 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9904 WIPHY_VENDOR_CMD_NEED_NETDEV |
9905 WIPHY_VENDOR_CMD_NEED_RUNNING,
9906 .doit = wlan_hdd_cfg80211_set_ota_test
9907 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009908#ifdef FEATURE_LFR_SUBNET_DETECTION
9909 {
9910 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9911 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9912 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9913 WIPHY_VENDOR_CMD_NEED_NETDEV |
9914 WIPHY_VENDOR_CMD_NEED_RUNNING,
9915 .doit = wlan_hdd_cfg80211_set_gateway_params
9916 },
9917#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009918 {
Peng Xud2220962016-07-11 17:59:17 -07009919 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009920 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9921 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9922 WIPHY_VENDOR_CMD_NEED_NETDEV |
9923 WIPHY_VENDOR_CMD_NEED_RUNNING,
9924 .doit = wlan_hdd_cfg80211_txpower_scale
9925 },
9926 {
9927 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9928 .info.subcmd =
9929 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9931 WIPHY_VENDOR_CMD_NEED_NETDEV |
9932 WIPHY_VENDOR_CMD_NEED_RUNNING,
9933 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9934 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309935 {
9936 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9937 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9938 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9939 WIPHY_VENDOR_CMD_NEED_NETDEV |
9940 WIPHY_VENDOR_CMD_NEED_RUNNING,
9941 .doit = wlan_hdd_cfg80211_bpf_offload
9942 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309943 {
9944 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309945 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9946 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9947 WIPHY_VENDOR_CMD_NEED_NETDEV |
9948 WIPHY_VENDOR_CMD_NEED_RUNNING,
9949 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9950 },
9951 {
9952 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309953 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9955 WIPHY_VENDOR_CMD_NEED_NETDEV |
9956 WIPHY_VENDOR_CMD_NEED_RUNNING,
9957 .doit = wlan_hdd_cfg80211_sta_roam_policy
9958 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309959#ifdef FEATURE_WLAN_CH_AVOID
9960 {
9961 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9962 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9963 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9964 WIPHY_VENDOR_CMD_NEED_NETDEV |
9965 WIPHY_VENDOR_CMD_NEED_RUNNING,
9966 .doit = wlan_hdd_cfg80211_avoid_freq
9967 },
9968#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309969 {
9970 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309971 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9973 WIPHY_VENDOR_CMD_NEED_NETDEV |
9974 WIPHY_VENDOR_CMD_NEED_RUNNING,
9975 .doit = wlan_hdd_cfg80211_sap_configuration_set
9976 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009977 {
Peng Xu4225c152016-07-14 21:18:14 -07009978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009979 .info.subcmd =
9980 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9981 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9982 WIPHY_VENDOR_CMD_NEED_NETDEV |
9983 WIPHY_VENDOR_CMD_NEED_RUNNING,
9984 .doit = wlan_hdd_cfg80211_p2p_lo_start
9985 },
9986 {
9987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9988 .info.subcmd =
9989 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9990 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9991 WIPHY_VENDOR_CMD_NEED_NETDEV |
9992 WIPHY_VENDOR_CMD_NEED_RUNNING,
9993 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9994 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309995 {
9996 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9997 .info.subcmd =
9998 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9999 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10000 WIPHY_VENDOR_CMD_NEED_NETDEV |
10001 WIPHY_VENDOR_CMD_NEED_RUNNING,
10002 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10003 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010004#ifdef WLAN_FEATURE_NAN_DATAPATH
10005 {
10006 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10007 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10008 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10009 WIPHY_VENDOR_CMD_NEED_NETDEV |
10010 WIPHY_VENDOR_CMD_NEED_RUNNING,
10011 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10012 },
10013#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010014 {
10015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10018 WIPHY_VENDOR_CMD_NEED_NETDEV |
10019 WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10021 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010022 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010023 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10024 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10025 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10026 WIPHY_VENDOR_CMD_NEED_NETDEV |
10027 WIPHY_VENDOR_CMD_NEED_RUNNING,
10028 .doit = wlan_hdd_cfg80211_get_bus_size
10029 },
10030 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010031 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10032 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10033 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10034 WIPHY_VENDOR_CMD_NEED_NETDEV |
10035 WIPHY_VENDOR_CMD_NEED_RUNNING,
10036 .doit = wlan_hdd_cfg80211_update_vendor_channel
10037 },
10038 {
bingsd09dea32017-03-17 10:08:26 +080010039 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010040 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10041 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10042 WIPHY_VENDOR_CMD_NEED_NETDEV |
10043 WIPHY_VENDOR_CMD_NEED_RUNNING,
10044 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010045 },
10046 {
10047 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10048 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10049 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10050 WIPHY_VENDOR_CMD_NEED_NETDEV |
10051 WIPHY_VENDOR_CMD_NEED_RUNNING,
10052 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010053 },
10054#ifdef WLAN_FEATURE_DISA
10055 {
10056 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10057 .info.subcmd =
10058 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10059 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10060 WIPHY_VENDOR_CMD_NEED_NETDEV |
10061 WIPHY_VENDOR_CMD_NEED_RUNNING,
10062 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10063 },
10064#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010065#ifdef FEATURE_WLAN_TDLS
10066 {
10067 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10068 .info.subcmd =
10069 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10070 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10071 WIPHY_VENDOR_CMD_NEED_NETDEV |
10072 WIPHY_VENDOR_CMD_NEED_RUNNING,
10073 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010074 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010075#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010076 {
10077 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10078 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10079 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10080 WIPHY_VENDOR_CMD_NEED_RUNNING,
10081 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10082 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010083 {
10084 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10085 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10086 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10087 WIPHY_VENDOR_CMD_NEED_NETDEV |
10088 WIPHY_VENDOR_CMD_NEED_RUNNING,
10089 .doit = wlan_hdd_cfg80211_set_trace_level
10090 },
10091
Paul Zhang3a210c52016-12-08 10:18:12 +080010092#ifdef WLAN_UMAC_CONVERGENCE
10093 COMMON_VENDOR_COMMANDS
10094#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010095 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010096};
10097
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010098#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10099 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10100 defined(FEATURE_WLAN_SCAN_PNO)
10101/**
10102 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10103 * @wiphy: pointer to wiphy
10104 * @config: pointer to config
10105 *
10106 * Return: None
10107 */
10108static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10109 struct hdd_config *config)
10110{
10111 if (config->configPNOScanSupport) {
10112 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010113 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10114 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010115 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010116 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010117 if (config->max_sched_scan_plan_interval)
10118 wiphy->max_sched_scan_plan_interval =
10119 config->max_sched_scan_plan_interval;
10120 if (config->max_sched_scan_plan_iterations)
10121 wiphy->max_sched_scan_plan_iterations =
10122 config->max_sched_scan_plan_iterations;
10123 }
10124}
10125#else
10126static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10127 struct hdd_config *config)
10128{
10129}
10130#endif
10131
10132
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010133/**
10134 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10135 * @priv_size: Size of the hdd context.
10136 *
10137 * Allocate wiphy context and hdd context.
10138 *
10139 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010141hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010142{
10143 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010144 hdd_context_t *hdd_ctx;
10145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010146 ENTER();
10147
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10149
10150 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010151 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010152 return NULL;
10153 }
10154
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010155 hdd_ctx = wiphy_priv(wiphy);
10156
10157 hdd_ctx->wiphy = wiphy;
10158
10159 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010160}
10161
10162/*
10163 * FUNCTION: wlan_hdd_cfg80211_update_band
10164 * This function is called from the supplicant through a
10165 * private ioctl to change the band value
10166 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010167int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10168 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010169{
10170 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010171 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010172
10173 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010174 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010175
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010176 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010177 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010178
10179 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10180 struct ieee80211_supported_band *band = wiphy->bands[i];
10181
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010182 channelEnabledState = wlan_reg_get_channel_state(
10183 hdd_ctx->hdd_pdev,
10184 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185
Dustin Browna30892e2016-10-12 17:28:36 -070010186 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187 /* 5G only */
10188#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10189 /* Enable Social channels for P2P */
10190 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10191 (band->channels[j].center_freq)
10192 && CHANNEL_STATE_ENABLE ==
10193 channelEnabledState)
10194 band->channels[j].flags &=
10195 ~IEEE80211_CHAN_DISABLED;
10196 else
10197#endif
10198 band->channels[j].flags |=
10199 IEEE80211_CHAN_DISABLED;
10200 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010201 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010202 eCSR_BAND_24 == eBand) {
10203 /* 2G only */
10204 band->channels[j].flags |=
10205 IEEE80211_CHAN_DISABLED;
10206 continue;
10207 }
10208
Amar Singhal6842e8f2016-02-23 16:30:32 -080010209 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010210 band->channels[j].flags &=
10211 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010212 }
10213 }
10214 return 0;
10215}
10216
Peng Xuacfdda12017-02-06 16:15:38 -080010217#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010218/*
10219 * FUNCTION: wlan_hdd_cfg80211_init
10220 * This function is called by hdd_wlan_startup()
10221 * during initialization.
10222 * This function is used to initialize and register wiphy structure.
10223 */
10224int wlan_hdd_cfg80211_init(struct device *dev,
10225 struct wiphy *wiphy, struct hdd_config *pCfg)
10226{
10227 int i, j;
10228 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10229
10230 ENTER();
10231
10232 /* Now bind the underlying wlan device with wiphy */
10233 set_wiphy_dev(wiphy, dev);
10234
10235 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10236
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010237 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10238 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10239 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10240#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10241 | WIPHY_FLAG_4ADDR_STATION
10242#endif
10243 | WIPHY_FLAG_OFFCHAN_TX;
10244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010245#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10246 wiphy->wowlan = &wowlan_support_cfg80211_init;
10247#else
10248 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10249 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10250 wiphy->wowlan.pattern_min_len = 1;
10251 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10252#endif
10253
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010254 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010255#ifdef FEATURE_WLAN_ESE
10256 || pCfg->isEseIniFeatureEnabled
10257#endif
10258 ) {
10259 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10260 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261#ifdef FEATURE_WLAN_TDLS
10262 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10263 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10264#endif
10265
10266 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10267
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010268#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10269 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10270#endif
10271
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010272 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010273
10274#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010275 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276#endif
10277
10278 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010279 * driver can still register regulatory callback and
10280 * it will get regulatory settings in wiphy->band[], but
10281 * driver need to determine what to do with both
10282 * regulatory settings
10283 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010284
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285#if defined QCA_WIFI_FTM
10286}
10287#endif
10288
10289 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10290
10291 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10292
10293 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10294
Arun Khandavallifae92942016-08-01 13:31:08 +053010295 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10296 | BIT(NL80211_IFTYPE_ADHOC)
10297 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10298 | BIT(NL80211_IFTYPE_P2P_GO)
10299 | BIT(NL80211_IFTYPE_AP)
10300 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301
Arun Khandavallifae92942016-08-01 13:31:08 +053010302 if (pCfg->advertiseConcurrentOperation) {
10303 if (pCfg->enableMCC) {
10304 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010305
Arun Khandavallifae92942016-08-01 13:31:08 +053010306 for (i = 0;
10307 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10308 i++) {
10309 if (!pCfg->allowMCCGODiffBI)
10310 wlan_hdd_iface_combination[i].
10311 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 }
10313 }
10314 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010315 ARRAY_SIZE(wlan_hdd_iface_combination);
10316 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010317 }
10318
10319 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010320 * on ini values
10321 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010322 if (!pCfg->ShortGI20MhzEnable) {
10323 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10324 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010325 }
10326
10327 if (!pCfg->ShortGI40MhzEnable) {
10328 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10329 }
10330
10331 if (!pCfg->nChannelBondingMode5GHz) {
10332 wlan_hdd_band_5_ghz.ht_cap.cap &=
10333 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10334 }
10335
Abhishek Singhf512bf32016-05-04 16:47:46 +053010336 /*
10337 * In case of static linked driver at the time of driver unload,
10338 * module exit doesn't happens. Module cleanup helps in cleaning
10339 * of static memory.
10340 * If driver load happens statically, at the time of driver unload,
10341 * wiphy flags don't get reset because of static memory.
10342 * It's better not to store channel in static memory.
10343 */
Dustin Browna30892e2016-10-12 17:28:36 -070010344 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10345 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010346 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010347 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010348 hdd_err("Not enough memory to allocate channels");
10349 return -ENOMEM;
10350 }
Dustin Browna30892e2016-10-12 17:28:36 -070010351 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010352 &hdd_channels_2_4_ghz[0],
10353 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010354 if ((hdd_is_5g_supported(pHddCtx)) &&
10355 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10356 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10357 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10358 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010359 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10360 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010361 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010362 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010363 hdd_err("Not enough memory to allocate channels");
10364 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010365 bands[NL80211_BAND_2GHZ]->channels);
10366 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010367 return -ENOMEM;
10368 }
Dustin Browna30892e2016-10-12 17:28:36 -070010369 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010370 &hdd_channels_5_ghz[0],
10371 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 }
10373
Dustin Browna30892e2016-10-12 17:28:36 -070010374 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010375
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010376 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010377 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010378
10379 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10380 struct ieee80211_supported_band *band = wiphy->bands[i];
10381
Dustin Browna30892e2016-10-12 17:28:36 -070010382 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010383 eCSR_BAND_5G == pCfg->nBandCapability) {
10384 /* 5G only */
10385#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10386 /* Enable social channels for P2P */
10387 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10388 (band->channels[j].center_freq))
10389 band->channels[j].flags &=
10390 ~IEEE80211_CHAN_DISABLED;
10391 else
10392#endif
10393 band->channels[j].flags |=
10394 IEEE80211_CHAN_DISABLED;
10395 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010396 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010397 eCSR_BAND_24 == pCfg->nBandCapability) {
10398 /* 2G only */
10399 band->channels[j].flags |=
10400 IEEE80211_CHAN_DISABLED;
10401 continue;
10402 }
10403 }
10404 }
10405 /*Initialise the supported cipher suite details */
10406 wiphy->cipher_suites = hdd_cipher_suites;
10407 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10408
10409 /*signal strength in mBm (100*dBm) */
10410 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10411 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10412
Anurag Chouhan6d760662016-02-20 16:05:43 +053010413 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414 wiphy->n_vendor_commands =
10415 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10416 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10417
10418 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10419 wiphy->n_vendor_events =
10420 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10421 }
10422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010423 if (pCfg->enableDFSMasterCap) {
10424 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10425 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010426
10427 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10428
10429#ifdef QCA_HT_2040_COEX
10430 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10431#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010432 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010433
10434#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10435 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10436 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10437 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10438 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10439#endif
10440
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010441 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010442 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010444 EXIT();
10445 return 0;
10446}
10447
Abhishek Singhf512bf32016-05-04 16:47:46 +053010448/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010449 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10450 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010451 *
10452 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010453 * memory allocated in wlan_hdd_cfg80211_init also
10454 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010455 *
10456 * Return: void
10457 */
10458void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10459{
10460 int i;
10461
Dustin Browna30892e2016-10-12 17:28:36 -070010462 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010463 if (NULL != wiphy->bands[i] &&
10464 (NULL != wiphy->bands[i]->channels)) {
10465 qdf_mem_free(wiphy->bands[i]->channels);
10466 wiphy->bands[i]->channels = NULL;
10467 }
10468 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010469
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010470 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010471}
10472
Yingying Tang80e15f32016-09-27 18:23:01 +080010473/**
10474 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10475 * @hdd_ctx: HDD context
10476 *
10477 * this function will update capabilities for supported bands
10478 *
10479 * Return: void
10480 */
10481static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10482{
10483 uint32_t val32;
10484 uint16_t val16;
10485 tSirMacHTCapabilityInfo *ht_cap_info;
10486 QDF_STATUS status;
10487
10488 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10489 if (QDF_STATUS_SUCCESS != status) {
10490 hdd_err("could not get HT capability info");
10491 val32 = 0;
10492 }
10493 val16 = (uint16_t)val32;
10494 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10495
10496 if (ht_cap_info->txSTBC == true) {
10497 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10498 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10499 IEEE80211_HT_CAP_TX_STBC;
10500 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10501 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10502 IEEE80211_HT_CAP_TX_STBC;
10503 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010504
10505 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10506 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10507 vht_cap.vht_supported = 0;
10508 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10509 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10510 vht_cap.vht_supported = 0;
10511 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10512 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010513}
10514
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010515/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010516 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010517 * initialization. In wlan_hdd_cfg80211_init, only the
10518 * default values will be initialized. The final initialization
10519 * of all required members can be done here.
10520 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010521void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010522{
Yingying Tang80e15f32016-09-27 18:23:01 +080010523 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10524
10525 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010526}
10527
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010528/**
10529 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10530 * @cfg: hdd cfg
10531 *
10532 * this function update 11n mode in hdd cfg
10533 *
10534 * Return: void
10535 */
10536void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10537{
10538 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010539 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010540 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010541 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010542 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10543 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10544 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10545 cfg->sap_p2p_11ac_override = 0;
10546 }
10547 }
10548}
10549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010550/* In this function we are registering wiphy. */
10551int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10552{
10553 ENTER();
10554 /* Register our wiphy dev with cfg80211 */
10555 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010556 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010557 return -EIO;
10558 }
10559
10560 EXIT();
10561 return 0;
10562}
10563
10564/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010565 * HDD function to update wiphy capability based on target offload status.
10566 *
10567 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10568 * capability even before downloading firmware to the target. In discrete
10569 * case, host will get know certain offload capability (say sched_scan
10570 * caps) only after downloading firmware to the target and target boots up.
10571 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10572 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010573 */
10574void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10575{
10576#ifdef FEATURE_WLAN_SCAN_PNO
10577 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10578 struct hdd_config *pCfg = pHddCtx->config;
10579
10580 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10581 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010582 * have PNO support.
10583 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010584 if (!pCfg->PnoOffload) {
10585 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10586 wiphy->max_sched_scan_ssids = 0;
10587 wiphy->max_match_sets = 0;
10588 wiphy->max_sched_scan_ie_len = 0;
10589 }
10590#endif
10591}
10592
10593/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010594#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10595
Wu Gao84d120c2017-03-24 18:46:00 +080010596void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10597{
10598 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10599 /* Register for all P2P action, public action etc frames */
10600 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10601
10602 ENTER();
10603
10604 /* Register frame indication call back */
10605 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10606
10607 /* Register for p2p ack indication */
10608 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10609
10610 /* Right now we are registering these frame when driver is getting
10611 * initialized. Once we will move to 2.6.37 kernel, in which we have
10612 * frame register ops, we will move this code as a part of that
10613 */
10614
10615 /* GAS Initial Request */
10616 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10617 (uint8_t *) GAS_INITIAL_REQ,
10618 GAS_INITIAL_REQ_SIZE);
10619
10620 /* GAS Initial Response */
10621 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10622 (uint8_t *) GAS_INITIAL_RSP,
10623 GAS_INITIAL_RSP_SIZE);
10624
10625 /* GAS Comeback Request */
10626 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10627 (uint8_t *) GAS_COMEBACK_REQ,
10628 GAS_COMEBACK_REQ_SIZE);
10629
10630 /* GAS Comeback Response */
10631 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10632 (uint8_t *) GAS_COMEBACK_RSP,
10633 GAS_COMEBACK_RSP_SIZE);
10634
10635 /* WNM BSS Transition Request frame */
10636 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10637 (uint8_t *) WNM_BSS_ACTION_FRAME,
10638 WNM_BSS_ACTION_FRAME_SIZE);
10639
10640 /* WNM-Notification */
10641 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10642 (uint8_t *) WNM_NOTIFICATION_FRAME,
10643 WNM_NOTIFICATION_FRAME_SIZE);
10644}
10645#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010646void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10647{
10648 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10649 /* Register for all P2P action, public action etc frames */
10650 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10651
10652 ENTER();
10653
Abhishek Singh7996eb72015-12-30 17:24:02 +053010654 /* Register frame indication call back */
10655 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10656
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010657 /* Register for p2p ack indication */
10658 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010660 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010661 * initialized. Once we will move to 2.6.37 kernel, in which we have
10662 * frame register ops, we will move this code as a part of that
10663 */
10664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010665 /* GAS Initial Request */
10666 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10667 (uint8_t *) GAS_INITIAL_REQ,
10668 GAS_INITIAL_REQ_SIZE);
10669
10670 /* GAS Initial Response */
10671 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10672 (uint8_t *) GAS_INITIAL_RSP,
10673 GAS_INITIAL_RSP_SIZE);
10674
10675 /* GAS Comeback Request */
10676 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10677 (uint8_t *) GAS_COMEBACK_REQ,
10678 GAS_COMEBACK_REQ_SIZE);
10679
10680 /* GAS Comeback Response */
10681 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10682 (uint8_t *) GAS_COMEBACK_RSP,
10683 GAS_COMEBACK_RSP_SIZE);
10684
10685 /* P2P Public Action */
10686 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10687 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10688 P2P_PUBLIC_ACTION_FRAME_SIZE);
10689
10690 /* P2P Action */
10691 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10692 (uint8_t *) P2P_ACTION_FRAME,
10693 P2P_ACTION_FRAME_SIZE);
10694
10695 /* WNM BSS Transition Request frame */
10696 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10697 (uint8_t *) WNM_BSS_ACTION_FRAME,
10698 WNM_BSS_ACTION_FRAME_SIZE);
10699
10700 /* WNM-Notification */
10701 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10702 (uint8_t *) WNM_NOTIFICATION_FRAME,
10703 WNM_NOTIFICATION_FRAME_SIZE);
10704}
Wu Gao84d120c2017-03-24 18:46:00 +080010705#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706
10707void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10708{
10709 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10710 /* Register for all P2P action, public action etc frames */
10711 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10712
10713 ENTER();
10714
10715 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010716 * initialized. Once we will move to 2.6.37 kernel, in which we have
10717 * frame register ops, we will move this code as a part of that
10718 */
10719
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010720 /* GAS Initial Request */
10721
10722 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10723 (uint8_t *) GAS_INITIAL_REQ,
10724 GAS_INITIAL_REQ_SIZE);
10725
10726 /* GAS Initial Response */
10727 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10728 (uint8_t *) GAS_INITIAL_RSP,
10729 GAS_INITIAL_RSP_SIZE);
10730
10731 /* GAS Comeback Request */
10732 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10733 (uint8_t *) GAS_COMEBACK_REQ,
10734 GAS_COMEBACK_REQ_SIZE);
10735
10736 /* GAS Comeback Response */
10737 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10738 (uint8_t *) GAS_COMEBACK_RSP,
10739 GAS_COMEBACK_RSP_SIZE);
10740
10741 /* P2P Public Action */
10742 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10743 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10744 P2P_PUBLIC_ACTION_FRAME_SIZE);
10745
10746 /* P2P Action */
10747 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10748 (uint8_t *) P2P_ACTION_FRAME,
10749 P2P_ACTION_FRAME_SIZE);
10750
10751 /* WNM-Notification */
10752 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10753 (uint8_t *) WNM_NOTIFICATION_FRAME,
10754 WNM_NOTIFICATION_FRAME_SIZE);
10755}
10756
10757#ifdef FEATURE_WLAN_WAPI
10758void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10759 const uint8_t *mac_addr, const uint8_t *key,
10760 int key_Len)
10761{
10762 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10763 tCsrRoamSetKey setKey;
10764 bool isConnected = true;
10765 int status = 0;
10766 uint32_t roamId = 0xFF;
10767 uint8_t *pKeyPtr = NULL;
10768 int n = 0;
10769
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010770 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771 hdd_device_mode_to_string(pAdapter->device_mode),
10772 pAdapter->device_mode);
10773
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010774 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010775 setKey.keyId = key_index; /* Store Key ID */
10776 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10777 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10778 setKey.paeRole = 0; /* the PAE role */
10779 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010780 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010781 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010782 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010783 }
10784 setKey.keyLength = key_Len;
10785 pKeyPtr = setKey.Key;
10786 memcpy(pKeyPtr, key, key_Len);
10787
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010788 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010789 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010790 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010791 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792
10793 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10794 if (isConnected) {
10795 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10796 pAdapter->sessionId, &setKey, &roamId);
10797 }
10798 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010799 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010800 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10801 }
10802}
10803#endif /* FEATURE_WLAN_WAPI */
10804
10805uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10806 uint8_t eid)
10807{
10808 int left = length;
10809 uint8_t *ptr = (uint8_t *)ies_ptr;
10810 uint8_t elem_id, elem_len;
10811
10812 while (left >= 2) {
10813 elem_id = ptr[0];
10814 elem_len = ptr[1];
10815 left -= 2;
10816 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010817 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818 eid, elem_len, left);
10819 return NULL;
10820 }
10821 if (elem_id == eid) {
10822 return ptr;
10823 }
10824
10825 left -= elem_len;
10826 ptr += (elem_len + 2);
10827 }
10828 return NULL;
10829}
10830
10831/*
10832 * FUNCTION: wlan_hdd_validate_operation_channel
10833 * called by wlan_hdd_cfg80211_start_bss() and
10834 * wlan_hdd_set_channel()
10835 * This function validates whether given channel is part of valid
10836 * channel list.
10837 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010838QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010839 int channel)
10840{
10841
10842 uint32_t num_ch = 0;
10843 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10844 u32 indx = 0;
10845 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10846 uint8_t fValidChannel = false, count = 0;
10847 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10848
10849 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10850
10851 if (hdd_pConfig_ini->sapAllowAllChannel) {
10852 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010853 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010854 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 fValidChannel = true;
10856 break;
10857 }
10858 }
10859 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010860 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010861 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862 }
10863 } else {
10864 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10865 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010866 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010867 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010868 }
10869 for (indx = 0; indx < num_ch; indx++) {
10870 if (channel == valid_ch[indx]) {
10871 break;
10872 }
10873 }
10874
10875 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010876 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010877 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010878 }
10879 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010880 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010881
10882}
10883
10884#ifdef DHCP_SERVER_OFFLOAD
10885static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10886{
10887 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10888 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10889 uint8_t numEntries = 0;
10890 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10891 uint8_t num;
10892 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010893 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010895 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010896 return;
10897 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010898 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10899 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10900 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10901 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10902 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10903 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010904 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010905 goto end;
10906 }
10907 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010908 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 goto end;
10910 }
10911 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010912 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913 goto end;
10914 }
10915 for (num = 0; num < numEntries; num++) {
10916 temp = srv_ip[num];
10917 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10918 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010919 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010921 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010922 goto end;
10923 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010924 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010925end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010926 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010927 return;
10928}
10929#endif /* DHCP_SERVER_OFFLOAD */
10930
10931static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10932 struct net_device *dev,
10933 struct bss_parameters *params)
10934{
10935 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10936 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10937 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010938 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010939
10940 ENTER();
10941
Anurag Chouhan6d760662016-02-20 16:05:43 +053010942 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010943 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010944 return -EINVAL;
10945 }
10946
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010947 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10948 hdd_err("invalid session id: %d", pAdapter->sessionId);
10949 return -EINVAL;
10950 }
10951
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010952 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010953 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10954 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010955 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010956 hdd_device_mode_to_string(pAdapter->device_mode),
10957 pAdapter->device_mode, params->ap_isolate);
10958
10959 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10960 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010961 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010962 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010963
Krunal Sonib4326f22016-03-10 13:05:51 -080010964 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10965 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010966 return -EOPNOTSUPP;
10967 }
10968
10969 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010970 * want to update this parameter
10971 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010972 if (-1 != params->ap_isolate) {
10973 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10974 !!params->ap_isolate;
10975
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010976 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010977 pAdapter->sessionId,
10978 pAdapter->sessionCtx.
10979 ap.
10980 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010981 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010982 ret = -EINVAL;
10983 }
10984 }
10985
10986 EXIT();
10987 return ret;
10988}
10989
Krunal Soni8c37e322016-02-03 16:08:37 -080010990/**
10991 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10992 * @ndev: pointer to net device provided by supplicant
10993 * @type: type of the interface, upper layer wanted to change
10994 *
10995 * Upper layer provides the new interface mode that needs to be changed
10996 * for given net device
10997 *
10998 * Return: success or failure in terms of integer value
10999 */
11000static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011001 enum nl80211_iftype type)
11002{
Krunal Soni8c37e322016-02-03 16:08:37 -080011003 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11004 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11005 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 hdd_wext_state_t *wext;
11007 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011008 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011009
11010 ENTER();
11011
Krunal Soni8c37e322016-02-03 16:08:37 -080011012 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011013 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014 return 0;
11015 }
11016
11017 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011018 hdd_stop_adapter(hdd_ctx, adapter, true);
11019 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 wdev->iftype = type;
11021 /*Check for sub-string p2p to confirm its a p2p interface */
11022 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011023 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011024 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011025 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011026 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011027 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011028 } else {
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_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011032 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011033 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11034 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011035 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11036 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011037 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011038 adapter->scan_info.scanAddIE.length;
11039 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011040 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011041 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11042 wext->roamProfile.phyMode =
11043 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11044 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 EXIT();
11046 return status;
11047}
11048
11049static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11050 struct net_device *dev,
11051 struct bss_parameters *params)
11052{
11053 int ret;
11054
11055 cds_ssr_protect(__func__);
11056 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11057 cds_ssr_unprotect(__func__);
11058
11059 return ret;
11060}
11061
11062/* FUNCTION: wlan_hdd_change_country_code_cd
11063 * to wait for contry code completion
11064 */
11065void *wlan_hdd_change_country_code_cb(void *pAdapter)
11066{
11067 hdd_adapter_t *call_back_pAdapter = pAdapter;
11068 complete(&call_back_pAdapter->change_country_code);
11069 return NULL;
11070}
11071
Rajeev Kumar98edb772016-01-19 12:42:19 -080011072/**
11073 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11074 * @wiphy: Pointer to the wiphy structure
11075 * @ndev: Pointer to the net device
11076 * @type: Interface type
11077 * @flags: Flags for change interface
11078 * @params: Pointer to change interface parameters
11079 *
11080 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011081 */
11082static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11083 struct net_device *ndev,
11084 enum nl80211_iftype type,
11085 u32 *flags,
11086 struct vif_params *params)
11087{
11088 struct wireless_dev *wdev;
11089 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11090 hdd_context_t *pHddCtx;
11091 tCsrRoamProfile *pRoamProfile = NULL;
11092 eCsrRoamBssType LastBSSType;
11093 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011094 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095 int status;
11096
11097 ENTER();
11098
Anurag Chouhan6d760662016-02-20 16:05:43 +053011099 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011100 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011101 return -EINVAL;
11102 }
11103
11104 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11105 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011106 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011108
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011109 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11111 pAdapter->sessionId, type));
11112
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011113 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011114 pAdapter->device_mode, type);
11115
Arun Khandavallifae92942016-08-01 13:31:08 +053011116 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11117 if (status) {
11118 hdd_err("Failed to start modules");
11119 return -EINVAL;
11120 }
11121
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011122 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011123 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11124 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011125 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011126 return -EINVAL;
11127 }
11128
11129 pConfig = pHddCtx->config;
11130 wdev = ndev->ieee80211_ptr;
11131
11132 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011133 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11134 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011135
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011136 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011137 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011138 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11139 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11140 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11141 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 hdd_wext_state_t *pWextState =
11143 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11144
11145 pRoamProfile = &pWextState->roamProfile;
11146 LastBSSType = pRoamProfile->BSSType;
11147
11148 switch (type) {
11149 case NL80211_IFTYPE_STATION:
11150 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011151 case NL80211_IFTYPE_ADHOC:
11152 if (type == NL80211_IFTYPE_ADHOC) {
11153 wlan_hdd_tdls_exit(pAdapter);
11154 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011155 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011156 }
11157 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11158 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011159 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011160 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011161 if (hdd_start_adapter(pAdapter)) {
11162 hdd_err("Failed to start adapter :%d",
11163 pAdapter->device_mode);
11164 return -EINVAL;
11165 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167 case NL80211_IFTYPE_AP:
11168 case NL80211_IFTYPE_P2P_GO:
11169 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011170 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011171 (type ==
11172 NL80211_IFTYPE_AP) ? "SoftAP" :
11173 "P2pGo");
11174
11175 /* Cancel any remain on channel for GO mode */
11176 if (NL80211_IFTYPE_P2P_GO == type) {
11177 wlan_hdd_cancel_existing_remain_on_channel
11178 (pAdapter);
11179 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180
Arun Khandavallifae92942016-08-01 13:31:08 +053011181 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011182 /* De-init the adapter */
11183 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11184 memset(&pAdapter->sessionCtx, 0,
11185 sizeof(pAdapter->sessionCtx));
11186 pAdapter->device_mode =
11187 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011188 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11189 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011190
11191 /*
11192 * Fw will take care incase of concurrency
11193 */
11194
Krunal Sonib4326f22016-03-10 13:05:51 -080011195 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011197 /* To meet Android requirements create
11198 * a randomized MAC address of the
11199 * form 02:1A:11:Fx:xx:xx
11200 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201 get_random_bytes(&ndev->dev_addr[3], 3);
11202 ndev->dev_addr[0] = 0x02;
11203 ndev->dev_addr[1] = 0x1A;
11204 ndev->dev_addr[2] = 0x11;
11205 ndev->dev_addr[3] |= 0xF0;
11206 memcpy(pAdapter->macAddressCurrent.
11207 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011208 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011209 pr_info("wlan: Generated HotSpot BSSID "
11210 MAC_ADDRESS_STR "\n",
11211 MAC_ADDR_ARRAY(ndev->dev_addr));
11212 }
11213
11214 hdd_set_ap_ops(pAdapter->dev);
11215
Arun Khandavallifae92942016-08-01 13:31:08 +053011216 if (hdd_start_adapter(pAdapter)) {
11217 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 return -EINVAL;
11219 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011220 /* Interface type changed update in wiphy structure */
11221 if (wdev) {
11222 wdev->iftype = type;
11223 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011224 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225 return -EINVAL;
11226 }
11227 goto done;
11228 }
11229
11230 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011231 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 return -EOPNOTSUPP;
11233 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011234 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11235 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011236 switch (type) {
11237 case NL80211_IFTYPE_STATION:
11238 case NL80211_IFTYPE_P2P_CLIENT:
11239 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011240 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11241 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011242 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011244 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011245 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011246 pAdapter->device_mode);
11247 return -EINVAL;
11248 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 goto done;
11250
11251 case NL80211_IFTYPE_AP:
11252 case NL80211_IFTYPE_P2P_GO:
11253 wdev->iftype = type;
11254 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011255 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256 goto done;
11257
11258 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011259 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260 return -EOPNOTSUPP;
11261 }
11262 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011263 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264 pAdapter->device_mode);
11265 return -EOPNOTSUPP;
11266 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011267done:
11268 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011269 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11270 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011271
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011272 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273
11274 EXIT();
11275 return 0;
11276}
11277
Rajeev Kumar98edb772016-01-19 12:42:19 -080011278/**
11279 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11280 * @wiphy: Pointer to the wiphy structure
11281 * @ndev: Pointer to the net device
11282 * @type: Interface type
11283 * @flags: Flags for change interface
11284 * @params: Pointer to change interface parameters
11285 *
11286 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 */
11288static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11289 struct net_device *ndev,
11290 enum nl80211_iftype type,
11291 u32 *flags,
11292 struct vif_params *params)
11293{
11294 int ret;
11295
11296 cds_ssr_protect(__func__);
11297 ret =
11298 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11299 cds_ssr_unprotect(__func__);
11300
11301 return ret;
11302}
11303
Frank Liud4b2fa02017-03-29 11:46:48 +080011304#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11306 int index, uint8_t match)
11307{
11308 int i;
11309 for (i = 0; i < index; i++) {
11310 if (arr[i] == match)
11311 return true;
11312 }
11313 return false;
11314}
11315#endif
11316
11317/**
11318 * __wlan_hdd_change_station() - change station
11319 * @wiphy: Pointer to the wiphy structure
11320 * @dev: Pointer to the net device.
11321 * @mac: bssid
11322 * @params: Pointer to station parameters
11323 *
11324 * Return: 0 for success, error number on failure.
11325 */
11326#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11327static int __wlan_hdd_change_station(struct wiphy *wiphy,
11328 struct net_device *dev,
11329 const uint8_t *mac,
11330 struct station_parameters *params)
11331#else
11332static int __wlan_hdd_change_station(struct wiphy *wiphy,
11333 struct net_device *dev,
11334 uint8_t *mac,
11335 struct station_parameters *params)
11336#endif
11337{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011338 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11340 hdd_context_t *pHddCtx;
11341 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011342 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011343#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 tCsrStaParams StaParams = { 0 };
11345 uint8_t isBufSta = 0;
11346 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011347 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348#endif
11349 int ret;
11350
11351 ENTER();
11352
Anurag Chouhan6d760662016-02-20 16:05:43 +053011353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011354 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011355 return -EINVAL;
11356 }
11357
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011358 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011359 TRACE_CODE_HDD_CHANGE_STATION,
11360 pAdapter->sessionId, params->listen_interval));
11361
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011362 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11363 hdd_err("invalid session id: %d", pAdapter->sessionId);
11364 return -EINVAL;
11365 }
11366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011367 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11368 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011369 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011371
11372 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11373
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011374 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375
Krunal Sonib4326f22016-03-10 13:05:51 -080011376 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11377 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011378 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11379 status =
11380 hdd_softap_change_sta_state(pAdapter,
11381 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011382 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011383
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011384 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011385 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386 return -EINVAL;
11387 }
11388 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011389 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11390 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011392#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11393 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11394 dev, mac, params);
11395#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011396
11397 if (cds_is_sub_20_mhz_enabled()) {
11398 hdd_err("TDLS not allowed with sub 20 MHz");
11399 return -EINVAL;
11400 }
11401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011402 StaParams.capability = params->capability;
11403 StaParams.uapsd_queues = params->uapsd_queues;
11404 StaParams.max_sp = params->max_sp;
11405
11406 /* Convert (first channel , number of channels) tuple to
11407 * the total list of channels. This goes with the assumption
11408 * that if the first channel is < 14, then the next channels
11409 * are an incremental of 1 else an incremental of 4 till the number
11410 * of channels.
11411 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011412 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011413 if (0 != params->supported_channels_len) {
11414 int i = 0, j = 0, k = 0, no_of_channels = 0;
11415 int num_unique_channels;
11416 int next;
11417 for (i = 0;
11418 i < params->supported_channels_len
11419 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11420 int wifi_chan_index;
11421 if (!wlan_hdd_is_duplicate_channel
11422 (StaParams.supported_channels, j,
11423 params->supported_channels[i])) {
11424 StaParams.
11425 supported_channels[j] =
11426 params->
11427 supported_channels[i];
11428 } else {
11429 continue;
11430 }
11431 wifi_chan_index =
11432 ((StaParams.supported_channels[j] <=
11433 HDD_CHANNEL_14) ? 1 : 4);
11434 no_of_channels =
11435 params->supported_channels[i + 1];
11436
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011437 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 -080011438 StaParams.
11439 supported_channels[j],
11440 wifi_chan_index,
11441 no_of_channels);
11442 for (k = 1; k <= no_of_channels &&
11443 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11444 k++) {
11445 next =
11446 StaParams.
11447 supported_channels[j] +
11448 wifi_chan_index;
11449 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11450 StaParams.
11451 supported_channels[j
11452 +
11453 1]
11454 = next;
11455 } else {
11456 continue;
11457 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011458 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459 j + 1,
11460 StaParams.
11461 supported_channels[j +
11462 1]);
11463 j += 1;
11464 }
11465 }
11466 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011467 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011468 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011469 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 StaParams.
11471 supported_channels[i]);
11472 }
11473 if (MAX_CHANNEL < num_unique_channels)
11474 num_unique_channels = MAX_CHANNEL;
11475 StaParams.supported_channels_len =
11476 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011477 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011478 StaParams.supported_channels_len);
11479 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011480 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011481 params->supported_oper_classes,
11482 params->supported_oper_classes_len);
11483 StaParams.supported_oper_classes_len =
11484 params->supported_oper_classes_len;
11485
11486 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011487 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011488 params->ext_capab,
11489 sizeof(StaParams.extn_capability));
11490
11491 if (NULL != params->ht_capa) {
11492 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011493 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011494 sizeof(tSirHTCap));
11495 }
11496
11497 StaParams.supported_rates_len =
11498 params->supported_rates_len;
11499
11500 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11501 * The supported_rates array , for all the structures propogating till Add Sta
11502 * to the firmware has to be modified , if the supplicant (ieee80211) is
11503 * modified to send more rates.
11504 */
11505
11506 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11507 */
11508 if (StaParams.supported_rates_len >
11509 SIR_MAC_MAX_SUPP_RATES)
11510 StaParams.supported_rates_len =
11511 SIR_MAC_MAX_SUPP_RATES;
11512
11513 if (0 != StaParams.supported_rates_len) {
11514 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011515 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 params->supported_rates,
11517 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011518 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011519 StaParams.supported_rates_len);
11520 for (i = 0; i < StaParams.supported_rates_len;
11521 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011522 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 StaParams.supported_rates[i]);
11524 }
11525
11526 if (NULL != params->vht_capa) {
11527 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011528 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 params->vht_capa,
11530 sizeof(tSirVHTCap));
11531 }
11532
11533 if (0 != params->ext_capab_len) {
11534 /*Define A Macro : TODO Sunil */
11535 if ((1 << 4) & StaParams.extn_capability[3]) {
11536 isBufSta = 1;
11537 }
11538 /* TDLS Channel Switching Support */
11539 if ((1 << 6) & StaParams.extn_capability[3]) {
11540 isOffChannelSupported = 1;
11541 }
11542 }
11543
Nitesh Shah99934ac2016-09-05 15:54:08 +053011544 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011545 (params->ht_capa || params->vht_capa ||
11546 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011547 is_qos_wmm_sta = true;
11548
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011549 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011550 " is_qos_wmm_sta= %d HTcapPresent = %d",
11551 __func__, is_qos_wmm_sta,
11552 StaParams.htcap_present);
11553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011555 &StaParams,
11556 isBufSta,
11557 isOffChannelSupported,
11558 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011559 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011560 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561 return -EINVAL;
11562 }
11563
11564 status =
11565 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11566 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011567 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011568 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569 return -EINVAL;
11570 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011571#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011572 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 }
11574 EXIT();
11575 return ret;
11576}
11577
11578/**
11579 * wlan_hdd_change_station() - cfg80211 change station handler function
11580 * @wiphy: Pointer to the wiphy structure
11581 * @dev: Pointer to the net device.
11582 * @mac: bssid
11583 * @params: Pointer to station parameters
11584 *
11585 * This is the cfg80211 change station handler function which invokes
11586 * the internal function @__wlan_hdd_change_station with
11587 * SSR protection.
11588 *
11589 * Return: 0 for success, error number on failure.
11590 */
11591#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11592static int wlan_hdd_change_station(struct wiphy *wiphy,
11593 struct net_device *dev,
11594 const u8 *mac,
11595 struct station_parameters *params)
11596#else
11597static int wlan_hdd_change_station(struct wiphy *wiphy,
11598 struct net_device *dev,
11599 u8 *mac,
11600 struct station_parameters *params)
11601#endif
11602{
11603 int ret;
11604
11605 cds_ssr_protect(__func__);
11606 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11607 cds_ssr_unprotect(__func__);
11608
11609 return ret;
11610}
11611
11612/*
11613 * FUNCTION: __wlan_hdd_cfg80211_add_key
11614 * This function is used to initialize the key information
11615 */
11616static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11617 struct net_device *ndev,
11618 u8 key_index, bool pairwise,
11619 const u8 *mac_addr,
11620 struct key_params *params)
11621{
11622 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11623 tCsrRoamSetKey setKey;
11624 int status;
11625 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011626 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011627 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 hdd_context_t *pHddCtx;
11629 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11630
11631 ENTER();
11632
Anurag Chouhan6d760662016-02-20 16:05:43 +053011633 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011634 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011635 return -EINVAL;
11636 }
11637
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011638 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011639 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011640 return -EINVAL;
11641 }
11642
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011643 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011644 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11645 pAdapter->sessionId, params->key_len));
11646 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11647 status = wlan_hdd_validate_context(pHddCtx);
11648
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011649 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011651
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011652 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011653 hdd_device_mode_to_string(pAdapter->device_mode),
11654 pAdapter->device_mode);
11655
11656 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011657 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658
11659 return -EINVAL;
11660 }
11661
11662 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011663 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664
11665 return -EINVAL;
11666 }
11667
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011668 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011669
11670 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011671 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011672 setKey.keyId = key_index;
11673 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011674 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011675
11676 switch (params->cipher) {
11677 case WLAN_CIPHER_SUITE_WEP40:
11678 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11679 break;
11680
11681 case WLAN_CIPHER_SUITE_WEP104:
11682 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11683 break;
11684
11685 case WLAN_CIPHER_SUITE_TKIP:
11686 {
11687 u8 *pKey = &setKey.Key[0];
11688 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11689
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011690 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011692 /* Supplicant sends the 32bytes key in this order
11693 *
11694 * |--------------|----------|----------|
11695 * | Tk1 |TX-MIC | RX Mic |
11696 * |--------------|----------|----------|
11697 * <---16bytes---><--8bytes--><--8bytes-->
11698 *
11699 * Sme expects the 32 bytes key to be in the below order
11700 *
11701 * |--------------|----------|----------|
11702 * | Tk1 |RX-MIC | TX Mic |
11703 * |--------------|----------|----------|
11704 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011705 */
11706 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011707 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011708
11709 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011710 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011711
11712 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011713 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714
11715 break;
11716 }
11717
11718 case WLAN_CIPHER_SUITE_CCMP:
11719 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11720 break;
11721
11722#ifdef FEATURE_WLAN_WAPI
11723 case WLAN_CIPHER_SUITE_SMS4:
11724 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011725 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011726 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11727 mac_addr, params->key,
11728 params->key_len);
11729 return 0;
11730 }
11731#endif
11732
11733#ifdef FEATURE_WLAN_ESE
11734 case WLAN_CIPHER_SUITE_KRK:
11735 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11736 break;
11737#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11738 case WLAN_CIPHER_SUITE_BTK:
11739 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11740 break;
11741#endif
11742#endif
11743
11744#ifdef WLAN_FEATURE_11W
11745 case WLAN_CIPHER_SUITE_AES_CMAC:
11746 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11747 break;
11748#endif
11749
11750 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011751 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 return -EOPNOTSUPP;
11753 }
11754
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011755 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756
11757 if (!pairwise) {
11758 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011759 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011761 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011762 } else {
11763 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011764 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011766 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011768 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 /* if a key is already installed, block all subsequent ones */
11770 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011771 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011772 return 0;
11773 }
11774
11775 setKey.keyDirection = eSIR_TX_RX;
11776 /*Set the group key */
11777 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11778 pAdapter->sessionId, &setKey, &roamId);
11779
11780 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011781 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782 return -EINVAL;
11783 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011784 /* Save the keys here and call sme_roam_set_key for setting
11785 * the PTK after peer joins the IBSS network
11786 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011787 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011788 &setKey, sizeof(tCsrRoamSetKey));
11789
11790 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11791 return status;
11792 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011793 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11794 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011795 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11796 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011797 status = wlansap_set_key_sta(
11798 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011799 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011800 hdd_err("wlansap_set_key_sta failed status: %d",
11801 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011802 }
11803 }
11804
11805 /* Save the key in ap ctx for use on START_BASS and restart */
11806 if (pairwise ||
11807 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11808 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011809 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011810 sizeof(tCsrRoamSetKey));
11811 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011812 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011813 sizeof(tCsrRoamSetKey));
11814
Krunal Sonib4326f22016-03-10 13:05:51 -080011815 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11816 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011817 hdd_wext_state_t *pWextState =
11818 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11819 hdd_station_ctx_t *pHddStaCtx =
11820 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11821
11822 if (!pairwise) {
11823 /* set group key */
11824 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011825 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 __func__, __LINE__);
11827 hdd_perform_roam_set_key_complete(pAdapter);
11828 }
11829 }
11830
11831 pWextState->roamProfile.Keys.KeyLength[key_index] =
11832 (u8) params->key_len;
11833
11834 pWextState->roamProfile.Keys.defaultIndex = key_index;
11835
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011836 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 KeyMaterial[key_index][0], params->key,
11838 params->key_len);
11839
11840 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11841
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011842 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11844 setKey.keyDirection);
11845
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011846 /* The supplicant may attempt to set the PTK once
11847 * pre-authentication is done. Save the key in the
11848 * UMAC and include it in the ADD BSS request
11849 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011850 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011851 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011852 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011853 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011854 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011855 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011856 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011857 return -EINVAL;
11858 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859
11860 /* issue set key request to SME */
11861 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11862 pAdapter->sessionId, &setKey, &roamId);
11863
11864 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011865 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011866 pHddStaCtx->roam_info.roamingState =
11867 HDD_ROAM_STATE_NONE;
11868 return -EINVAL;
11869 }
11870
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011871 /* in case of IBSS as there was no information
11872 * available about WEP keys during IBSS join, group
11873 * key intialized with NULL key, so re-initialize
11874 * group key with correct value
11875 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 if ((eCSR_BSS_TYPE_START_IBSS ==
11877 pWextState->roamProfile.BSSType)
11878 &&
11879 !((IW_AUTH_KEY_MGMT_802_1X ==
11880 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11881 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11882 pHddStaCtx->conn_info.authType)
11883 )
11884 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11885 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11886 )
11887 ) {
11888 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011889 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011890
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011891 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011892 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11893 setKey.keyDirection);
11894
11895 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11896 pAdapter->sessionId, &setKey,
11897 &roamId);
11898
11899 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011900 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011901 pHddStaCtx->roam_info.roamingState =
11902 HDD_ROAM_STATE_NONE;
11903 return -EINVAL;
11904 }
11905 }
11906 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011907 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011908 return 0;
11909}
11910
11911static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11912 struct net_device *ndev,
11913 u8 key_index, bool pairwise,
11914 const u8 *mac_addr,
11915 struct key_params *params)
11916{
11917 int ret;
11918 cds_ssr_protect(__func__);
11919 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11920 mac_addr, params);
11921 cds_ssr_unprotect(__func__);
11922
11923 return ret;
11924}
11925
11926/*
11927 * FUNCTION: __wlan_hdd_cfg80211_get_key
11928 * This function is used to get the key information
11929 */
11930static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11931 struct net_device *ndev,
11932 u8 key_index, bool pairwise,
11933 const u8 *mac_addr, void *cookie,
11934 void (*callback)(void *cookie,
11935 struct key_params *)
11936 )
11937{
11938 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11939 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11940 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11941 struct key_params params;
11942
11943 ENTER();
11944
Anurag Chouhan6d760662016-02-20 16:05:43 +053011945 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011946 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 return -EINVAL;
11948 }
11949
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011950 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011951 hdd_device_mode_to_string(pAdapter->device_mode),
11952 pAdapter->device_mode);
11953
11954 memset(&params, 0, sizeof(params));
11955
11956 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011957 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011958 return -EINVAL;
11959 }
11960
11961 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11962 case eCSR_ENCRYPT_TYPE_NONE:
11963 params.cipher = IW_AUTH_CIPHER_NONE;
11964 break;
11965
11966 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11967 case eCSR_ENCRYPT_TYPE_WEP40:
11968 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11969 break;
11970
11971 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11972 case eCSR_ENCRYPT_TYPE_WEP104:
11973 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11974 break;
11975
11976 case eCSR_ENCRYPT_TYPE_TKIP:
11977 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11978 break;
11979
11980 case eCSR_ENCRYPT_TYPE_AES:
11981 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11982 break;
11983
11984 default:
11985 params.cipher = IW_AUTH_CIPHER_NONE;
11986 break;
11987 }
11988
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011989 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011990 TRACE_CODE_HDD_CFG80211_GET_KEY,
11991 pAdapter->sessionId, params.cipher));
11992
11993 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11994 params.seq_len = 0;
11995 params.seq = NULL;
11996 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11997 callback(cookie, &params);
11998
11999 EXIT();
12000 return 0;
12001}
12002
12003static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12004 struct net_device *ndev,
12005 u8 key_index, bool pairwise,
12006 const u8 *mac_addr, void *cookie,
12007 void (*callback)(void *cookie,
12008 struct key_params *)
12009 )
12010{
12011 int ret;
12012
12013 cds_ssr_protect(__func__);
12014 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12015 mac_addr, cookie, callback);
12016 cds_ssr_unprotect(__func__);
12017
12018 return ret;
12019}
12020
12021/**
12022 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12023 * @wiphy: wiphy interface context
12024 * @ndev: pointer to net device
12025 * @key_index: Key index used in 802.11 frames
12026 * @unicast: true if it is unicast key
12027 * @multicast: true if it is multicast key
12028 *
12029 * This function is required for cfg80211_ops API.
12030 * It is used to delete the key information
12031 * Underlying hardware implementation does not have API to delete the
12032 * encryption key. It is automatically deleted when the peer is
12033 * removed. Hence this function currently does nothing.
12034 * Future implementation may interprete delete key operation to
12035 * replacing the key with a random junk value, effectively making it
12036 * useless.
12037 *
12038 * Return: status code, always 0.
12039 */
12040
12041static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12042 struct net_device *ndev,
12043 u8 key_index,
12044 bool pairwise, const u8 *mac_addr)
12045{
12046 EXIT();
12047 return 0;
12048}
12049
12050/**
12051 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12052 * @wiphy: Pointer to wiphy structure.
12053 * @dev: Pointer to net_device structure.
12054 * @key_index: key index
12055 * @pairwise: pairwise
12056 * @mac_addr: mac address
12057 *
12058 * This is the cfg80211 delete key handler function which invokes
12059 * the internal function @__wlan_hdd_cfg80211_del_key with
12060 * SSR protection.
12061 *
12062 * Return: 0 for success, error number on failure.
12063 */
12064static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12065 struct net_device *dev,
12066 u8 key_index,
12067 bool pairwise, const u8 *mac_addr)
12068{
12069 int ret;
12070
12071 cds_ssr_protect(__func__);
12072 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12073 pairwise, mac_addr);
12074 cds_ssr_unprotect(__func__);
12075
12076 return ret;
12077}
12078
12079/*
12080 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12081 * This function is used to set the default tx key index
12082 */
12083static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12084 struct net_device *ndev,
12085 u8 key_index,
12086 bool unicast, bool multicast)
12087{
12088 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12089 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12090 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12091 hdd_context_t *pHddCtx;
12092 int status;
12093
12094 ENTER();
12095
Anurag Chouhan6d760662016-02-20 16:05:43 +053012096 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012097 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 return -EINVAL;
12099 }
12100
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012101 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012102 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012103 return -EINVAL;
12104 }
12105
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012106 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12108 pAdapter->sessionId, key_index));
12109
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012110 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012111 hdd_device_mode_to_string(pAdapter->device_mode),
12112 pAdapter->device_mode, key_index);
12113
12114 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012115 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012116 return -EINVAL;
12117 }
12118
12119 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12120 status = wlan_hdd_validate_context(pHddCtx);
12121
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012122 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012124
Krunal Sonib4326f22016-03-10 13:05:51 -080012125 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12126 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12128 pHddStaCtx->conn_info.ucEncryptionType) &&
12129 (eCSR_ENCRYPT_TYPE_AES !=
12130 pHddStaCtx->conn_info.ucEncryptionType)) {
12131 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012132 * then update the default key index
12133 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012134
12135 tCsrRoamSetKey setKey;
12136 uint32_t roamId = 0xFF;
12137 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12138
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012139 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012140
12141 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012142 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143 setKey.keyId = key_index;
12144 setKey.keyLength = Keys->KeyLength[key_index];
12145
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012146 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012147 &Keys->KeyMaterial[key_index][0],
12148 Keys->KeyLength[key_index]);
12149
12150 setKey.keyDirection = eSIR_TX_RX;
12151
Anurag Chouhanc5548422016-02-24 18:33:27 +053012152 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012153 &pHddStaCtx->conn_info.bssId);
12154
12155 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12156 pWextState->roamProfile.EncryptionType.
12157 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012158 /* In the case of dynamic wep
12159 * supplicant hardcodes DWEP type to
12160 * eCSR_ENCRYPT_TYPE_WEP104 even
12161 * though ap is configured for WEP-40
12162 * encryption. In this canse the key
12163 * length is 5 but the encryption type
12164 * is 104 hence checking the key
12165 * lenght(5) and encryption type(104)
12166 * and switching encryption type to 40
12167 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012168 pWextState->roamProfile.EncryptionType.
12169 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12170 pWextState->roamProfile.mcEncryptionType.
12171 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12172 }
12173
12174 setKey.encType =
12175 pWextState->roamProfile.EncryptionType.
12176 encryptionType[0];
12177
12178 /* Issue set key request */
12179 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12180 pAdapter->sessionId, &setKey,
12181 &roamId);
12182
12183 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012184 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185 status);
12186 return -EINVAL;
12187 }
12188 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012189 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012190 /* In SoftAp mode setting key direction for default mode */
12191 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12192 pWextState->roamProfile.EncryptionType.encryptionType[0])
12193 && (eCSR_ENCRYPT_TYPE_AES !=
12194 pWextState->roamProfile.EncryptionType.
12195 encryptionType[0])) {
12196 /* Saving key direction for default key index to TX default */
12197 hdd_ap_ctx_t *pAPCtx =
12198 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12199 pAPCtx->wepKey[key_index].keyDirection =
12200 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012201 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012202 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012203 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012204 }
12205 }
12206
12207 EXIT();
12208 return status;
12209}
12210
12211static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12212 struct net_device *ndev,
12213 u8 key_index,
12214 bool unicast, bool multicast)
12215{
12216 int ret;
12217 cds_ssr_protect(__func__);
12218 ret =
12219 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12220 multicast);
12221 cds_ssr_unprotect(__func__);
12222
12223 return ret;
12224}
12225
Abhishek Singhc9941602016-08-09 16:06:22 +053012226/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012227 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12228 * interface that BSS might have been lost.
12229 * @pAdapter: adaptor
12230 * @bssid: bssid which might have been lost
12231 *
12232 * Return: bss which is unlinked from kernel cache
12233 */
12234struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12235 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012236{
12237 struct net_device *dev = pAdapter->dev;
12238 struct wireless_dev *wdev = dev->ieee80211_ptr;
12239 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012240 struct cfg80211_bss *bss = NULL;
12241
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012242 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012243 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012244 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012245 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012247 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012248 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 cfg80211_unlink_bss(wiphy, bss);
12250 }
12251 return bss;
12252}
12253
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012254#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12255 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12256static struct cfg80211_bss *
12257wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12258 struct ieee80211_channel *chan,
12259 struct ieee80211_mgmt *mgmt,
12260 size_t frame_len,
12261 int rssi, gfp_t gfp,
12262 uint64_t boottime_ns)
12263{
12264 struct cfg80211_bss *bss_status = NULL;
12265 struct cfg80211_inform_bss data = {0};
12266
12267 data.chan = chan;
12268 data.boottime_ns = boottime_ns;
12269 data.signal = rssi;
12270 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12271 frame_len, gfp);
12272 return bss_status;
12273}
12274#else
12275static struct cfg80211_bss *
12276wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12277 struct ieee80211_channel *chan,
12278 struct ieee80211_mgmt *mgmt,
12279 size_t frame_len,
12280 int rssi, gfp_t gfp,
12281 uint64_t boottime_ns)
12282{
12283 struct cfg80211_bss *bss_status = NULL;
12284
12285 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12286 rssi, gfp);
12287 return bss_status;
12288}
12289#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012290
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012291/**
12292 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12293 * @pAdapter: Pointer to adapter
12294 * @bss_desc: Pointer to bss descriptor
12295 *
12296 * This function is used to inform the BSS details to nl80211 interface.
12297 *
12298 * Return: struct cfg80211_bss pointer
12299 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012300struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12301 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012302{
12303 /*
12304 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12305 * already exists in bss data base of cfg80211 for that particular BSS
12306 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12307 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12308 * As of now there is no possibility to get the mgmt(probe response)
12309 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12310 * and passing to cfg80211_inform_bss_frame.
12311 */
12312 struct net_device *dev = pAdapter->dev;
12313 struct wireless_dev *wdev = dev->ieee80211_ptr;
12314 struct wiphy *wiphy = wdev->wiphy;
12315 int chan_no = bss_desc->channelId;
12316#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12317 qcom_ie_age *qie_age = NULL;
12318 int ie_length =
12319 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12320#else
12321 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12322#endif
12323 const char *ie =
12324 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12325 unsigned int freq;
12326 struct ieee80211_channel *chan;
12327 struct ieee80211_mgmt *mgmt = NULL;
12328 struct cfg80211_bss *bss_status = NULL;
12329 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12330 int rssi = 0;
12331 hdd_context_t *pHddCtx;
12332 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012334 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012335
12336 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12337 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012338 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012341 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012342 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012344 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012345 return NULL;
12346 }
12347
12348 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12349
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012350 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012351 * Instead it wants a monotonic increasing value
12352 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012353 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354 mgmt->u.probe_resp.timestamp =
12355 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356
12357 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12358 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12359
12360#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12361 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12362 /* Assuming this is the last IE, copy at the end */
12363 ie_length -= sizeof(qcom_ie_age);
12364 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12365 qie_age->element_id = QCOM_VENDOR_IE_ID;
12366 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12367 qie_age->oui_1 = QCOM_OUI1;
12368 qie_age->oui_2 = QCOM_OUI2;
12369 qie_age->oui_3 = QCOM_OUI3;
12370 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012371 /*
12372 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12373 * all bss related timestamp is in units of ms. Due to this when scan
12374 * results are sent to lowi the scan age is high.To address this,
12375 * send age in units of 1/10 ms.
12376 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012378 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012380 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12381 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012382 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12383 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384#endif
12385
12386 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12387 if (bss_desc->fProbeRsp) {
12388 mgmt->frame_control |=
12389 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12390 } else {
12391 mgmt->frame_control |=
12392 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12393 }
12394
12395 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012396 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012397 freq =
12398 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012399 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012401 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012402 freq =
12403 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012404 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012405 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012406 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012407 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 return NULL;
12409 }
12410
12411 chan = __ieee80211_get_channel(wiphy, freq);
12412 /* When the band is changed on the fly using the GUI, three things are done
12413 * 1. scan abort
12414 * 2. flush scan results from cache
12415 * 3. update the band with the new band user specified (refer to the
12416 * hdd_set_band_helper function) as part of the scan abort, message will be
12417 * queued to PE and we proceed with flushing and changinh the band.
12418 * PE will stop the scanning further and report back the results what ever
12419 * it had till now by calling the call back function.
12420 * if the time between update band and scandone call back is sufficient
12421 * enough the band change reflects in SME, SME validates the channels
12422 * and discards the channels correponding to previous band and calls back
12423 * with zero bss results. but if the time between band update and scan done
12424 * callback is very small then band change will not reflect in SME and SME
12425 * reports to HDD all the channels correponding to previous band.this is due
12426 * to race condition.but those channels are invalid to the new band and so
12427 * this function __ieee80211_get_channel will return NULL.Each time we
12428 * report scan result with this pointer null warning kernel trace is printed.
12429 * if the scan results contain large number of APs continuosly kernel
12430 * warning trace is printed and it will lead to apps watch dog bark.
12431 * So drop the bss and continue to next bss.
12432 */
12433 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012434 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12435 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012436 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012437 return NULL;
12438 }
12439
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012440 /* Based on .ini configuration, raw rssi can be reported for bss.
12441 * Raw rssi is typically used for estimating power.
12442 */
12443
12444 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12445 bss_desc->rssi;
12446
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012447 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012448 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012449
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012450 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012451 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012452 (int)(rssi / 100),
12453 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012454
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012455 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12456 frame_len, rssi,
12457 GFP_KERNEL,
12458 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012459 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012460 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012461 return bss_status;
12462}
12463
12464/**
12465 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12466 * @pAdapter: Pointer to adapter
12467 * @pRoamInfo: Pointer to roam info
12468 *
12469 * This function is used to update the BSS data base of CFG8011
12470 *
12471 * Return: struct cfg80211_bss pointer
12472 */
12473struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12474 tCsrRoamInfo *pRoamInfo)
12475{
12476 tCsrRoamConnectedProfile roamProfile;
12477 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12478 struct cfg80211_bss *bss = NULL;
12479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12481 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12482
12483 if (NULL != roamProfile.pBssDesc) {
12484 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12485 roamProfile.pBssDesc);
12486
12487 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012488 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012489
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012490 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012491 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012492 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012493 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012494 return bss;
12495}
12496/**
12497 * wlan_hdd_cfg80211_update_bss() - update bss
12498 * @wiphy: Pointer to wiphy
12499 * @pAdapter: Pointer to adapter
12500 * @scan_time: scan request timestamp
12501 *
12502 * Return: zero if success, non-zero otherwise
12503 */
12504int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12505 hdd_adapter_t *pAdapter,
12506 uint32_t scan_time)
12507{
12508 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12509 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012510 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511 tScanResultHandle pResult;
12512 struct cfg80211_bss *bss_status = NULL;
12513 hdd_context_t *pHddCtx;
12514 int ret;
12515
12516 ENTER();
12517
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012518 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12519 hdd_err("invalid session id: %d", pAdapter->sessionId);
12520 return -EINVAL;
12521 }
12522
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012523 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12525 NO_SESSION, pAdapter->sessionId));
12526
12527 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12528 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012529 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012531
12532 /* start getting scan results and populate cgf80211 BSS database */
12533 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12534
12535 /* no scan results */
12536 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012537 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012538 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012539 }
12540
12541 pScanResult = sme_scan_result_get_first(hHal, pResult);
12542
12543 while (pScanResult) {
12544 /*
12545 * - cfg80211_inform_bss() is not updating ie field of bss
12546 * entry if entry already exists in bss data base of cfg80211
12547 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12548 * to update thebss entry instead of cfg80211_inform_bss,
12549 * But this call expects mgmt packet as input. As of now
12550 * there is no possibility to get the mgmt(probe response)
12551 * frame from PE, converting bss_desc to
12552 * ieee80211_mgmt(probe response) and passing to c
12553 * fg80211_inform_bss_frame.
12554 * - Update BSS only if beacon timestamp is later than
12555 * scan request timestamp.
12556 */
12557 if ((scan_time == 0) ||
12558 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012559 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012560 bss_status =
12561 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12562 &pScanResult->BssDescriptor);
12563
12564 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012565 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012566 } else {
12567 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012568 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012569 bss_status);
12570 }
12571 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012572 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012573 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12574 }
12575 pScanResult = sme_scan_result_get_next(hHal, pResult);
12576 }
12577
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012578 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579 /*
12580 * For SAP mode, scan is invoked by hostapd during SAP start
12581 * if hostapd is restarted, we need to flush previous scan
12582 * result so that it will reflect environment change
12583 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012584 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012585#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12586 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12587#endif
12588 )
12589 sme_scan_flush_result(hHal);
12590
12591 EXIT();
12592 return 0;
12593}
12594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012595/**
12596 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12597 * @pAdapter: Pointer to adapter
12598 * @pRoamInfo: Pointer to roam info
12599 * @index: Index
12600 * @preauth: Preauth flag
12601 *
12602 * This function is used to notify the supplicant of a new PMKSA candidate.
12603 *
12604 * Return: 0 for success, non-zero for failure
12605 */
12606int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12607 tCsrRoamInfo *pRoamInfo,
12608 int index, bool preauth)
12609{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610 struct net_device *dev = pAdapter->dev;
12611 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12612
12613 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012614 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012615
12616 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012617 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 return -EINVAL;
12619 }
12620
12621 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012622 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12624 cfg80211_pmksa_candidate_notify(dev, index,
12625 pRoamInfo->bssid.bytes,
12626 preauth, GFP_KERNEL);
12627 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012628 return 0;
12629}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012630
12631#ifdef FEATURE_WLAN_LFR_METRICS
12632/**
12633 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12634 * @pAdapter: Pointer to adapter
12635 * @pRoamInfo: Pointer to roam info
12636 *
12637 * 802.11r/LFR metrics reporting function to report preauth initiation
12638 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012639 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012640 */
12641#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012642QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012643 tCsrRoamInfo *pRoamInfo)
12644{
12645 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12646 union iwreq_data wrqu;
12647
12648 ENTER();
12649
12650 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012651 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012652 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012653 }
12654
12655 /* create the event */
12656 memset(&wrqu, 0, sizeof(wrqu));
12657 memset(metrics_notification, 0, sizeof(metrics_notification));
12658
12659 wrqu.data.pointer = metrics_notification;
12660 wrqu.data.length = scnprintf(metrics_notification,
12661 sizeof(metrics_notification),
12662 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12663 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12664
12665 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12666 metrics_notification);
12667
12668 EXIT();
12669
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012670 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671}
12672
12673/**
12674 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12675 * @pAdapter: Pointer to adapter
12676 * @pRoamInfo: Pointer to roam info
12677 * @preauth_status: Preauth status
12678 *
12679 * 802.11r/LFR metrics reporting function to report handover initiation
12680 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012681 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012683QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012684wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12685 tCsrRoamInfo *pRoamInfo,
12686 bool preauth_status)
12687{
12688 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12689 union iwreq_data wrqu;
12690
12691 ENTER();
12692
12693 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012694 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012695 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012696 }
12697
12698 /* create the event */
12699 memset(&wrqu, 0, sizeof(wrqu));
12700 memset(metrics_notification, 0, sizeof(metrics_notification));
12701
12702 scnprintf(metrics_notification, sizeof(metrics_notification),
12703 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12704 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12705
12706 if (1 == preauth_status)
12707 strlcat(metrics_notification, " true",
12708 sizeof(metrics_notification));
12709 else
12710 strlcat(metrics_notification, " false",
12711 sizeof(metrics_notification));
12712
12713 wrqu.data.pointer = metrics_notification;
12714 wrqu.data.length = strlen(metrics_notification);
12715
12716 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12717 metrics_notification);
12718
12719 EXIT();
12720
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012721 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012722}
12723
12724/**
12725 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12726 * @pAdapter: Pointer to adapter
12727 * @pRoamInfo: Pointer to roam info
12728 *
12729 * 802.11r/LFR metrics reporting function to report handover initiation
12730 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012731 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012732 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012733QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012734 tCsrRoamInfo *pRoamInfo)
12735{
12736 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12737 union iwreq_data wrqu;
12738
12739 ENTER();
12740
12741 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012742 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012743 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012744 }
12745
12746 /* create the event */
12747 memset(&wrqu, 0, sizeof(wrqu));
12748 memset(metrics_notification, 0, sizeof(metrics_notification));
12749
12750 wrqu.data.pointer = metrics_notification;
12751 wrqu.data.length = scnprintf(metrics_notification,
12752 sizeof(metrics_notification),
12753 "QCOM: LFR_PREAUTH_HANDOVER "
12754 MAC_ADDRESS_STR,
12755 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12756
12757 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12758 metrics_notification);
12759
12760 EXIT();
12761
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012762 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012763}
12764#endif
12765
12766/**
12767 * hdd_select_cbmode() - select channel bonding mode
12768 * @pAdapter: Pointer to adapter
12769 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012770 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012771 *
12772 * Return: none
12773 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012774void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012775 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012776{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012777 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012778 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012779 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012780 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012781
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012782 /*
12783 * CDS api expects secondary channel for calculating
12784 * the channel params
12785 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012786 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012787 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012788 if (operationChannel >= 1 && operationChannel <= 5)
12789 sec_ch = operationChannel + 4;
12790 else if (operationChannel >= 6 && operationChannel <= 13)
12791 sec_ch = operationChannel - 4;
12792 }
12793
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012794 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012795 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
12796 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012797
12798 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012799 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012800 uint8_t iniDot11Mode =
12801 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12802
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012803 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012804 switch (iniDot11Mode) {
12805 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012806 case eHDD_DOT11_MODE_11ax:
12807 case eHDD_DOT11_MODE_11ax_ONLY:
12808 if (sme_is_feature_supported_by_fw(DOT11AX))
12809 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12810 else if (sme_is_feature_supported_by_fw(DOT11AC))
12811 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12812 else
12813 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12814 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012815 case eHDD_DOT11_MODE_11ac:
12816 case eHDD_DOT11_MODE_11ac_ONLY:
12817 if (sme_is_feature_supported_by_fw(DOT11AC))
12818 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12819 else
12820 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12821 break;
12822 case eHDD_DOT11_MODE_11n:
12823 case eHDD_DOT11_MODE_11n_ONLY:
12824 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12825 break;
12826 default:
12827 hdd_dot11_mode = iniDot11Mode;
12828 break;
12829 }
12830 ch_info->channel_width = ch_params->ch_width;
12831 ch_info->phy_mode =
12832 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012833 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012834 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012835 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012836 ch_info->channel_width, ch_info->phy_mode,
12837 ch_info->channel);
12838 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839}
12840
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012841/**
12842 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12843 * @adapter: STA adapter
12844 * @roam_profile: STA roam profile
12845 *
12846 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12847 *
12848 * Return: false if sta-sap conc is not allowed, else return true
12849 */
12850static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12851 tCsrRoamProfile *roam_profile)
12852{
12853 hdd_context_t *hdd_ctx;
12854 hdd_adapter_t *ap_adapter;
12855 hdd_ap_ctx_t *hdd_ap_ctx;
12856 hdd_hostapd_state_t *hostapd_state;
12857 uint8_t channel = 0;
12858 QDF_STATUS status;
12859
12860 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12861 if (!hdd_ctx) {
12862 hdd_err("HDD context is NULL");
12863 return true;
12864 }
12865
12866 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12867 /* probably no sap running, no handling required */
12868 if (ap_adapter == NULL)
12869 return true;
12870
12871 /*
12872 * sap is not in started state, so it is fine to go ahead with sta.
12873 * if sap is currently doing CAC then don't allow sta to go further.
12874 */
12875 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12876 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12877 return true;
12878
12879 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12880 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12881 return false;
12882 }
12883
12884 /*
12885 * log and return error, if we allow STA to go through, we don't
12886 * know what is going to happen better stop sta connection
12887 */
12888 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12889 if (NULL == hdd_ap_ctx) {
12890 hdd_err("AP context not found");
12891 return false;
12892 }
12893
12894 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012895 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
12896 hdd_ap_ctx->operatingChannel)) {
12897 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012898 return true;
12899 }
12900 /*
12901 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012902 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012903 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012904 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012905 roam_profile, &channel);
12906
Nitesh Shah59774522016-09-16 15:14:21 +053012907 /*
12908 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12909 * channels for roaming case.
12910 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012911 if (WLAN_REG_IS_24GHZ_CH(channel)) {
12912 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012913 return true;
12914 }
12915
12916 /*
12917 * If channel is 0 or DFS then better to call pcl and find out the
12918 * best channel. If channel is non-dfs 5 GHz then better move SAP
12919 * to STA's channel to make scc, so we have room for 3port MCC
12920 * scenario.
12921 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012922 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012923 channel = policy_mgr_get_nondfs_preferred_channel(
12924 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012925
12926 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12927 qdf_event_reset(&hostapd_state->qdf_event);
12928 status = wlansap_set_channel_change_with_csa(
12929 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12930 hdd_ap_ctx->sapConfig.ch_width_orig);
12931
12932 if (QDF_STATUS_SUCCESS != status) {
12933 hdd_err("Set channel with CSA IE failed, can't allow STA");
12934 return false;
12935 }
12936
12937 /*
12938 * wait here for SAP to finish the channel switch. When channel
12939 * switch happens, SAP sends few beacons with CSA_IE. After
12940 * successfully Transmission of those beacons, it will move its
12941 * state from started to disconnected and move to new channel.
12942 * once it moves to new channel, sap again moves its state
12943 * machine from disconnected to started and set this event.
12944 * wait for 10 secs to finish this.
12945 */
12946 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12947 if (!QDF_IS_STATUS_SUCCESS(status)) {
12948 hdd_err("wait for qdf_event failed, STA not allowed!!");
12949 return false;
12950 }
12951
12952 return true;
12953}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012954
Abhishek Singhcfb44482017-03-10 12:42:37 +053012955#ifdef WLAN_FEATURE_11W
12956/**
12957 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12958 * @roam_profile: pointer to roam profile
12959 *
12960 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12961 * or pmf=2 is an explicit configuration in the supplicant
12962 * configuration, drop the connection request.
12963 *
12964 * Return: 0 if check result is valid, otherwise return error code
12965 */
12966static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12967{
12968 if (roam_profile->MFPEnabled &&
12969 !(roam_profile->MFPRequired ||
12970 roam_profile->MFPCapable)) {
12971 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12972 roam_profile->MFPEnabled,
12973 roam_profile->MFPRequired,
12974 roam_profile->MFPCapable);
12975 return -EINVAL;
12976 }
12977 return 0;
12978}
12979#else
12980static inline
12981int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12982{
12983 return 0;
12984}
12985#endif
12986
Krunal Soni31949422016-07-29 17:17:53 -070012987/**
12988 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012989 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012990 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 * @ssid_len: Length of ssid
12992 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012993 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012994 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012995 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012996 *
12997 * This function is used to start the association process
12998 *
12999 * Return: 0 for success, non-zero for failure
13000 */
Krunal Soni31949422016-07-29 17:17:53 -070013001static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013002 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013003 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013004 u8 operatingChannel,
13005 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013006{
13007 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013008 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013009 hdd_wext_state_t *pWextState;
13010 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013011 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013012 uint32_t roamId;
13013 tCsrRoamProfile *pRoamProfile;
13014 eCsrAuthType RSNAuthType;
13015 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013016 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013017
13018 ENTER();
13019
13020 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13021 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013022 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023
13024 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013025 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013026 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027
13028 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013029 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013030 status = -EINVAL;
13031 goto ret_status;
13032 }
13033
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013034 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013035 hdd_err("Connection refused: conn in progress");
13036 status = -EINVAL;
13037 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013038 }
13039
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013040 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013041 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13042
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013043 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013044 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13045 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013046
13047 if (pRoamProfile) {
13048 hdd_station_ctx_t *pHddStaCtx;
13049 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13050
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013051 /* Restart the opportunistic timer
13052 *
13053 * If hw_mode_change_in_progress is true, then wait
13054 * till firmware sends the callback for hw_mode change.
13055 *
13056 * Else set connect_in_progress as true and proceed.
13057 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013058 policy_mgr_restart_opportunistic_timer(
13059 pHddCtx->hdd_psoc, false);
13060 if (policy_mgr_is_hw_mode_change_in_progress(
13061 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013062 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013063 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013064 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013065 hdd_err("qdf wait for event failed!!");
13066 status = -EINVAL;
13067 goto ret_status;
13068 }
13069 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013070 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013071
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013072 if (HDD_WMM_USER_MODE_NO_QOS ==
13073 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13074 /*QoS not enabled in cfg file */
13075 pRoamProfile->uapsd_mask = 0;
13076 } else {
13077 /*QoS enabled, update uapsd mask from cfg file */
13078 pRoamProfile->uapsd_mask =
13079 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13080 }
13081
13082 pRoamProfile->SSIDs.numOfSSIDs = 1;
13083 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013084 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013086 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087 ssid, ssid_len);
13088
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013089 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013090 /* cleanup bssid hint */
13091 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13092 QDF_MAC_ADDR_SIZE);
13093 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13094 QDF_MAC_ADDR_SIZE);
13095
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 if (bssid) {
13097 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013098 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013099 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013100 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013101 /*
13102 * Save BSSID in seperate variable as
13103 * pRoamProfile's BSSID is getting zeroed out in the
13104 * association process. In case of join failure
13105 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013107 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013108 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013109 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013110 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013111 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13112 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013113 /*
13114 * Save BSSID in a separate variable as
13115 * pRoamProfile's BSSID is getting zeroed out in the
13116 * association process. In case of join failure
13117 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013119 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013120 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013121 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013122 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 }
13124
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013125 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 pRoamProfile->SSIDs.SSIDList->SSID.length,
13127 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13128 operatingChannel);
13129
13130 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13131 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013132 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013133 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13134 }
13135#ifdef FEATURE_WLAN_WAPI
13136 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013137 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138 switch (pAdapter->wapi_info.wapiAuthMode) {
13139 case WAPI_AUTH_MODE_PSK:
13140 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013141 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013142 pAdapter->wapi_info.wapiAuthMode);
13143 pRoamProfile->AuthType.authType[0] =
13144 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13145 break;
13146 }
13147 case WAPI_AUTH_MODE_CERT:
13148 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013149 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013150 pAdapter->wapi_info.wapiAuthMode);
13151 pRoamProfile->AuthType.authType[0] =
13152 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13153 break;
13154 }
13155 } /* End of switch */
13156 if (pAdapter->wapi_info.wapiAuthMode ==
13157 WAPI_AUTH_MODE_PSK
13158 || pAdapter->wapi_info.wapiAuthMode ==
13159 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013160 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 pRoamProfile->AuthType.numEntries = 1;
13162 pRoamProfile->EncryptionType.numEntries = 1;
13163 pRoamProfile->EncryptionType.encryptionType[0] =
13164 eCSR_ENCRYPT_TYPE_WPI;
13165 pRoamProfile->mcEncryptionType.numEntries = 1;
13166 pRoamProfile->mcEncryptionType.
13167 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13168 }
13169 }
Krunal Soni31949422016-07-29 17:17:53 -070013170#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013171 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013172 pRoamProfile->csrPersona = pAdapter->device_mode;
13173
13174 if (operatingChannel) {
13175 pRoamProfile->ChannelInfo.ChannelList =
13176 &operatingChannel;
13177 pRoamProfile->ChannelInfo.numOfChannels = 1;
13178 } else {
13179 pRoamProfile->ChannelInfo.ChannelList = NULL;
13180 pRoamProfile->ChannelInfo.numOfChannels = 0;
13181 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013182 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183 && operatingChannel) {
13184 /*
13185 * Need to post the IBSS power save parameters
13186 * to WMA. WMA will configure this parameters
13187 * to firmware if power save is enabled by the
13188 * firmware.
13189 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013190 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013191
Abhishek Singh471652b2017-04-14 12:28:32 +053013192 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013193 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013194 status = -EINVAL;
13195 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013196 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013197 pRoamProfile->ch_params.ch_width =
13198 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013199 /*
13200 * In IBSS mode while operating in 2.4 GHz,
13201 * the device supports only 20 MHz.
13202 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013203 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013204 pRoamProfile->ch_params.ch_width =
13205 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013206 hdd_select_cbmode(pAdapter, operatingChannel,
13207 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013208 }
13209
Abhishek Singhcfb44482017-03-10 12:42:37 +053013210 if (wlan_hdd_cfg80211_check_pmf_valid(
13211 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013212 status = -EINVAL;
13213 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013214 }
13215
Krunal Soni31949422016-07-29 17:17:53 -070013216 /*
13217 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013218 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013219 * enhancements, the supplicant is not issuing the scan command
13220 * now. So the unicast frames which are sent from the host are
13221 * not having the additional IEs. If it is P2P CLIENT and there
13222 * is no additional IE present in roamProfile, then use the
13223 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013224 */
13225
Krunal Sonib4326f22016-03-10 13:05:51 -080013226 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013227 (!pRoamProfile->pAddIEScan)) {
13228 pRoamProfile->pAddIEScan =
13229 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13230 pRoamProfile->nAddIEScanLength =
13231 pAdapter->scan_info.scanAddIE.length;
13232 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013234 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13235 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013236 pRoamProfile))) {
13237 hdd_err("sap-sta conc will fail, can't allow sta");
13238 hdd_conn_set_connection_state(pAdapter,
13239 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013240 status = -ENOMEM;
13241 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013242 }
13243
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013244 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245 if (!sme_config) {
13246 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013247 hdd_conn_set_connection_state(pAdapter,
13248 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013249 status = -ENOMEM;
13250 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013251 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013252 sme_get_config_param(pHddCtx->hHal, sme_config);
13253 /* These values are not sessionized. So, any change in these SME
13254 * configs on an older or parallel interface will affect the
13255 * cb mode. So, restoring the default INI params before starting
13256 * interfaces such as sta, cli etc.,
13257 */
13258 sme_config->csrConfig.channelBondingMode5GHz =
13259 pHddCtx->config->nChannelBondingMode5GHz;
13260 sme_config->csrConfig.channelBondingMode24GHz =
13261 pHddCtx->config->nChannelBondingMode24GHz;
13262 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013263 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013264 /*
13265 * Change conn_state to connecting before sme_roam_connect(),
13266 * because sme_roam_connect() has a direct path to call
13267 * hdd_sme_roam_callback(), which will change the conn_state
13268 * If direct path, conn_state will be accordingly changed to
13269 * NotConnected or Associated by either
13270 * hdd_association_completion_handler() or
13271 * hdd_dis_connect_handler() in sme_RoamCallback()if
13272 * sme_RomConnect is to be queued,
13273 * Connecting state will remain until it is completed.
13274 *
13275 * If connection state is not changed, connection state will
13276 * remain in eConnectionState_NotConnected state.
13277 * In hdd_association_completion_handler, "hddDisconInProgress"
13278 * is set to true if conn state is
13279 * eConnectionState_NotConnected.
13280 * If "hddDisconInProgress" is set to true then cfg80211 layer
13281 * is not informed of connect result indication which
13282 * is an issue.
13283 */
13284 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013285 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013286 hdd_conn_set_connection_state(pAdapter,
13287 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013288
Komal Seelama89be8d2016-09-29 11:09:26 +053013289 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13290 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013291 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 pAdapter->sessionId, pRoamProfile,
13293 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013294 if (QDF_IS_STATUS_ERROR(qdf_status))
13295 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296
Rajeev Kumard31e1542017-01-13 14:37:42 -080013297 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013298 (QDF_STA_MODE == pAdapter->device_mode ||
13299 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013300 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013301 "qdf_status %d. -> NotConnected",
13302 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013303 /* change back to NotAssociated */
13304 hdd_conn_set_connection_state(pAdapter,
13305 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013306 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13307 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013308 }
13309
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013310 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013311 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013313 pRoamProfile->ChannelInfo.ChannelList = NULL;
13314 pRoamProfile->ChannelInfo.numOfChannels = 0;
13315
Nitesh Shah044fd672016-10-13 18:53:25 +053013316 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013317 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13318 && !policy_mgr_is_hw_dbs_2x2_capable(
13319 pHddCtx->hdd_psoc)) {
13320 policy_mgr_get_channel_from_scan_result(
13321 pHddCtx->hdd_psoc,
13322 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013323 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013324 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013325 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13326 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013327 }
13328
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013329 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013330 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013331 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013333 goto ret_status;
13334
13335conn_failure:
13336 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013337 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013338
13339ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340 EXIT();
13341 return status;
13342}
13343
13344/**
13345 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13346 * @pAdapter: Pointer to adapter
13347 * @auth_type: Auth type
13348 *
13349 * This function is used to set the authentication type (OPEN/SHARED).
13350 *
13351 * Return: 0 for success, non-zero for failure
13352 */
13353static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13354 enum nl80211_auth_type auth_type)
13355{
13356 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13357 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13358
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013359 /*set authentication type */
13360 switch (auth_type) {
13361 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013362 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013363 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13364 break;
13365
13366 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013367 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013368 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013369 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13370 break;
13371
13372 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013373 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013374 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13375 break;
13376#ifdef FEATURE_WLAN_ESE
13377 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013378 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13380 break;
13381#endif
13382
13383 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013384 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013385 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13386 return -EINVAL;
13387 }
13388
13389 pWextState->roamProfile.AuthType.authType[0] =
13390 pHddStaCtx->conn_info.authType;
13391 return 0;
13392}
13393
13394/**
13395 * wlan_hdd_set_akm_suite() - set key management type
13396 * @pAdapter: Pointer to adapter
13397 * @key_mgmt: Key management type
13398 *
13399 * This function is used to set the key mgmt type(PSK/8021x).
13400 *
13401 * Return: 0 for success, non-zero for failure
13402 */
13403static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13404{
13405 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13406
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013407#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013408#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013409#endif
13410#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013412#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413 /*set key mgmt type */
13414 switch (key_mgmt) {
13415 case WLAN_AKM_SUITE_PSK:
13416 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013418 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013419 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13420 break;
13421
13422 case WLAN_AKM_SUITE_8021X_SHA256:
13423 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013425 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013426 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13427 break;
13428#ifdef FEATURE_WLAN_ESE
13429#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13430#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13431 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013432 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013433 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13434 break;
13435#endif
13436#ifndef WLAN_AKM_SUITE_OSEN
13437#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13438#endif
13439 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013440 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13442 break;
13443
13444 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013445 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013446 return -EINVAL;
13447
13448 }
13449 return 0;
13450}
13451
13452/**
13453 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13454 * @pAdapter: Pointer to adapter
13455 * @cipher: Cipher type
13456 * @ucast: Unicast flag
13457 *
13458 * This function is used to set the encryption type
13459 * (NONE/WEP40/WEP104/TKIP/CCMP).
13460 *
13461 * Return: 0 for success, non-zero for failure
13462 */
13463static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13464 u32 cipher, bool ucast)
13465{
13466 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13467 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13468 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13469
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013470 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013471 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013472 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13473 } else {
13474
13475 /*set encryption method */
13476 switch (cipher) {
13477 case IW_AUTH_CIPHER_NONE:
13478 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13479 break;
13480
13481 case WLAN_CIPHER_SUITE_WEP40:
13482 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13483 break;
13484
13485 case WLAN_CIPHER_SUITE_WEP104:
13486 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13487 break;
13488
13489 case WLAN_CIPHER_SUITE_TKIP:
13490 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13491 break;
13492
13493 case WLAN_CIPHER_SUITE_CCMP:
13494 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13495 break;
13496#ifdef FEATURE_WLAN_WAPI
13497 case WLAN_CIPHER_SUITE_SMS4:
13498 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13499 break;
13500#endif
13501
13502#ifdef FEATURE_WLAN_ESE
13503 case WLAN_CIPHER_SUITE_KRK:
13504 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13505 break;
13506#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13507 case WLAN_CIPHER_SUITE_BTK:
13508 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13509 break;
13510#endif
13511#endif
13512 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013513 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013514 return -EOPNOTSUPP;
13515 }
13516 }
13517
13518 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013519 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13521 pWextState->roamProfile.EncryptionType.numEntries = 1;
13522 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13523 encryptionType;
13524 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013525 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13527 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13528 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13529 encryptionType;
13530 }
13531
13532 return 0;
13533}
13534
13535/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013536 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13537 * @wext_state: Pointer to wext state
13538 * @gen_ie: Pointer to IE data
13539 * @len: length of IE data
13540 *
13541 * Return: 0 for success, non-zero for failure
13542 */
13543static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13544 const uint8_t *gen_ie, uint16_t len)
13545{
13546 uint16_t cur_add_ie_len =
13547 wext_state->assocAddIE.length;
13548
13549 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13550 (wext_state->assocAddIE.length + len)) {
13551 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13552 QDF_ASSERT(0);
13553 return -ENOMEM;
13554 }
13555 memcpy(wext_state->assocAddIE.addIEdata +
13556 cur_add_ie_len, gen_ie, len);
13557 wext_state->assocAddIE.length += len;
13558
13559 wext_state->roamProfile.pAddIEAssoc =
13560 wext_state->assocAddIE.addIEdata;
13561 wext_state->roamProfile.nAddIEAssocLength =
13562 wext_state->assocAddIE.length;
13563 return 0;
13564}
13565
13566/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013567 * wlan_hdd_cfg80211_set_ie() - set IEs
13568 * @pAdapter: Pointer to adapter
13569 * @ie: Pointer ot ie
13570 * @ie: IE length
13571 *
13572 * Return: 0 for success, non-zero for failure
13573 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013574static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013575 size_t ie_len)
13576{
13577 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13578 const uint8_t *genie = ie;
13579 uint16_t remLen = ie_len;
13580#ifdef FEATURE_WLAN_WAPI
13581 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13582 u16 *tmp;
13583 uint16_t akmsuiteCount;
13584 int *akmlist;
13585#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013586 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587
13588 /* clear previous assocAddIE */
13589 pWextState->assocAddIE.length = 0;
13590 pWextState->roamProfile.bWPSAssociation = false;
13591 pWextState->roamProfile.bOSENAssociation = false;
13592
13593 while (remLen >= 2) {
13594 uint16_t eLen = 0;
13595 uint8_t elementId;
13596 elementId = *genie++;
13597 eLen = *genie++;
13598 remLen -= 2;
13599
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013600 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601
13602 switch (elementId) {
13603 case DOT11F_EID_WPA:
13604 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 -070013605 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 return -EINVAL;
13607 } else if (0 ==
13608 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13609 uint16_t curAddIELen =
13610 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013611 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612
13613 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13614 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013615 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013616 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 return -ENOMEM;
13618 }
13619 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13620 memcpy(pWextState->assocAddIE.addIEdata +
13621 curAddIELen, genie - 2, eLen + 2);
13622 pWextState->assocAddIE.length += eLen + 2;
13623
13624 pWextState->roamProfile.bWPSAssociation = true;
13625 pWextState->roamProfile.pAddIEAssoc =
13626 pWextState->assocAddIE.addIEdata;
13627 pWextState->roamProfile.nAddIEAssocLength =
13628 pWextState->assocAddIE.length;
13629 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013630 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013631 memset(pWextState->WPARSNIE, 0,
13632 MAX_WPA_RSN_IE_LEN);
13633 memcpy(pWextState->WPARSNIE, genie - 2,
13634 (eLen + 2));
13635 pWextState->roamProfile.pWPAReqIE =
13636 pWextState->WPARSNIE;
13637 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13638 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13639 P2P_OUI_TYPE_SIZE))) {
13640 uint16_t curAddIELen =
13641 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013642 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643
13644 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13645 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013646 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013647 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013648 return -ENOMEM;
13649 }
13650 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13651 memcpy(pWextState->assocAddIE.addIEdata +
13652 curAddIELen, genie - 2, eLen + 2);
13653 pWextState->assocAddIE.length += eLen + 2;
13654
13655 pWextState->roamProfile.pAddIEAssoc =
13656 pWextState->assocAddIE.addIEdata;
13657 pWextState->roamProfile.nAddIEAssocLength =
13658 pWextState->assocAddIE.length;
13659 }
13660#ifdef WLAN_FEATURE_WFD
13661 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13662 WFD_OUI_TYPE_SIZE)) &&
13663 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013664 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 pAdapter->device_mode)) {
13666 uint16_t curAddIELen =
13667 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013668 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013669
13670 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13671 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013672 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013673 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013674 return -ENOMEM;
13675 }
13676 /* WFD IE is saved to Additional IE ; it should
13677 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013678 * WFD IE
13679 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013680 memcpy(pWextState->assocAddIE.addIEdata +
13681 curAddIELen, genie - 2, eLen + 2);
13682 pWextState->assocAddIE.length += eLen + 2;
13683
13684 pWextState->roamProfile.pAddIEAssoc =
13685 pWextState->assocAddIE.addIEdata;
13686 pWextState->roamProfile.nAddIEAssocLength =
13687 pWextState->assocAddIE.length;
13688 }
13689#endif
13690 /* Appending HS 2.0 Indication Element in Assiciation Request */
13691 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13692 HS20_OUI_TYPE_SIZE))) {
13693 uint16_t curAddIELen =
13694 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013695 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013696
13697 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13698 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013699 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013700 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013701 return -ENOMEM;
13702 }
13703 memcpy(pWextState->assocAddIE.addIEdata +
13704 curAddIELen, genie - 2, eLen + 2);
13705 pWextState->assocAddIE.length += eLen + 2;
13706
13707 pWextState->roamProfile.pAddIEAssoc =
13708 pWextState->assocAddIE.addIEdata;
13709 pWextState->roamProfile.nAddIEAssocLength =
13710 pWextState->assocAddIE.length;
13711 }
13712 /* Appending OSEN Information Element in Assiciation Request */
13713 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13714 OSEN_OUI_TYPE_SIZE))) {
13715 uint16_t curAddIELen =
13716 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013717 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013718
13719 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13720 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013721 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013722 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 return -ENOMEM;
13724 }
13725 memcpy(pWextState->assocAddIE.addIEdata +
13726 curAddIELen, genie - 2, eLen + 2);
13727 pWextState->assocAddIE.length += eLen + 2;
13728
13729 pWextState->roamProfile.bOSENAssociation = true;
13730 pWextState->roamProfile.pAddIEAssoc =
13731 pWextState->assocAddIE.addIEdata;
13732 pWextState->roamProfile.nAddIEAssocLength =
13733 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013734 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13735 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013736 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013737 status = wlan_hdd_add_assoc_ie(pWextState,
13738 genie - 2, eLen + 2);
13739 if (status)
13740 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013741 } else {
13742 uint16_t add_ie_len =
13743 pWextState->assocAddIE.length;
13744
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013745 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013746
13747 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13748 (pWextState->assocAddIE.length + eLen)) {
13749 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013750 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013751 return -ENOMEM;
13752 }
13753
13754 memcpy(pWextState->assocAddIE.addIEdata +
13755 add_ie_len, genie - 2, eLen + 2);
13756 pWextState->assocAddIE.length += eLen + 2;
13757
13758 pWextState->roamProfile.pAddIEAssoc =
13759 pWextState->assocAddIE.addIEdata;
13760 pWextState->roamProfile.nAddIEAssocLength =
13761 pWextState->assocAddIE.length;
13762 }
13763 break;
13764 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013765 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013766 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13767 memcpy(pWextState->WPARSNIE, genie - 2,
13768 (eLen + 2));
13769 pWextState->roamProfile.pRSNReqIE =
13770 pWextState->WPARSNIE;
13771 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13772 break;
13773 /*
13774 * Appending Extended Capabilities with Interworking bit set
13775 * in Assoc Req.
13776 *
13777 * In assoc req this EXT Cap will only be taken into account if
13778 * interworkingService bit is set to 1. Currently
13779 * driver is only interested in interworkingService capability
13780 * from supplicant. If in future any other EXT Cap info is
13781 * required from supplicat, it needs to be handled while
13782 * sending Assoc Req in LIM.
13783 */
13784 case DOT11F_EID_EXTCAP:
13785 {
13786 uint16_t curAddIELen =
13787 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013788 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789
13790 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13791 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013792 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013793 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013794 return -ENOMEM;
13795 }
13796 memcpy(pWextState->assocAddIE.addIEdata +
13797 curAddIELen, genie - 2, eLen + 2);
13798 pWextState->assocAddIE.length += eLen + 2;
13799
13800 pWextState->roamProfile.pAddIEAssoc =
13801 pWextState->assocAddIE.addIEdata;
13802 pWextState->roamProfile.nAddIEAssocLength =
13803 pWextState->assocAddIE.length;
13804 break;
13805 }
13806#ifdef FEATURE_WLAN_WAPI
13807 case WLAN_EID_WAPI:
13808 /* Setting WAPI Mode to ON=1 */
13809 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013810 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013811 tmp = (u16 *) ie;
13812 tmp = tmp + 2; /* Skip element Id and Len, Version */
13813 akmsuiteCount = WPA_GET_LE16(tmp);
13814 tmp = tmp + 1;
13815 akmlist = (int *)(tmp);
13816 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13817 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13818 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013819 hdd_err("Invalid akmSuite count: %u",
13820 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013821 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 return -EINVAL;
13823 }
13824
13825 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013826 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013827 pAdapter->wapi_info.wapiAuthMode =
13828 WAPI_AUTH_MODE_PSK;
13829 }
13830 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013831 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013832 pAdapter->wapi_info.wapiAuthMode =
13833 WAPI_AUTH_MODE_CERT;
13834 }
13835 break;
13836#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013837 case DOT11F_EID_SUPPOPERATINGCLASSES:
13838 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013839 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013840 status = wlan_hdd_add_assoc_ie(pWextState,
13841 genie - 2, eLen + 2);
13842 if (status)
13843 return status;
13844 break;
13845 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013847 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013848 /* when Unknown IE is received we break
13849 * and continue to the next IE in the buffer
13850 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 break;
13852 }
13853 genie += eLen;
13854 remLen -= eLen;
13855 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013856 return 0;
13857}
13858
13859/**
13860 * hdd_is_wpaie_present() - check for WPA ie
13861 * @ie: Pointer to ie
13862 * @ie_len: Ie length
13863 *
13864 * Parse the received IE to find the WPA IE
13865 *
13866 * Return: true if wpa ie is found else false
13867 */
13868static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13869{
13870 uint8_t eLen = 0;
13871 uint16_t remLen = ie_len;
13872 uint8_t elementId = 0;
13873
13874 while (remLen >= 2) {
13875 elementId = *ie++;
13876 eLen = *ie++;
13877 remLen -= 2;
13878 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013879 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 return false;
13881 }
13882 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13883 /* OUI - 0x00 0X50 0XF2
13884 * WPA Information Element - 0x01
13885 * WPA version - 0x01
13886 */
13887 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13888 return true;
13889 }
13890 ie += eLen;
13891 remLen -= eLen;
13892 }
13893 return false;
13894}
13895
13896/**
13897 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13898 * @pAdapter: Pointer to adapter
13899 * @req: Pointer to security parameters
13900 *
13901 * Return: 0 for success, non-zero for failure
13902 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013903static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13904 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905{
13906 int status = 0;
13907 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13908 ENTER();
13909
13910 /*set wpa version */
13911 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13912
13913 if (req->crypto.wpa_versions) {
13914 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13915 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13916 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13917 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13918 }
13919 }
13920
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013921 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922
13923 /*set authentication type */
13924 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13925
13926 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013927 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928 return status;
13929 }
13930
13931 /*set key mgmt type */
13932 if (req->crypto.n_akm_suites) {
13933 status =
13934 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13935 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013936 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 return status;
13938 }
13939 }
13940
13941 /*set pairwise cipher type */
13942 if (req->crypto.n_ciphers_pairwise) {
13943 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13944 req->crypto.
13945 ciphers_pairwise[0],
13946 true);
13947 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013948 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013949 return status;
13950 }
13951 } else {
13952 /*Reset previous cipher suite to none */
13953 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13954 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013955 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956 return status;
13957 }
13958 }
13959
13960 /*set group cipher type */
13961 status =
13962 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13963 false);
13964
13965 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013966 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 return status;
13968 }
13969#ifdef WLAN_FEATURE_11W
13970 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13971#endif
13972
13973 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13974 if (req->ie_len) {
13975 status =
13976 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13977 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013978 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 return status;
13980 }
13981 }
13982
13983 /*incase of WEP set default key information */
13984 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013985 u8 key_len = req->key_len;
13986 u8 key_idx = req->key_idx;
13987
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013988 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13989 || (WLAN_CIPHER_SUITE_WEP104 ==
13990 req->crypto.ciphers_pairwise[0])
13991 ) {
13992 if (IW_AUTH_KEY_MGMT_802_1X
13993 ==
13994 (pWextState->
13995 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013996 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013997 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013998 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013999
Jeff Johnson68755312017-02-10 11:46:55 -080014000 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14001 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014002 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014003 key_idx, key_len);
14004 qdf_mem_copy(&pWextState->roamProfile.
14005 Keys.
14006 KeyMaterial[key_idx][0],
14007 req->key, key_len);
14008 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014010 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 }
14013 }
14014 }
14015
14016 return status;
14017}
14018
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014019int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020{
14021 unsigned long rc;
14022 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014023 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014024 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025
14026 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014027 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14028 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014029 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014030 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14031 }
14032 /*
14033 * If firmware has already started roaming process, driver
14034 * needs to defer the processing of this disconnect request.
14035 *
14036 */
14037 if (hdd_is_roaming_in_progress(pAdapter)) {
14038 /*
14039 * Defer the disconnect action until firmware roaming
14040 * result is received. If STA is in connected state after
14041 * that, send the disconnect command to CSR, otherwise
14042 * CSR would have already sent disconnect event to upper
14043 * layer.
14044 */
14045
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014046 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014047 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14048 pAdapter->cfg80211_disconnect_reason =
14049 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14050 return 0;
14051 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014052
Jeff Johnson9edf9572016-10-03 15:24:49 -070014053 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014054 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14055 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14056 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014057 hdd_conn_set_connection_state(pAdapter,
14058 eConnectionState_Disconnecting);
14059 /* Issue disconnect to CSR */
14060 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014061
14062 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14063 pAdapter->sessionId,
14064 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14065 /*
14066 * Wait here instead of returning directly, this will block the
14067 * next connect command and allow processing of the scan for
14068 * ssid and the previous connect command in CSR. Else we might
14069 * hit some race conditions leading to SME and HDD out of sync.
14070 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014071 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014072 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014073 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014074 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014075 (int)status);
14076 pHddStaCtx->staDebugState = status;
14077 result = -EINVAL;
14078 goto disconnected;
14079 }
14080
14081 rc = wait_for_completion_timeout(
14082 &pAdapter->disconnect_comp_var,
14083 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014084 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014085 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014086 pAdapter->sessionId, pHddStaCtx->staDebugState);
14087 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014088 }
14089 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014090 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014091 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014092 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014094 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014095 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014096 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014097 }
14098 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014099disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014100 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14101 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014102}
14103
14104/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014105 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14106 * @adapter: Pointer to the HDD adapter
14107 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014108 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014109 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014110 * This function will start reassociation if prev_bssid is set and bssid/
14111 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014112 *
Naveen Rawat07332902016-07-27 09:13:17 -070014113 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014114 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014115#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14116 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014117static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14118 struct cfg80211_connect_params *req,
14119 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014120{
Naveen Rawat07332902016-07-27 09:13:17 -070014121 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014122 const uint8_t *bssid = NULL;
14123 uint16_t channel = 0;
14124
14125 if (req->bssid)
14126 bssid = req->bssid;
14127 else if (req->bssid_hint)
14128 bssid = req->bssid_hint;
14129
14130 if (req->channel)
14131 channel = req->channel->hw_value;
14132 else if (req->channel_hint)
14133 channel = req->channel_hint->hw_value;
14134
14135 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014136 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014137 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014138 channel, MAC_ADDR_ARRAY(bssid));
14139 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014140 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014141 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014142 }
Naveen Rawat07332902016-07-27 09:13:17 -070014143 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014144}
14145#else
Naveen Rawat07332902016-07-27 09:13:17 -070014146static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14147 struct cfg80211_connect_params *req,
14148 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014149{
Naveen Rawat07332902016-07-27 09:13:17 -070014150 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014151}
14152#endif
14153
14154/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14156 * @wiphy: Pointer to wiphy
14157 * @dev: Pointer to network device
14158 * @req: Pointer to cfg80211 connect request
14159 *
14160 * This function is used to start the association process
14161 *
14162 * Return: 0 for success, non-zero for failure
14163 */
14164static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14165 struct net_device *ndev,
14166 struct cfg80211_connect_params *req)
14167{
14168 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014169 u16 channel;
14170#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14171 const u8 *bssid_hint = req->bssid_hint;
14172#else
14173 const u8 *bssid_hint = NULL;
14174#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014175 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14176 hdd_context_t *pHddCtx;
14177
14178 ENTER();
14179
Anurag Chouhan6d760662016-02-20 16:05:43 +053014180 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014181 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014182 return -EINVAL;
14183 }
14184
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014185 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14186 hdd_err("invalid session id: %d", pAdapter->sessionId);
14187 return -EINVAL;
14188 }
14189
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014190 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 TRACE_CODE_HDD_CFG80211_CONNECT,
14192 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014193 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194 hdd_device_mode_to_string(pAdapter->device_mode),
14195 pAdapter->device_mode);
14196
Krunal Sonib4326f22016-03-10 13:05:51 -080014197 if (pAdapter->device_mode != QDF_STA_MODE &&
14198 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014199 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 hdd_device_mode_to_string(pAdapter->device_mode),
14201 pAdapter->device_mode);
14202 return -EINVAL;
14203 }
14204
14205 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14206 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014207 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 return -EINVAL;
14209 }
14210
14211 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014212 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014213 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014214
Naveen Rawat07332902016-07-27 09:13:17 -070014215 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014216 return status;
14217
Agrawal Ashishf156e942016-08-04 14:54:47 +053014218 /* Try disconnecting if already in connected state */
14219 status = wlan_hdd_try_disconnect(pAdapter);
14220 if (0 > status) {
14221 hdd_err("Failed to disconnect the existing connection");
14222 return -EALREADY;
14223 }
14224
14225 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014226 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014227 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14228 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014229 pAdapter->device_mode),
14230 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014231 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 return -ECONNREFUSED;
14233 }
14234 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014235 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14236 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014237 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014238 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014239 return -ECONNREFUSED;
14240 }
14241 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 /*initialise security parameters */
14244 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14245
14246 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014247 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014248 return status;
14249 }
14250
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014251 if (req->channel)
14252 channel = req->channel->hw_value;
14253 else
14254 channel = 0;
14255 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14256 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014257 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014258 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014259 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014260 return status;
14261 }
14262 EXIT();
14263 return status;
14264}
14265
14266/**
14267 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14268 * @wiphy: Pointer to wiphy
14269 * @dev: Pointer to network device
14270 * @req: Pointer to cfg80211 connect request
14271 *
14272 * Return: 0 for success, non-zero for failure
14273 */
14274static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14275 struct net_device *ndev,
14276 struct cfg80211_connect_params *req)
14277{
14278 int ret;
14279 cds_ssr_protect(__func__);
14280 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14281 cds_ssr_unprotect(__func__);
14282
14283 return ret;
14284}
14285
14286/**
14287 * wlan_hdd_disconnect() - hdd disconnect api
14288 * @pAdapter: Pointer to adapter
14289 * @reason: Disconnect reason code
14290 *
14291 * This function is used to issue a disconnect request to SME
14292 *
14293 * Return: 0 for success, non-zero for failure
14294 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014295static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296{
14297 int status, result = 0;
14298 unsigned long rc;
14299 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14300 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014301 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014302 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014304 ENTER();
14305
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014306 status = wlan_hdd_validate_context(pHddCtx);
14307
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014308 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014309 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014310 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014311 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014312 status = sme_stop_roaming(hal, pAdapter->sessionId,
14313 eCsrHddIssued);
14314 }
14315 /*
14316 * If firmware has already started roaming process, driver
14317 * needs to defer the processing of this disconnect request.
14318 */
14319 if (hdd_is_roaming_in_progress(pAdapter)) {
14320 /*
14321 * Defer the disconnect action until firmware roaming
14322 * result is received. If STA is in connected state after
14323 * that, send the disconnect command to CSR, otherwise
14324 * CSR would have already sent disconnect event to upper
14325 * layer.
14326 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014327 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014328 pAdapter->defer_disconnect =
14329 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14330 pAdapter->cfg80211_disconnect_reason = reason;
14331 return 0;
14332 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014334 prev_conn_state = pHddStaCtx->conn_info.connState;
14335
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014336 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014337 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014338 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014339 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014340 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014341 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14342 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14343
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014344 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014345
14346 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14347 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014348 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14349 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014350 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014351 result = 0;
14352 goto disconnected;
14353 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14354 /*
14355 * Wait here instead of returning directly, this will block the
14356 * next connect command and allow processing of the scan for
14357 * ssid and the previous connect command in CSR. Else we might
14358 * hit some race conditions leading to SME and HDD out of sync.
14359 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014360 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014361 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014362 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014363 pHddStaCtx->staDebugState = status;
14364 result = -EINVAL;
14365 goto disconnected;
14366 }
14367 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14368 msecs_to_jiffies
14369 (WLAN_WAIT_TIME_DISCONNECT));
14370
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014371 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014372 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014373 result = -ETIMEDOUT;
14374 }
14375disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014376 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14377#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14378 /* Sending disconnect event to userspace for kernel version < 3.11
14379 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14380 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014381 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014382 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14383 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014384#endif
14385
14386 return result;
14387}
14388
14389/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014390 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14391 * @reason: ieee80211 reason code.
14392 *
14393 * This utility function helps log string conversion of reason code.
14394 *
14395 * Return: string conversion of reason code, if match found;
14396 * "Unknown" otherwise.
14397 */
14398static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14399{
14400 switch (reason) {
14401 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14402 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14403 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14404 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14405 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14406 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14407 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14408 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14409 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14410 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14411 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14412 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14413 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14414 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14415 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14416 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14417 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14418 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14419 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14420 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14421 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14422 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14423 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14424 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14425 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14426 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14427 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14428 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14429 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14430 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14431 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14432 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14433 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14434 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14435 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14436 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14437 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14438 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14439 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14440 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14441 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14442 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14443 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14444 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14445 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14446 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14447 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14448 default:
14449 return "Unknown";
14450 }
14451}
14452
14453/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014454 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14455 * @wiphy: Pointer to wiphy
14456 * @dev: Pointer to network device
14457 * @reason: Disconnect reason code
14458 *
14459 * This function is used to issue a disconnect request to SME
14460 *
14461 * Return: 0 for success, non-zero for failure
14462 */
14463static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14464 struct net_device *dev, u16 reason)
14465{
14466 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14467 int status;
14468 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14469 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14470#ifdef FEATURE_WLAN_TDLS
14471 uint8_t staIdx;
14472#endif
14473
14474 ENTER();
14475
Anurag Chouhan6d760662016-02-20 16:05:43 +053014476 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014477 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478 return -EINVAL;
14479 }
14480
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014481 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014482 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014483 return -EINVAL;
14484 }
14485
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014486 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014487 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14488 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014489 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014490 hdd_device_mode_to_string(pAdapter->device_mode),
14491 pAdapter->device_mode, reason);
14492
14493 status = wlan_hdd_validate_context(pHddCtx);
14494
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014495 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014497
14498 /* Issue disconnect request to SME, if station is in connected state */
14499 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14500 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14501 eCsrRoamDisconnectReason reasonCode =
14502 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14503 hdd_scaninfo_t *pScanInfo;
14504
14505 switch (reason) {
14506 case WLAN_REASON_MIC_FAILURE:
14507 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14508 break;
14509
14510 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14511 case WLAN_REASON_DISASSOC_AP_BUSY:
14512 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14513 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14514 break;
14515
14516 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14517 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14518 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14519 break;
14520
14521 case WLAN_REASON_DEAUTH_LEAVING:
14522 reasonCode =
14523 pHddCtx->config->
14524 gEnableDeauthToDisassocMap ?
14525 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14526 eCSR_DISCONNECT_REASON_DEAUTH;
14527 break;
14528 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14529 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14530 break;
14531 default:
14532 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14533 break;
14534 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014535 pScanInfo = &pAdapter->scan_info;
14536 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014537 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014539 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014540 eCSR_SCAN_ABORT_DEFAULT);
14541 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014542 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014543#ifdef FEATURE_WLAN_TDLS
14544 /* First clean up the tdls peers if any */
14545 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14546 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14547 pAdapter->sessionId)
14548 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14549 uint8_t *mac;
14550 mac =
14551 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014552 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014553 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 pHddCtx->tdlsConnInfo[staIdx].staId,
14555 pAdapter->sessionId,
14556 MAC_ADDR_ARRAY(mac));
14557 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14558 (pAdapter),
14559 pAdapter->sessionId, mac);
14560 }
14561 }
14562#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014563 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14564 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14566 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014567 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014568 return -EINVAL;
14569 }
14570 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014571 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 pHddStaCtx->conn_info.connState);
14573 }
14574
14575 return status;
14576}
14577
14578/**
14579 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14580 * @wiphy: Pointer to wiphy
14581 * @dev: Pointer to network device
14582 * @reason: Disconnect reason code
14583 *
14584 * Return: 0 for success, non-zero for failure
14585 */
14586static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14587 struct net_device *dev, u16 reason)
14588{
14589 int ret;
14590 cds_ssr_protect(__func__);
14591 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14592 cds_ssr_unprotect(__func__);
14593
14594 return ret;
14595}
14596
14597/**
14598 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14599 * @pAdapter: Pointer to adapter
14600 * @param: Pointer to IBSS parameters
14601 *
14602 * This function is used to initialize the security settings in IBSS mode
14603 *
14604 * Return: 0 for success, non-zero for failure
14605 */
14606static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14607 struct cfg80211_ibss_params
14608 *params)
14609{
14610 int status = 0;
14611 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14612 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14613 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14614
14615 ENTER();
14616
14617 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014618 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014619 pHddStaCtx->ibss_enc_key_installed = 0;
14620
14621 if (params->ie_len && (NULL != params->ie)) {
14622 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14623 params->ie_len, WLAN_EID_RSN)) {
14624 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14625 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14626 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14627 tDot11fIEWPA dot11WPAIE;
14628 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14629 u8 *ie;
14630
14631 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14632 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14633 params->ie_len,
14634 DOT11F_EID_WPA);
14635 if (NULL != ie) {
14636 pWextState->wpaVersion =
14637 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014638 /* Unpack the WPA IE
14639 * Skip past the EID byte and length byte
14640 * and four byte WiFi OUI
14641 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014642 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014643 &ie[2 + 4], ie[1] - 4,
14644 &dot11WPAIE, false);
14645 /*
14646 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014647 * encType for unicast cipher for
14648 * wpa-none is none
14649 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014650 encryptionType =
14651 hdd_translate_wpa_to_csr_encryption_type
14652 (dot11WPAIE.multicast_cipher);
14653 }
14654 }
14655
14656 status =
14657 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14658 params->ie_len);
14659
14660 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014661 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014662 return status;
14663 }
14664 }
14665
14666 pWextState->roamProfile.AuthType.authType[0] =
14667 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14668
14669 if (params->privacy) {
14670 /* Security enabled IBSS, At this time there is no information
14671 * available about the security paramters, so initialise the
14672 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14673 * The correct security parameters will be updated later in
14674 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14675 * set inorder enable privacy bit in beacons
14676 */
14677
14678 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14679 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014680 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014681 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14682 pWextState->roamProfile.EncryptionType.numEntries = 1;
14683 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14684 encryptionType;
14685 return status;
14686}
14687
14688/**
14689 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14690 * @wiphy: Pointer to wiphy
14691 * @dev: Pointer to network device
14692 * @param: Pointer to IBSS join parameters
14693 *
14694 * This function is used to create/join an IBSS network
14695 *
14696 * Return: 0 for success, non-zero for failure
14697 */
14698static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14699 struct net_device *dev,
14700 struct cfg80211_ibss_params *params)
14701{
14702 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14703 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14704 tCsrRoamProfile *pRoamProfile;
14705 int status;
14706 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14707 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014708 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014709 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014710
14711 ENTER();
14712
Anurag Chouhan6d760662016-02-20 16:05:43 +053014713 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014714 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014715 return -EINVAL;
14716 }
14717
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014718 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014719 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014720 return -EINVAL;
14721 }
14722
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014723 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014724 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14725 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014726 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014727 hdd_device_mode_to_string(pAdapter->device_mode),
14728 pAdapter->device_mode);
14729
14730 status = wlan_hdd_validate_context(pHddCtx);
14731
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014732 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734
14735 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014736 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014737 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14738 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14739 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14740 int indx;
14741
14742 /* Get channel number */
14743 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014744 params->
14745 chandef.
14746 chan->
14747 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748
14749 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14750 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014751 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014752 return -EOPNOTSUPP;
14753 }
14754
14755 for (indx = 0; indx < numChans; indx++) {
14756 if (channelNum == validChan[indx]) {
14757 break;
14758 }
14759 }
14760 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014761 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014762 return -EINVAL;
14763 }
14764 }
14765
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014766 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14767 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014768 hdd_err("This concurrency combination is not allowed");
14769 return -ECONNREFUSED;
14770 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014771
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014772 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014773 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014774 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014775
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014776 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14777 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014778 SIR_UPDATE_REASON_JOIN_IBSS);
14779 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014780 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014781 return -EINVAL;
14782 }
14783
14784 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014785 status = policy_mgr_wait_for_connection_update(
14786 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014787 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014788 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014789 return -EINVAL;
14790 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014791 }
14792
14793 /*Try disconnecting if already in connected state */
14794 status = wlan_hdd_try_disconnect(pAdapter);
14795 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014796 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014797 return -EALREADY;
14798 }
14799
14800 pRoamProfile = &pWextState->roamProfile;
14801
14802 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014803 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 return -EINVAL;
14805 }
14806
14807 /* enable selected protection checks in IBSS mode */
14808 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14809
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014810 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14812 pHddCtx->config->
14813 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014814 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014815 }
14816
14817 /* BSSID is provided by upper layers hence no need to AUTO generate */
14818 if (NULL != params->bssid) {
14819 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014820 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014821 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014822 return -EIO;
14823 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014824 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14826 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014827 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014828 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014829 return -EIO;
14830 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014831 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014832 }
14833 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14834 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14835 pRoamProfile->beaconInterval = params->beacon_interval;
14836 else {
14837 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014838 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014839 params->beacon_interval, pRoamProfile->beaconInterval);
14840 }
14841
14842 /* Set Channel */
14843 if (channelNum) {
14844 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014845 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014846 pRoamProfile->ChannelInfo.numOfChannels = 1;
14847 pHddStaCtx->conn_info.operationChannel = channelNum;
14848 pRoamProfile->ChannelInfo.ChannelList =
14849 &pHddStaCtx->conn_info.operationChannel;
14850 }
14851
14852 /* Initialize security parameters */
14853 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14854 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014855 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856 return status;
14857 }
14858
14859 /* Issue connect start */
14860 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14861 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014862 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014863 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014864 operationChannel,
14865 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014866
14867 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014868 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014869 return status;
14870 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014871 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014872 return 0;
14873}
14874
14875/**
14876 * wlan_hdd_cfg80211_join_ibss() - join ibss
14877 * @wiphy: Pointer to wiphy
14878 * @dev: Pointer to network device
14879 * @param: Pointer to IBSS join parameters
14880 *
14881 * This function is used to create/join an IBSS network
14882 *
14883 * Return: 0 for success, non-zero for failure
14884 */
14885static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14886 struct net_device *dev,
14887 struct cfg80211_ibss_params *params)
14888{
14889 int ret = 0;
14890
14891 cds_ssr_protect(__func__);
14892 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14893 cds_ssr_unprotect(__func__);
14894
14895 return ret;
14896}
14897
14898/**
14899 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14900 * @wiphy: Pointer to wiphy
14901 * @dev: Pointer to network device
14902 *
14903 * This function is used to leave an IBSS network
14904 *
14905 * Return: 0 for success, non-zero for failure
14906 */
14907static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14908 struct net_device *dev)
14909{
14910 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14911 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14912 tCsrRoamProfile *pRoamProfile;
14913 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14914 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014915 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014916 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014917 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918
14919 ENTER();
14920
Anurag Chouhan6d760662016-02-20 16:05:43 +053014921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014922 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014923 return -EINVAL;
14924 }
14925
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014926 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014927 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014928 return -EINVAL;
14929 }
14930
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014931 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014932 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14933 pAdapter->sessionId,
14934 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14935 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014936 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014937 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014938
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014939 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014940 hdd_device_mode_to_string(pAdapter->device_mode),
14941 pAdapter->device_mode);
14942 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014943 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014944 return -EIO;
14945 }
14946
14947 pRoamProfile = &pWextState->roamProfile;
14948
14949 /* Issue disconnect only if interface type is set to IBSS */
14950 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014951 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014952 return -EINVAL;
14953 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014954 /* Clearing add IE of beacon */
14955 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14956 sizeof(tSirMacAddr));
14957 updateIE.smeSessionId = pAdapter->sessionId;
14958 updateIE.ieBufferlength = 0;
14959 updateIE.pAdditionIEBuffer = NULL;
14960 updateIE.append = true;
14961 updateIE.notify = true;
14962 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14963 &updateIE,
14964 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014965 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014966 }
14967
14968 /* Reset WNI_CFG_PROBE_RSP Flags */
14969 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970
14971 /* Issue Disconnect request */
14972 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14973 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14974 pAdapter->sessionId,
14975 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014976 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014977 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978 hal_status);
14979 return -EAGAIN;
14980 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014981
14982 /* wait for mc thread to cleanup and then return to upper stack
14983 * so by the time upper layer calls the change interface, we are
14984 * all set to proceed further
14985 */
14986 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14987 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14988 if (!rc) {
14989 hdd_err("Failed to disconnect, timed out");
14990 return -ETIMEDOUT;
14991 }
14992
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014993 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014994 return 0;
14995}
14996
14997/**
14998 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14999 * @wiphy: Pointer to wiphy
15000 * @dev: Pointer to network device
15001 *
15002 * This function is used to leave an IBSS network
15003 *
15004 * Return: 0 for success, non-zero for failure
15005 */
15006static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15007 struct net_device *dev)
15008{
15009 int ret = 0;
15010
15011 cds_ssr_protect(__func__);
15012 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15013 cds_ssr_unprotect(__func__);
15014
15015 return ret;
15016}
15017
15018/**
15019 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15020 * @wiphy: Pointer to wiphy
15021 * @changed: Parameters changed
15022 *
15023 * This function is used to set the phy parameters. RTS Threshold/FRAG
15024 * Threshold/Retry Count etc.
15025 *
15026 * Return: 0 for success, non-zero for failure
15027 */
15028static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15029 u32 changed)
15030{
15031 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15032 tHalHandle hHal = pHddCtx->hHal;
15033 int status;
15034
15035 ENTER();
15036
Anurag Chouhan6d760662016-02-20 16:05:43 +053015037 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015038 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 return -EINVAL;
15040 }
15041
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015042 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15044 NO_SESSION, wiphy->rts_threshold));
15045 status = wlan_hdd_validate_context(pHddCtx);
15046
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015047 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015048 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015049
15050 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15051 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15052 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15053
15054 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15055 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015056 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015057 rts_threshold);
15058 return -EINVAL;
15059 }
15060
15061 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15062 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015063 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 rts_threshold);
15065 return -EIO;
15066 }
15067
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015068 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015069 }
15070
15071 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15072 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15073 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15074 wiphy->frag_threshold;
15075
15076 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15077 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015078 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015079 frag_threshold);
15080 return -EINVAL;
15081 }
15082
15083 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15084 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015085 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015086 frag_threshold);
15087 return -EIO;
15088 }
15089
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015090 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015091 }
15092
15093 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15094 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15095 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15096 wiphy->retry_short : wiphy->retry_long;
15097
15098 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15099 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015100 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015101 return -EINVAL;
15102 }
15103
15104 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15105 if (0 != sme_cfg_set_int(hHal,
15106 WNI_CFG_LONG_RETRY_LIMIT,
15107 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015108 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015109 retry_value);
15110 return -EIO;
15111 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015112 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015113 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15114 if (0 != sme_cfg_set_int(hHal,
15115 WNI_CFG_SHORT_RETRY_LIMIT,
15116 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015117 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015118 retry_value);
15119 return -EIO;
15120 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015121 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015122 }
15123 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015124 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125 return 0;
15126}
15127
15128/**
15129 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15130 * @wiphy: Pointer to wiphy
15131 * @changed: Parameters changed
15132 *
15133 * Return: 0 for success, non-zero for failure
15134 */
15135static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15136{
15137 int ret;
15138
15139 cds_ssr_protect(__func__);
15140 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15141 cds_ssr_unprotect(__func__);
15142
15143 return ret;
15144}
15145
15146/**
15147 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15148 * key
15149 * @wiphy: Pointer to wiphy
15150 * @dev: Pointer to network device
15151 * @key_index: Key index
15152 *
15153 * Return: 0
15154 */
15155static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15156 struct net_device *netdev,
15157 u8 key_index)
15158{
15159 ENTER();
15160 return 0;
15161}
15162
15163/**
15164 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15165 * wlan_hdd_set_default_mgmt_key
15166 * @wiphy: pointer to wiphy
15167 * @netdev: pointer to net_device structure
15168 * @key_index: key index
15169 *
15170 * Return: 0 on success, error number on failure
15171 */
15172static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15173 struct net_device *netdev,
15174 u8 key_index)
15175{
15176 int ret;
15177
15178 cds_ssr_protect(__func__);
15179 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15180 cds_ssr_unprotect(__func__);
15181
15182 return ret;
15183}
15184
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015185/**
15186 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15187 * @wiphy: Pointer to wiphy
15188 * @dev: Pointer to network device
15189 * @params: Pointer to tx queue parameters
15190 *
15191 * Return: 0
15192 */
15193static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15194 struct net_device *dev,
15195 struct ieee80211_txq_params *params)
15196{
15197 ENTER();
15198 return 0;
15199}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015200
15201/**
15202 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15203 * @wiphy: pointer to wiphy
15204 * @netdev: pointer to net_device structure
15205 * @params: pointer to ieee80211_txq_params
15206 *
15207 * Return: 0 on success, error number on failure
15208 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015209static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15210 struct net_device *dev,
15211 struct ieee80211_txq_params *params)
15212{
15213 int ret;
15214
15215 cds_ssr_protect(__func__);
15216 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15217 cds_ssr_unprotect(__func__);
15218
15219 return ret;
15220}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015221
15222/**
15223 * __wlan_hdd_cfg80211_del_station() - delete station v2
15224 * @wiphy: Pointer to wiphy
15225 * @param: Pointer to delete station parameter
15226 *
15227 * Return: 0 for success, non-zero for failure
15228 */
15229static
15230int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15231 struct net_device *dev,
15232 struct tagCsrDelStaParams *pDelStaParams)
15233{
15234 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15235 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015236 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015237 hdd_hostapd_state_t *hapd_state;
15238 int status;
15239 uint8_t staId;
15240 uint8_t *mac;
15241
15242 ENTER();
15243
Anurag Chouhan6d760662016-02-20 16:05:43 +053015244 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015245 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 return -EINVAL;
15247 }
15248
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015249 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015250 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015251 return -EINVAL;
15252 }
15253
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015254 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255 TRACE_CODE_HDD_CFG80211_DEL_STA,
15256 pAdapter->sessionId, pAdapter->device_mode));
15257
15258 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15259 status = wlan_hdd_validate_context(pHddCtx);
15260
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015261 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015262 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015263
15264 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15265
Krunal Sonib4326f22016-03-10 13:05:51 -080015266 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15267 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015268
15269 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15270 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015271 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015272 return 0;
15273 }
15274
Anurag Chouhanc5548422016-02-24 18:33:27 +053015275 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015276 uint16_t i;
15277 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15278 if ((pAdapter->aStaInfo[i].isUsed) &&
15279 (!pAdapter->aStaInfo[i].
15280 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015281 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 mac,
15283 pAdapter->aStaInfo[i].
15284 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015285 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015286 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15287 hdd_ipa_wlan_evt(pAdapter,
15288 pAdapter->
15289 aStaInfo[i].
15290 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015291 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015292 mac);
15293 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015294 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015295 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015296 MAC_ADDR_ARRAY(mac));
15297
15298 if (pHddCtx->dev_dfs_cac_status ==
15299 DFS_CAC_IN_PROGRESS)
15300 goto fn_end;
15301
Wei Song2f76f642016-11-18 16:32:53 +080015302 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015303 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015304 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015305 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015306 hdd_softap_sta_deauth(pAdapter,
15307 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015308 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 pAdapter->aStaInfo[i].
15310 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015311 qdf_status =
15312 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015313 &hapd_state->
15314 qdf_sta_disassoc_event,
15315 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015316 if (!QDF_IS_STATUS_SUCCESS(
15317 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015318 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015319 }
15320 }
15321 }
15322 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015323 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015325 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015326 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015327 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015328 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015329 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015330 MAC_ADDR_ARRAY(mac));
15331 return -ENOENT;
15332 }
15333
15334 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15335 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015336 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015337 }
15338
15339 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15340 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015341 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015342 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015343 MAC_ADDR_ARRAY(mac));
15344 return -ENOENT;
15345 }
15346
15347 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15348
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015349 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015350 MAC_ADDR_ARRAY(mac));
15351
15352 /* Case: SAP in ACS selected DFS ch and client connected
15353 * Now Radar detected. Then if random channel is another
15354 * DFS ch then new CAC is initiated and no TX allowed.
15355 * So do not send any mgmt frames as it will timeout
15356 * during CAC.
15357 */
15358
15359 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15360 goto fn_end;
15361
Wei Song2f76f642016-11-18 16:32:53 +080015362 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015363 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15364 (pAdapter), pAdapter->sessionId,
15365 (uint8_t *)&pDelStaParams->peerMacAddr,
15366 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015367 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015368 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015369 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015370 pAdapter->aStaInfo[staId].isDeauthInProgress =
15371 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015372 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015373 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374 MAC_ADDR_ARRAY(mac));
15375 return -ENOENT;
15376 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015377 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015378 &hapd_state->
15379 qdf_sta_disassoc_event,
15380 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015381 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015382 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015383 }
15384 }
15385 }
15386
15387fn_end:
15388 EXIT();
15389 return 0;
15390}
15391
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015392#if defined(USE_CFG80211_DEL_STA_V2)
15393/**
15394 * wlan_hdd_del_station() - delete station wrapper
15395 * @adapter: pointer to the hdd adapter
15396 *
15397 * Return: None
15398 */
15399void wlan_hdd_del_station(hdd_adapter_t *adapter)
15400{
15401 struct station_del_parameters del_sta;
15402 del_sta.mac = NULL;
15403 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15404 del_sta.reason_code = eCsrForcedDeauthSta;
15405
15406 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15407 &del_sta);
15408}
15409#else
15410void wlan_hdd_del_station(hdd_adapter_t *adapter)
15411{
15412 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15413}
15414#endif
15415
15416#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015417/**
15418 * wlan_hdd_cfg80211_del_station() - delete station v2
15419 * @wiphy: Pointer to wiphy
15420 * @param: Pointer to delete station parameter
15421 *
15422 * Return: 0 for success, non-zero for failure
15423 */
15424int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15425 struct net_device *dev,
15426 struct station_del_parameters *param)
15427#else
15428/**
15429 * wlan_hdd_cfg80211_del_station() - delete station
15430 * @wiphy: Pointer to wiphy
15431 * @mac: Pointer to station mac address
15432 *
15433 * Return: 0 for success, non-zero for failure
15434 */
15435#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15436int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15437 struct net_device *dev,
15438 const uint8_t *mac)
15439#else
15440int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15441 struct net_device *dev,
15442 uint8_t *mac)
15443#endif
15444#endif
15445{
15446 int ret;
15447 struct tagCsrDelStaParams delStaParams;
15448
15449 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015450#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015451 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015452 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015453 return -EINVAL;
15454 }
15455 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15456 param->subtype, &delStaParams);
15457#else
15458 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15459 (SIR_MAC_MGMT_DEAUTH >> 4),
15460 &delStaParams);
15461#endif
15462 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15463 cds_ssr_unprotect(__func__);
15464
15465 return ret;
15466}
15467
15468/**
15469 * __wlan_hdd_cfg80211_add_station() - add station
15470 * @wiphy: Pointer to wiphy
15471 * @mac: Pointer to station mac address
15472 * @pmksa: Pointer to add station parameter
15473 *
15474 * Return: 0 for success, non-zero for failure
15475 */
15476static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15477 struct net_device *dev,
15478 const uint8_t *mac,
15479 struct station_parameters *params)
15480{
15481 int status = -EPERM;
15482#ifdef FEATURE_WLAN_TDLS
15483 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15484 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15485 u32 mask, set;
15486
15487 ENTER();
15488
Anurag Chouhan6d760662016-02-20 16:05:43 +053015489 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015490 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 return -EINVAL;
15492 }
15493
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015494 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015495 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015496 return -EINVAL;
15497 }
15498
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015499 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015500 TRACE_CODE_HDD_CFG80211_ADD_STA,
15501 pAdapter->sessionId, params->listen_interval));
15502
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015503 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015504 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015505
15506 mask = params->sta_flags_mask;
15507
15508 set = params->sta_flags_set;
15509
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015510 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015511 MAC_ADDR_ARRAY(mac));
15512
15513 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15514 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015515#if defined(CONVERGED_TDLS_ENABLE)
15516 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15517 dev, mac);
15518#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015519 status =
15520 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015521#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015522 }
15523 }
15524#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015525 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015526 return status;
15527}
15528
15529/**
15530 * wlan_hdd_cfg80211_add_station() - add station
15531 * @wiphy: Pointer to wiphy
15532 * @mac: Pointer to station mac address
15533 * @pmksa: Pointer to add station parameter
15534 *
15535 * Return: 0 for success, non-zero for failure
15536 */
15537#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15538static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15539 struct net_device *dev,
15540 const uint8_t *mac,
15541 struct station_parameters *params)
15542#else
15543static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15544 struct net_device *dev, uint8_t *mac,
15545 struct station_parameters *params)
15546#endif
15547{
15548 int ret;
15549
15550 cds_ssr_protect(__func__);
15551 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15552 cds_ssr_unprotect(__func__);
15553
15554 return ret;
15555}
15556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557/**
15558 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15559 * @wiphy: Pointer to wiphy
15560 * @dev: Pointer to network device
15561 * @pmksa: Pointer to set pmksa parameter
15562 *
15563 * Return: 0 for success, non-zero for failure
15564 */
15565static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15566 struct net_device *dev,
15567 struct cfg80211_pmksa *pmksa)
15568{
15569 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15570 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15571 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015572 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015573 int status;
15574 tPmkidCacheInfo pmk_id;
15575
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015576 ENTER();
15577
Anurag Chouhan6d760662016-02-20 16:05:43 +053015578 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015579 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580 return -EINVAL;
15581 }
15582
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015583 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015584 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015585 return -EINVAL;
15586 }
15587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015588 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015589 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015590 return -EINVAL;
15591 }
15592
15593 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015594 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595 pmksa->bssid, pmksa->pmkid);
15596 return -EINVAL;
15597 }
15598
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015599 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015600 MAC_ADDR_ARRAY(pmksa->bssid));
15601
15602 status = wlan_hdd_validate_context(pHddCtx);
15603
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015604 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015605 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606
15607 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15608
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015609 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15610 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015611
15612 /* Add to the PMKSA ID Cache in CSR */
15613 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15614 &pmk_id, 1, false);
15615
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015616 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015617 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15618 pAdapter->sessionId, result));
15619
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015620 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015621 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015622}
15623
15624/**
15625 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15626 * @wiphy: Pointer to wiphy
15627 * @dev: Pointer to network device
15628 * @pmksa: Pointer to set pmksa parameter
15629 *
15630 * Return: 0 for success, non-zero for failure
15631 */
15632static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15633 struct net_device *dev,
15634 struct cfg80211_pmksa *pmksa)
15635{
15636 int ret;
15637
15638 cds_ssr_protect(__func__);
15639 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15640 cds_ssr_unprotect(__func__);
15641
15642 return ret;
15643}
15644
15645/**
15646 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15647 * @wiphy: Pointer to wiphy
15648 * @dev: Pointer to network device
15649 * @pmksa: Pointer to pmksa parameter
15650 *
15651 * Return: 0 for success, non-zero for failure
15652 */
15653static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15654 struct net_device *dev,
15655 struct cfg80211_pmksa *pmksa)
15656{
15657 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15658 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15659 tHalHandle halHandle;
15660 int status = 0;
15661
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015662 ENTER();
15663
Anurag Chouhan6d760662016-02-20 16:05:43 +053015664 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015665 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015666 return -EINVAL;
15667 }
15668
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015669 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15670 hdd_err("invalid session id: %d", pAdapter->sessionId);
15671 return -EINVAL;
15672 }
15673
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015674 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015675 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676 return -EINVAL;
15677 }
15678
15679 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015680 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015681 return -EINVAL;
15682 }
15683
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015684 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015685 MAC_ADDR_ARRAY(pmksa->bssid));
15686
15687 status = wlan_hdd_validate_context(pHddCtx);
15688
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015689 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015690 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015691
15692 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15693
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015694 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015695 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15696 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015697 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015698 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015699 sme_roam_del_pmkid_from_cache(halHandle,
15700 pAdapter->sessionId, pmksa->bssid,
15701 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015702 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703 MAC_ADDR_ARRAY(pmksa->bssid));
15704 status = -EINVAL;
15705 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015706 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015707 return status;
15708}
15709
15710/**
15711 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15712 * @wiphy: Pointer to wiphy
15713 * @dev: Pointer to network device
15714 * @pmksa: Pointer to pmksa parameter
15715 *
15716 * Return: 0 for success, non-zero for failure
15717 */
15718static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15719 struct net_device *dev,
15720 struct cfg80211_pmksa *pmksa)
15721{
15722 int ret;
15723
15724 cds_ssr_protect(__func__);
15725 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15726 cds_ssr_unprotect(__func__);
15727
15728 return ret;
15729
15730}
15731
15732/**
15733 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15734 * @wiphy: Pointer to wiphy
15735 * @dev: Pointer to network device
15736 *
15737 * Return: 0 for success, non-zero for failure
15738 */
15739static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15740 struct net_device *dev)
15741{
15742 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15743 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15744 tHalHandle halHandle;
15745 int status = 0;
15746
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015747 ENTER();
15748
Anurag Chouhan6d760662016-02-20 16:05:43 +053015749 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015750 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 return -EINVAL;
15752 }
15753
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015754 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15755 hdd_err("invalid session id: %d", pAdapter->sessionId);
15756 return -EINVAL;
15757 }
15758
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015759 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015760
15761 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15762 status = wlan_hdd_validate_context(pHddCtx);
15763
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015764 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015765 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015766
15767 /* Retrieve halHandle */
15768 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15769
15770 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015771 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015772 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15773 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015774 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775 status = -EINVAL;
15776 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015777 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015778 return status;
15779}
15780
15781/**
15782 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15783 * @wiphy: Pointer to wiphy
15784 * @dev: Pointer to network device
15785 *
15786 * Return: 0 for success, non-zero for failure
15787 */
15788static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15789 struct net_device *dev)
15790{
15791 int ret;
15792
15793 cds_ssr_protect(__func__);
15794 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15795 cds_ssr_unprotect(__func__);
15796
15797 return ret;
15798}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015799
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015800#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015801/**
15802 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15803 * @wiphy: Pointer to wiphy
15804 * @dev: Pointer to network device
15805 * @ftie: Pointer to fast transition ie parameter
15806 *
15807 * Return: 0 for success, non-zero for failure
15808 */
15809static int
15810__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15811 struct net_device *dev,
15812 struct cfg80211_update_ft_ies_params *ftie)
15813{
15814 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15815 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15816 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15817 int status;
15818
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015819 ENTER();
15820
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821 status = wlan_hdd_validate_context(hdd_ctx);
15822 if (status)
15823 return status;
15824
Anurag Chouhan6d760662016-02-20 16:05:43 +053015825 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015826 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 return -EINVAL;
15828 }
15829
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015830 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15831 hdd_err("invalid session id: %d", pAdapter->sessionId);
15832 return -EINVAL;
15833 }
15834
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015835 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15837 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15838 /* Added for debug on reception of Re-assoc Req. */
15839 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015840 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015841 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015842 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015843 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015844 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015845 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015846
15847 /* Pass the received FT IEs to SME */
15848 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15849 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015850 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015851 return 0;
15852}
15853
15854/**
15855 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15856 * @wiphy: Pointer to wiphy
15857 * @dev: Pointer to network device
15858 * @ftie: Pointer to fast transition ie parameter
15859 *
15860 * Return: 0 for success, non-zero for failure
15861 */
15862static int
15863wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15864 struct net_device *dev,
15865 struct cfg80211_update_ft_ies_params *ftie)
15866{
15867 int ret;
15868
15869 cds_ssr_protect(__func__);
15870 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15871 cds_ssr_unprotect(__func__);
15872
15873 return ret;
15874}
15875#endif
15876
Mukul Sharma3d36c392017-01-18 18:39:12 +053015877void wlan_hdd_cfg80211_update_replay_counter_callback(
15878 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15879
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015880{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015881 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15882 uint8_t temp_replay_counter[8];
15883 int i;
15884 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015885
15886 ENTER();
15887
Mukul Sharma3d36c392017-01-18 18:39:12 +053015888 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015889 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015890 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015891 }
15892
Mukul Sharma3d36c392017-01-18 18:39:12 +053015893 if (!gtk_rsp_param) {
15894 hdd_err("gtk_rsp_param is Null");
15895 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015896 }
15897
Mukul Sharma3d36c392017-01-18 18:39:12 +053015898 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015899 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015900 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015901 }
15902
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015903 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015904 gtk_rsp_param->replay_counter);
15905 /* convert little to big endian since supplicant works on big endian */
15906 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15907 for (i = 0; i < 8; i++)
15908 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015909
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015910 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015911 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015912 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015913 gtk_rsp_param->bssid.bytes,
15914 temp_replay_counter, GFP_KERNEL);
15915out:
15916 EXIT();
15917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015918}
15919
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015920static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015921int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015922 struct net_device *dev,
15923 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015924{
15925 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015926 int result, i;
15927 struct pmo_gtk_req *gtk_req = NULL;
15928 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15929 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015930 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015931
15932 ENTER();
15933
Anurag Chouhan6d760662016-02-20 16:05:43 +053015934 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015935 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015936 result = -EINVAL;
15937 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015938 }
15939
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015940 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15941 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015942 result = -EINVAL;
15943 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015944 }
15945
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015946 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015947 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15948 pAdapter->sessionId, pAdapter->device_mode));
15949
Mukul Sharma3d36c392017-01-18 18:39:12 +053015950 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015951 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015952 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015953
Mukul Sharma3d36c392017-01-18 18:39:12 +053015954 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15955 if (!gtk_req) {
15956 hdd_err("cannot allocate gtk_req");
15957 result = -ENOMEM;
15958 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015959 }
15960
Mukul Sharma3d36c392017-01-18 18:39:12 +053015961 /* convert big to little endian since driver work on little endian */
15962 buf = (uint8_t *)&gtk_req->replay_counter;
15963 for (i = 0; i < 8; i++)
15964 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015966 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015967 gtk_req->replay_counter);
15968 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15969 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15970 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15971 if (status != QDF_STATUS_SUCCESS) {
15972 hdd_err("Failed to cache GTK Offload");
15973 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015974 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015975out:
15976 if (gtk_req)
15977 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015978 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015979
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015980 return result;
15981}
15982
15983/**
15984 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15985 * @wiphy: Pointer to wiphy
15986 * @dev: Pointer to network device
15987 * @data: Pointer to rekey data
15988 *
15989 * This function is used to offload GTK rekeying job to the firmware.
15990 *
15991 * Return: 0 for success, non-zero for failure
15992 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015993static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015994int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15995 struct net_device *dev,
15996 struct cfg80211_gtk_rekey_data *data)
15997{
15998 int ret;
15999
16000 cds_ssr_protect(__func__);
16001 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16002 cds_ssr_unprotect(__func__);
16003
16004 return ret;
16005}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006
16007/**
16008 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16009 * @wiphy: Pointer to wiphy
16010 * @dev: Pointer to network device
16011 * @param: Pointer to access control parameter
16012 *
16013 * Return: 0 for success, non-zero for failure
16014 */
16015static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16016 struct net_device *dev,
16017 const struct cfg80211_acl_data *params)
16018{
16019 int i;
16020 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16021 hdd_hostapd_state_t *pHostapdState;
16022 tsap_Config_t *pConfig;
16023 v_CONTEXT_t p_cds_context = NULL;
16024 hdd_context_t *pHddCtx;
16025 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016026 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016027
16028 ENTER();
16029
Anurag Chouhan6d760662016-02-20 16:05:43 +053016030 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016031 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016032 return -EINVAL;
16033 }
16034
16035 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016036 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016037 return -EINVAL;
16038 }
16039
16040 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16041 status = wlan_hdd_validate_context(pHddCtx);
16042
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016043 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016044 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016045
16046 p_cds_context = pHddCtx->pcds_context;
16047 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16048
16049 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016050 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016051 return -EINVAL;
16052 }
16053
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016054 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016055 params->n_acl_entries);
16056
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016057 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016058 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16059 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016060 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016061 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16062
16063 /* default value */
16064 pConfig->num_accept_mac = 0;
16065 pConfig->num_deny_mac = 0;
16066
16067 /**
16068 * access control policy
16069 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16070 * listed in hostapd.deny file.
16071 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16072 * listed in hostapd.accept file.
16073 */
16074 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16075 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16076 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16077 params->acl_policy) {
16078 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16079 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016080 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016081 params->acl_policy);
16082 return -ENOTSUPP;
16083 }
16084
16085 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16086 pConfig->num_accept_mac = params->n_acl_entries;
16087 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016088 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016089 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016090 MAC_ADDR_ARRAY(
16091 params->mac_addrs[i].addr));
16092
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016093 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016094 params->mac_addrs[i].addr,
16095 sizeof(qcmacaddr));
16096 }
16097 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16098 pConfig->num_deny_mac = params->n_acl_entries;
16099 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016100 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016101 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016102 MAC_ADDR_ARRAY(
16103 params->mac_addrs[i].addr));
16104
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016105 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016106 params->mac_addrs[i].addr,
16107 sizeof(qcmacaddr));
16108 }
16109 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016110 qdf_status = wlansap_set_mac_acl(
16111 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016112 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016113 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016114 return -EINVAL;
16115 }
16116 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016117 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016118 hdd_device_mode_to_string(pAdapter->device_mode),
16119 pAdapter->device_mode);
16120 return -EINVAL;
16121 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016122 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016123 return 0;
16124}
16125
16126/**
16127 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16128 * __wlan_hdd_cfg80211_set_mac_acl
16129 * @wiphy: pointer to wiphy structure
16130 * @dev: pointer to net_device
16131 * @params: pointer to cfg80211_acl_data
16132 *
16133 * Return; 0 on success, error number otherwise
16134 */
16135static int
16136wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16137 struct net_device *dev,
16138 const struct cfg80211_acl_data *params)
16139{
16140 int ret;
16141
16142 cds_ssr_protect(__func__);
16143 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16144 cds_ssr_unprotect(__func__);
16145
16146 return ret;
16147}
16148
16149#ifdef WLAN_NL80211_TESTMODE
16150#ifdef FEATURE_WLAN_LPHB
16151/**
16152 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16153 * @pHddCtx: Pointer to hdd context
16154 * @lphbInd: Pointer to low power heart beat indication parameter
16155 *
16156 * Return: none
16157 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016158static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016159 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160{
16161 struct sk_buff *skb;
16162
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016163 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016164
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016165 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016168 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016169 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016170 return;
16171 }
16172
16173 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016174 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016175 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016176 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016177 return;
16178 }
16179
16180 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016181 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016182 goto nla_put_failure;
16183 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016184 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016185 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016186 goto nla_put_failure;
16187 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016188 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16189 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016190 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016191 goto nla_put_failure;
16192 }
16193 cfg80211_testmode_event(skb, GFP_ATOMIC);
16194 return;
16195
16196nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016197 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016198 kfree_skb(skb);
16199
16200 return;
16201}
16202#endif /* FEATURE_WLAN_LPHB */
16203
16204/**
16205 * __wlan_hdd_cfg80211_testmode() - test mode
16206 * @wiphy: Pointer to wiphy
16207 * @data: Data pointer
16208 * @len: Data length
16209 *
16210 * Return: 0 for success, non-zero for failure
16211 */
16212static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16213 void *data, int len)
16214{
16215 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16216 int err;
16217 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16218
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016219 ENTER();
16220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016221 err = wlan_hdd_validate_context(pHddCtx);
16222 if (err)
16223 return err;
16224
16225 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16226 len, wlan_hdd_tm_policy);
16227 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016228 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016229 return err;
16230 }
16231
16232 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016233 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016234 return -EINVAL;
16235 }
16236
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016237 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016238 TRACE_CODE_HDD_CFG80211_TESTMODE,
16239 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16241#ifdef FEATURE_WLAN_LPHB
16242 /* Low Power Heartbeat configuration request */
16243 case WLAN_HDD_TM_CMD_WLAN_HB:
16244 {
16245 int buf_len;
16246 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016247 struct pmo_lphb_req *hb_params = NULL;
16248 struct pmo_lphb_req *hb_params_temp = NULL;
16249 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250
16251 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016252 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 return -EINVAL;
16254 }
16255
16256 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16257 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16258
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016259 hb_params_temp = (struct pmo_lphb_req *) buf;
16260 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16261 && (hb_params_temp->params.lphb_tcp_params.
16262 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016263 return -EINVAL;
16264
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016265 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16266 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016267 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016268 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269 return -ENOMEM;
16270 }
16271
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016272 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016273 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16274 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016276 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016277 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016278
16279 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016280 return 0;
16281 }
16282#endif /* FEATURE_WLAN_LPHB */
16283
16284#if defined(QCA_WIFI_FTM)
16285 case WLAN_HDD_TM_CMD_WLAN_FTM:
16286 {
16287 int buf_len;
16288 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016289 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016290 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016291 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016292 return -EINVAL;
16293 }
16294
16295 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16296 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16297
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016298 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016299
16300 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16301
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016302 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016303 err = -EBUSY;
16304 break;
16305 }
16306#endif
16307
16308 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016309 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016310 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16311 return -EOPNOTSUPP;
16312 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016313 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016314 return err;
16315}
16316
16317/**
16318 * wlan_hdd_cfg80211_testmode() - test mode
16319 * @wiphy: Pointer to wiphy
16320 * @dev: Pointer to network device
16321 * @data: Data pointer
16322 * @len: Data length
16323 *
16324 * Return: 0 for success, non-zero for failure
16325 */
16326static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16327#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16328 struct wireless_dev *wdev,
16329#endif
16330 void *data, int len)
16331{
16332 int ret;
16333
16334 cds_ssr_protect(__func__);
16335 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16336 cds_ssr_unprotect(__func__);
16337
16338 return ret;
16339}
16340
16341#if defined(QCA_WIFI_FTM)
16342/**
16343 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16344 * @buf: Pointer to buffer
16345 * @buf_len: Buffer length
16346 *
16347 * Return: none
16348 */
16349void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16350{
16351 struct sk_buff *skb;
16352 hdd_context_t *hdd_ctx;
16353
16354 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016355 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016356 return;
16357 }
16358
Anurag Chouhan6d760662016-02-20 16:05:43 +053016359 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016360 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016361 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016362 return;
16363 }
16364
16365 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16366 buf_len, GFP_KERNEL);
16367 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016368 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016369 return;
16370 }
16371
16372 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16373 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16374 goto nla_put_failure;
16375
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016376 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016377
16378 cfg80211_testmode_event(skb, GFP_KERNEL);
16379 return;
16380
16381nla_put_failure:
16382 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016383 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016384}
16385#endif
16386#endif /* CONFIG_NL80211_TESTMODE */
16387
16388#ifdef QCA_HT_2040_COEX
16389/**
16390 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16391 * @wiphy: Pointer to wiphy
16392 * @dev: Pointer to network device
16393 * @chandef: Pointer to channel definition parameter
16394 *
16395 * Return: 0 for success, non-zero for failure
16396 */
16397static int
16398__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16399 struct net_device *dev,
16400 struct cfg80211_chan_def *chandef)
16401{
16402 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16403 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016404 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016406 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016407
Anurag Chouhan6d760662016-02-20 16:05:43 +053016408 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016409 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016410 return -EINVAL;
16411 }
16412
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016413 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16414 hdd_err("invalid session id: %d", pAdapter->sessionId);
16415 return -EINVAL;
16416 }
16417
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016418 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16419 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016420 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016421 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016423 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016424 sme_get_config_param(pHddCtx->hHal, &sme_config);
16425 switch (chandef->width) {
16426 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016427 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016428 if (sme_config.csrConfig.channelBondingMode24GHz !=
16429 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16430 sme_config.csrConfig.channelBondingMode24GHz =
16431 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16432 sme_update_config(pHddCtx->hHal, &sme_config);
16433 cbModeChange = true;
16434 }
16435 break;
16436
16437 case NL80211_CHAN_WIDTH_40:
16438 if (sme_config.csrConfig.channelBondingMode24GHz ==
16439 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16440 if (NL80211_CHAN_HT40MINUS ==
16441 cfg80211_get_chandef_type(chandef))
16442 sme_config.csrConfig.channelBondingMode24GHz =
16443 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16444 else
16445 sme_config.csrConfig.channelBondingMode24GHz =
16446 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16447 sme_update_config(pHddCtx->hHal, &sme_config);
16448 cbModeChange = true;
16449 }
16450 break;
16451
16452 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016453 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016454 return -EINVAL;
16455 }
16456
16457 if (!cbModeChange)
16458 return 0;
16459
Krunal Sonib4326f22016-03-10 13:05:51 -080016460 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016461 return 0;
16462
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016463 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016464 sme_config.csrConfig.channelBondingMode24GHz);
16465
16466 /* Change SAP ht2040 mode */
16467 status = hdd_set_sap_ht2040_mode(pAdapter,
16468 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016469 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016470 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016471 return -EINVAL;
16472 }
16473
16474 return 0;
16475}
16476
16477/**
16478 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16479 * @wiphy: Pointer to wiphy
16480 * @dev: Pointer to network device
16481 * @chandef: Pointer to channel definition parameter
16482 *
16483 * Return: 0 for success, non-zero for failure
16484 */
16485static int
16486wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16487 struct net_device *dev,
16488 struct cfg80211_chan_def *chandef)
16489{
16490 int ret;
16491
16492 cds_ssr_protect(__func__);
16493 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16494 cds_ssr_unprotect(__func__);
16495
16496 return ret;
16497}
16498#endif
16499
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016500#ifdef CHANNEL_SWITCH_SUPPORTED
16501/**
16502 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16503 * channel in SAP/GO
16504 * @wiphy: wiphy pointer
16505 * @dev: dev pointer.
16506 * @csa_params: Change channel params
16507 *
16508 * This function is called to switch channel in SAP/GO
16509 *
16510 * Return: 0 if success else return non zero
16511 */
16512static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16513 struct net_device *dev,
16514 struct cfg80211_csa_settings *csa_params)
16515{
16516 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16517 hdd_context_t *hdd_ctx;
16518 uint8_t channel;
16519 uint16_t freq;
16520 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016521 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016522
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016523 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016524 csa_params->chandef.chan->center_freq);
16525
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016526 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16527 hdd_err("invalid session id: %d", adapter->sessionId);
16528 return -EINVAL;
16529 }
16530
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016531 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16532 ret = wlan_hdd_validate_context(hdd_ctx);
16533
16534 if (0 != ret)
16535 return ret;
16536
Krunal Sonib4326f22016-03-10 13:05:51 -080016537 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16538 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016539 return -ENOTSUPP;
16540
16541 freq = csa_params->chandef.chan->center_freq;
16542 channel = cds_freq_to_chan(freq);
16543
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016544 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16545
16546 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016547 return ret;
16548}
16549
16550/**
16551 * wlan_hdd_cfg80211_channel_switch()- function to switch
16552 * channel in SAP/GO
16553 * @wiphy: wiphy pointer
16554 * @dev: dev pointer.
16555 * @csa_params: Change channel params
16556 *
16557 * This function is called to switch channel in SAP/GO
16558 *
16559 * Return: 0 if success else return non zero
16560 */
16561static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16562 struct net_device *dev,
16563 struct cfg80211_csa_settings *csa_params)
16564{
16565 int ret;
16566
16567 cds_ssr_protect(__func__);
16568 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16569 cds_ssr_unprotect(__func__);
16570 return ret;
16571}
16572#endif
16573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016574/**
16575 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16576 * translation from NL to policy manager type
16577 * @type: Generic connection mode type defined in NL
16578 *
16579 *
16580 * This function provides the type translation
16581 *
16582 * Return: cds_con_mode enum
16583 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016584enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016585 enum nl80211_iftype type)
16586{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016587 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016588 switch (type) {
16589 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016590 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016591 break;
16592 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016593 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016594 break;
16595 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016596 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016597 break;
16598 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016599 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016600 break;
16601 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016602 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016603 break;
16604 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016605 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016606 }
16607 return mode;
16608}
16609
16610/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016611 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16612 * @wiphy: Handle to struct wiphy to get handle to module context.
16613 * @chandef: Contains information about the capture channel to be set.
16614 *
16615 * This interface is called if and only if monitor mode interface alone is
16616 * active.
16617 *
16618 * Return: 0 success or error code on failure.
16619 */
16620static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16621 struct cfg80211_chan_def *chandef)
16622{
16623 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16624 hdd_adapter_t *adapter;
16625 hdd_station_ctx_t *sta_ctx;
16626 struct hdd_mon_set_ch_info *ch_info;
16627 QDF_STATUS status;
16628 tHalHandle hal_hdl;
16629 struct qdf_mac_addr bssid;
16630 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016631 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016632 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016633 int ret;
16634 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16635
16636 ENTER();
16637
16638 ret = wlan_hdd_validate_context(hdd_ctx);
16639 if (ret)
16640 return ret;
16641
16642 hal_hdl = hdd_ctx->hHal;
16643
16644 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16645 if (!adapter)
16646 return -EIO;
16647
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016648 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016649 adapter->dev->name, chan_num, chandef->chan->center_freq);
16650
16651 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16652 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016653 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16654 roam_profile.ChannelInfo.numOfChannels = 1;
16655 roam_profile.phyMode = ch_info->phy_mode;
16656 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016657 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016658
16659 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16660 QDF_MAC_ADDR_SIZE);
16661
16662 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016663 /*
16664 * CDS api expects secondary channel for calculating
16665 * the channel params
16666 */
16667 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016668 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016669 if (chan_num >= 1 && chan_num <= 5)
16670 sec_ch = chan_num + 4;
16671 else if (chan_num >= 6 && chan_num <= 13)
16672 sec_ch = chan_num - 4;
16673 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016674 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16675 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016676 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16677 &roam_profile);
16678 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016679 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016680 status);
16681 ret = qdf_status_to_os_return(status);
16682 return ret;
16683 }
16684 EXIT();
16685 return 0;
16686}
16687
16688/**
16689 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16690 * @wiphy: Handle to struct wiphy to get handle to module context.
16691 * @chandef: Contains information about the capture channel to be set.
16692 *
16693 * This interface is called if and only if monitor mode interface alone is
16694 * active.
16695 *
16696 * Return: 0 success or error code on failure.
16697 */
16698static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16699 struct cfg80211_chan_def *chandef)
16700{
16701 int ret;
16702
16703 cds_ssr_protect(__func__);
16704 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16705 cds_ssr_unprotect(__func__);
16706 return ret;
16707}
16708
16709/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016710 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16711 * @adapter: pointer to adapter
16712 *
16713 * Wrapper function to clear link layer stats.
16714 * return - void
16715 */
16716void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16717{
16718 tSirLLStatsClearReq link_layer_stats_clear_req;
16719 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16720
Mukul Sharma491021c2016-09-29 21:39:19 +053016721 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16722 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016723 link_layer_stats_clear_req.stopReq = 0;
16724 link_layer_stats_clear_req.reqId = 1;
16725 link_layer_stats_clear_req.staId = adapter->sessionId;
16726 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16727
16728 return;
16729}
16730
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016731/**
16732 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16733 * @adapter: HDD Adapter
16734 *
16735 * If roaming is in progress and there is a request to
16736 * disconnect the session, then it is deferred. Once
16737 * roaming is complete/aborted, then this routine is
16738 * used to resume the disconnect that was deferred
16739 *
16740 * Return: None
16741 */
16742void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16743{
16744 switch (adapter->defer_disconnect) {
16745 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16746 adapter->defer_disconnect = 0;
16747 wlan_hdd_disconnect(adapter,
16748 adapter->cfg80211_disconnect_reason);
16749 break;
16750 case DEFER_DISCONNECT_TRY_DISCONNECT:
16751 wlan_hdd_try_disconnect(adapter);
16752 adapter->defer_disconnect = 0;
16753 break;
16754 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016755 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016756 adapter->defer_disconnect);
16757 break;
16758 }
16759}
16760
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016761#define CNT_DIFF(cur, prev) \
16762 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16763#define MAX_COUNT 0xffffffff
16764static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16765 struct scan_chan_info *chan,
16766 struct scan_chan_info *info, uint32_t cmd_flag)
16767{
16768 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16769 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16770 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16771
16772 mutex_lock(&hdd_ctx->chan_info_lock);
16773
16774 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16775 qdf_mem_zero(chan, sizeof(*chan));
16776
16777 chan->freq = info->freq;
16778 chan->noise_floor = info->noise_floor;
16779 chan->clock_freq = info->clock_freq;
16780 chan->cmd_flag = info->cmd_flag;
16781 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16782
16783 chan->rx_clear_count =
16784 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16785
16786 chan->tx_frame_count =
16787 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16788
16789 mutex_unlock(&hdd_ctx->chan_info_lock);
16790
16791}
16792#undef CNT_DIFF
16793#undef MAX_COUNT
16794
16795/**
16796 * wlan_hdd_chan_info_cb() - channel info callback
16797 * @chan_info: struct scan_chan_info
16798 *
16799 * Store channel info into HDD context
16800 *
16801 * Return: None.
16802 */
16803static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16804{
16805 hdd_context_t *hdd_ctx;
16806 struct scan_chan_info *chan;
16807 uint8_t idx;
16808
16809 ENTER();
16810
16811 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16812 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16813 hdd_err("hdd_ctx is invalid");
16814 return;
16815 }
16816
16817 if (!hdd_ctx->chan_info) {
16818 hdd_err("chan_info is NULL");
16819 return;
16820 }
16821
16822 chan = hdd_ctx->chan_info;
16823 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16824 if (chan[idx].freq == info->freq) {
16825 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16826 info->cmd_flag);
16827 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16828 chan[idx].cmd_flag, chan[idx].freq,
16829 chan[idx].noise_floor,
16830 chan[idx].cycle_count, chan[idx].rx_clear_count,
16831 chan[idx].clock_freq, chan[idx].cmd_flag,
16832 chan[idx].tx_frame_count, idx);
16833 if (chan[idx].freq == 0)
16834 break;
16835
16836 }
16837 }
16838
16839 EXIT();
16840}
16841
16842/**
16843 * wlan_hdd_init_chan_info() - init chan info in hdd context
16844 * @hdd_ctx: HDD context pointer
16845 *
16846 * Return: none
16847 */
16848void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16849{
16850 uint8_t num_2g, num_5g, index = 0;
16851
16852 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16853 hdd_info("SNR monitoring is disabled");
16854 return;
16855 }
16856
16857 hdd_ctx->chan_info =
16858 qdf_mem_malloc(sizeof(struct scan_chan_info)
16859 * QDF_MAX_NUM_CHAN);
16860 if (hdd_ctx->chan_info == NULL) {
16861 hdd_err("Failed to malloc for chan info");
16862 return;
16863 }
16864 mutex_init(&hdd_ctx->chan_info_lock);
16865
16866 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16867 for (; index < num_2g; index++) {
16868 hdd_ctx->chan_info[index].freq =
16869 hdd_channels_2_4_ghz[index].center_freq;
16870 }
16871
16872 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16873 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016874 if (WLAN_REG_IS_11P_CH(
16875 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016876 continue;
16877 hdd_ctx->chan_info[index].freq =
16878 hdd_channels_5_ghz[index - num_2g].center_freq;
16879 }
16880 sme_set_chan_info_callback(hdd_ctx->hHal,
16881 &wlan_hdd_chan_info_cb);
16882}
16883
16884/**
16885 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16886 * @hdd_ctx: hdd context pointer
16887 *
16888 * Return: none
16889 */
16890void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16891{
16892 struct scan_chan_info *chan;
16893
16894 chan = hdd_ctx->chan_info;
16895 hdd_ctx->chan_info = NULL;
16896 if (chan)
16897 qdf_mem_free(chan);
16898}
16899
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016900/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016901 * struct cfg80211_ops - cfg80211_ops
16902 *
16903 * @add_virtual_intf: Add virtual interface
16904 * @del_virtual_intf: Delete virtual interface
16905 * @change_virtual_intf: Change virtual interface
16906 * @change_station: Change station
16907 * @add_beacon: Add beacon in sap mode
16908 * @del_beacon: Delete beacon in sap mode
16909 * @set_beacon: Set beacon in sap mode
16910 * @start_ap: Start ap
16911 * @change_beacon: Change beacon
16912 * @stop_ap: Stop ap
16913 * @change_bss: Change bss
16914 * @add_key: Add key
16915 * @get_key: Get key
16916 * @del_key: Delete key
16917 * @set_default_key: Set default key
16918 * @set_channel: Set channel
16919 * @scan: Scan
16920 * @connect: Connect
16921 * @disconnect: Disconnect
16922 * @join_ibss = Join ibss
16923 * @leave_ibss = Leave ibss
16924 * @set_wiphy_params = Set wiphy params
16925 * @set_tx_power = Set tx power
16926 * @get_tx_power = get tx power
16927 * @remain_on_channel = Remain on channel
16928 * @cancel_remain_on_channel = Cancel remain on channel
16929 * @mgmt_tx = Tx management frame
16930 * @mgmt_tx_cancel_wait = Cancel management tx wait
16931 * @set_default_mgmt_key = Set default management key
16932 * @set_txq_params = Set tx queue parameters
16933 * @get_station = Get station
16934 * @set_power_mgmt = Set power management
16935 * @del_station = Delete station
16936 * @add_station = Add station
16937 * @set_pmksa = Set pmksa
16938 * @del_pmksa = Delete pmksa
16939 * @flush_pmksa = Flush pmksa
16940 * @update_ft_ies = Update FT IEs
16941 * @tdls_mgmt = Tdls management
16942 * @tdls_oper = Tdls operation
16943 * @set_rekey_data = Set rekey data
16944 * @sched_scan_start = Scheduled scan start
16945 * @sched_scan_stop = Scheduled scan stop
16946 * @resume = Resume wlan
16947 * @suspend = Suspend wlan
16948 * @set_mac_acl = Set mac acl
16949 * @testmode_cmd = Test mode command
16950 * @set_ap_chanwidth = Set AP channel bandwidth
16951 * @dump_survey = Dump survey
16952 * @key_mgmt_set_pmk = Set pmk key management
16953 */
16954static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16955 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16956 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16957 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16958 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016959 .start_ap = wlan_hdd_cfg80211_start_ap,
16960 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16961 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016962 .change_bss = wlan_hdd_cfg80211_change_bss,
16963 .add_key = wlan_hdd_cfg80211_add_key,
16964 .get_key = wlan_hdd_cfg80211_get_key,
16965 .del_key = wlan_hdd_cfg80211_del_key,
16966 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16967 .scan = wlan_hdd_cfg80211_scan,
16968 .connect = wlan_hdd_cfg80211_connect,
16969 .disconnect = wlan_hdd_cfg80211_disconnect,
16970 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16971 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16972 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16973 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16974 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16975 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16976 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16977 .mgmt_tx = wlan_hdd_mgmt_tx,
16978 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16979 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16980 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016981 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016982 .get_station = wlan_hdd_cfg80211_get_station,
16983 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16984 .del_station = wlan_hdd_cfg80211_del_station,
16985 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016986 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16987 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16988 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016989#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016990 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16991#endif
16992#ifdef FEATURE_WLAN_TDLS
16993 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16994 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16995#endif
16996#ifdef WLAN_FEATURE_GTK_OFFLOAD
16997 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16998#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16999#ifdef FEATURE_WLAN_SCAN_PNO
17000 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17001 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17002#endif /*FEATURE_WLAN_SCAN_PNO */
17003 .resume = wlan_hdd_cfg80211_resume_wlan,
17004 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17005 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17006#ifdef WLAN_NL80211_TESTMODE
17007 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17008#endif
17009#ifdef QCA_HT_2040_COEX
17010 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17011#endif
17012 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017013#ifdef CHANNEL_SWITCH_SUPPORTED
17014 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17015#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017016 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017017#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17018 defined(CFG80211_ABORT_SCAN)
17019 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17020#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017021};