blob: 18663bb28077113eb6dbb379d3af0a45c4b29d6c [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Paul Zhang3a210c52016-12-08 10:18:12 +080077#ifdef WLAN_UMAC_CONVERGENCE
78#include "wlan_cfg80211.h"
79#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080080#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080081#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082
83#ifdef FEATURE_WLAN_EXTSCAN
84#include "wlan_hdd_ext_scan.h"
85#endif
86
87#ifdef WLAN_FEATURE_LINK_LAYER_STATS
88#include "wlan_hdd_stats.h"
89#endif
90#include "cds_concurrency.h"
91#include "qwlan_version.h"
92#include "wlan_hdd_memdump.h"
93
94#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070095#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053098#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070099#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700100#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530101#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800102#include "wlan_hdd_request_manager.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800103
Leo Changfdb45c32016-10-28 11:09:23 -0700104#include <cdp_txrx_cmn.h>
105#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800106#include <qca_vendor.h>
107
Leo Changfdb45c32016-10-28 11:09:23 -0700108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800109#define g_mode_rates_size (12)
110#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
112 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
113
114/*
115 * Android CTS verifier needs atleast this much wait time (in msec)
116 */
117#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
118
119/*
120 * Refer @tCfgProtection structure for definition of the bit map.
121 * below value is obtained by setting the following bit-fields.
122 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
123 */
124#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
125
126#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700127 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128 .center_freq = (freq), \
129 .hw_value = (chan), \
130 .flags = (flag), \
131 .max_antenna_gain = 0, \
132 .max_power = 30, \
133}
134
135#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700136 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800137 .center_freq = (freq), \
138 .hw_value = (chan), \
139 .flags = (flag), \
140 .max_antenna_gain = 0, \
141 .max_power = 30, \
142}
143
144#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
145 { \
146 .bitrate = rate, \
147 .hw_value = rate_id, \
148 .flags = flag, \
149 }
150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
152#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153
154#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155
Agrawal Ashish65634612016-08-18 13:24:32 +0530156#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
157 mode <= DFS_MODE_DEPRIORITIZE))
158#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
159 || (channel >= 36 && channel <= 184))
160
Peng Xu4d67c8f2015-10-16 16:02:26 -0700161#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530162#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164static const u32 hdd_cipher_suites[] = {
165 WLAN_CIPHER_SUITE_WEP40,
166 WLAN_CIPHER_SUITE_WEP104,
167 WLAN_CIPHER_SUITE_TKIP,
168#ifdef FEATURE_WLAN_ESE
169#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
170#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
171 WLAN_CIPHER_SUITE_BTK,
172 WLAN_CIPHER_SUITE_KRK,
173 WLAN_CIPHER_SUITE_CCMP,
174#else
175 WLAN_CIPHER_SUITE_CCMP,
176#endif
177#ifdef FEATURE_WLAN_WAPI
178 WLAN_CIPHER_SUITE_SMS4,
179#endif
180#ifdef WLAN_FEATURE_11W
181 WLAN_CIPHER_SUITE_AES_CMAC,
182#endif
183};
184
Abhishek Singhf512bf32016-05-04 16:47:46 +0530185static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186 HDD2GHZCHAN(2412, 1, 0),
187 HDD2GHZCHAN(2417, 2, 0),
188 HDD2GHZCHAN(2422, 3, 0),
189 HDD2GHZCHAN(2427, 4, 0),
190 HDD2GHZCHAN(2432, 5, 0),
191 HDD2GHZCHAN(2437, 6, 0),
192 HDD2GHZCHAN(2442, 7, 0),
193 HDD2GHZCHAN(2447, 8, 0),
194 HDD2GHZCHAN(2452, 9, 0),
195 HDD2GHZCHAN(2457, 10, 0),
196 HDD2GHZCHAN(2462, 11, 0),
197 HDD2GHZCHAN(2467, 12, 0),
198 HDD2GHZCHAN(2472, 13, 0),
199 HDD2GHZCHAN(2484, 14, 0),
200};
201
Abhishek Singhf512bf32016-05-04 16:47:46 +0530202static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203 HDD5GHZCHAN(5180, 36, 0),
204 HDD5GHZCHAN(5200, 40, 0),
205 HDD5GHZCHAN(5220, 44, 0),
206 HDD5GHZCHAN(5240, 48, 0),
207 HDD5GHZCHAN(5260, 52, 0),
208 HDD5GHZCHAN(5280, 56, 0),
209 HDD5GHZCHAN(5300, 60, 0),
210 HDD5GHZCHAN(5320, 64, 0),
211 HDD5GHZCHAN(5500, 100, 0),
212 HDD5GHZCHAN(5520, 104, 0),
213 HDD5GHZCHAN(5540, 108, 0),
214 HDD5GHZCHAN(5560, 112, 0),
215 HDD5GHZCHAN(5580, 116, 0),
216 HDD5GHZCHAN(5600, 120, 0),
217 HDD5GHZCHAN(5620, 124, 0),
218 HDD5GHZCHAN(5640, 128, 0),
219 HDD5GHZCHAN(5660, 132, 0),
220 HDD5GHZCHAN(5680, 136, 0),
221 HDD5GHZCHAN(5700, 140, 0),
222 HDD5GHZCHAN(5720, 144, 0),
223 HDD5GHZCHAN(5745, 149, 0),
224 HDD5GHZCHAN(5765, 153, 0),
225 HDD5GHZCHAN(5785, 157, 0),
226 HDD5GHZCHAN(5805, 161, 0),
227 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 HDD5GHZCHAN(5852, 170, 0),
229 HDD5GHZCHAN(5855, 171, 0),
230 HDD5GHZCHAN(5860, 172, 0),
231 HDD5GHZCHAN(5865, 173, 0),
232 HDD5GHZCHAN(5870, 174, 0),
233 HDD5GHZCHAN(5875, 175, 0),
234 HDD5GHZCHAN(5880, 176, 0),
235 HDD5GHZCHAN(5885, 177, 0),
236 HDD5GHZCHAN(5890, 178, 0),
237 HDD5GHZCHAN(5895, 179, 0),
238 HDD5GHZCHAN(5900, 180, 0),
239 HDD5GHZCHAN(5905, 181, 0),
240 HDD5GHZCHAN(5910, 182, 0),
241 HDD5GHZCHAN(5915, 183, 0),
242 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800243};
244
245static struct ieee80211_rate g_mode_rates[] = {
246 HDD_G_MODE_RATETAB(10, 0x1, 0),
247 HDD_G_MODE_RATETAB(20, 0x2, 0),
248 HDD_G_MODE_RATETAB(55, 0x4, 0),
249 HDD_G_MODE_RATETAB(110, 0x8, 0),
250 HDD_G_MODE_RATETAB(60, 0x10, 0),
251 HDD_G_MODE_RATETAB(90, 0x20, 0),
252 HDD_G_MODE_RATETAB(120, 0x40, 0),
253 HDD_G_MODE_RATETAB(180, 0x80, 0),
254 HDD_G_MODE_RATETAB(240, 0x100, 0),
255 HDD_G_MODE_RATETAB(360, 0x200, 0),
256 HDD_G_MODE_RATETAB(480, 0x400, 0),
257 HDD_G_MODE_RATETAB(540, 0x800, 0),
258};
259
260static struct ieee80211_rate a_mode_rates[] = {
261 HDD_G_MODE_RATETAB(60, 0x10, 0),
262 HDD_G_MODE_RATETAB(90, 0x20, 0),
263 HDD_G_MODE_RATETAB(120, 0x40, 0),
264 HDD_G_MODE_RATETAB(180, 0x80, 0),
265 HDD_G_MODE_RATETAB(240, 0x100, 0),
266 HDD_G_MODE_RATETAB(360, 0x200, 0),
267 HDD_G_MODE_RATETAB(480, 0x400, 0),
268 HDD_G_MODE_RATETAB(540, 0x800, 0),
269};
270
271static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530272 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700274 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275 .bitrates = g_mode_rates,
276 .n_bitrates = g_mode_rates_size,
277 .ht_cap.ht_supported = 1,
278 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
279 | IEEE80211_HT_CAP_GRN_FLD
280 | IEEE80211_HT_CAP_DSSSCCK40
281 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
282 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
283 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
284 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
285 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
286 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
287 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
288};
289
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530291 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700293 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294 .bitrates = a_mode_rates,
295 .n_bitrates = a_mode_rates_size,
296 .ht_cap.ht_supported = 1,
297 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
298 | IEEE80211_HT_CAP_GRN_FLD
299 | IEEE80211_HT_CAP_DSSSCCK40
300 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
301 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
302 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
303 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
304 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
305 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
306 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
307 .vht_cap.vht_supported = 1,
308};
309
310/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800311 * TX/RX direction for each kind of interface
312 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800313static const struct ieee80211_txrx_stypes
314 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
315 [NL80211_IFTYPE_STATION] = {
316 .tx = 0xffff,
317 .rx = BIT(SIR_MAC_MGMT_ACTION) |
318 BIT(SIR_MAC_MGMT_PROBE_REQ),
319 },
320 [NL80211_IFTYPE_AP] = {
321 .tx = 0xffff,
322 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
323 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ) |
325 BIT(SIR_MAC_MGMT_DISASSOC) |
326 BIT(SIR_MAC_MGMT_AUTH) |
327 BIT(SIR_MAC_MGMT_DEAUTH) |
328 BIT(SIR_MAC_MGMT_ACTION),
329 },
330 [NL80211_IFTYPE_ADHOC] = {
331 .tx = 0xffff,
332 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
333 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
334 BIT(SIR_MAC_MGMT_PROBE_REQ) |
335 BIT(SIR_MAC_MGMT_DISASSOC) |
336 BIT(SIR_MAC_MGMT_AUTH) |
337 BIT(SIR_MAC_MGMT_DEAUTH) |
338 BIT(SIR_MAC_MGMT_ACTION),
339 },
340 [NL80211_IFTYPE_P2P_CLIENT] = {
341 .tx = 0xffff,
342 .rx = BIT(SIR_MAC_MGMT_ACTION) |
343 BIT(SIR_MAC_MGMT_PROBE_REQ),
344 },
345 [NL80211_IFTYPE_P2P_GO] = {
346 /* This is also same as for SoftAP */
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
349 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
350 BIT(SIR_MAC_MGMT_PROBE_REQ) |
351 BIT(SIR_MAC_MGMT_DISASSOC) |
352 BIT(SIR_MAC_MGMT_AUTH) |
353 BIT(SIR_MAC_MGMT_DEAUTH) |
354 BIT(SIR_MAC_MGMT_ACTION),
355 },
356};
357
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800358/* Interface limits and combinations registered by the driver */
359
360/* STA ( + STA ) combination */
361static const struct ieee80211_iface_limit
362 wlan_hdd_sta_iface_limit[] = {
363 {
364 .max = 3, /* p2p0 is a STA as well */
365 .types = BIT(NL80211_IFTYPE_STATION),
366 },
367};
368
369/* ADHOC (IBSS) limit */
370static const struct ieee80211_iface_limit
371 wlan_hdd_adhoc_iface_limit[] = {
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_STATION),
375 },
376 {
377 .max = 1,
378 .types = BIT(NL80211_IFTYPE_ADHOC),
379 },
380};
381
382/* AP ( + AP ) combination */
383static const struct ieee80211_iface_limit
384 wlan_hdd_ap_iface_limit[] = {
385 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530386 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 .types = BIT(NL80211_IFTYPE_AP),
388 },
389};
390
391/* P2P limit */
392static const struct ieee80211_iface_limit
393 wlan_hdd_p2p_iface_limit[] = {
394 {
395 .max = 1,
396 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
397 },
398 {
399 .max = 1,
400 .types = BIT(NL80211_IFTYPE_P2P_GO),
401 },
402};
403
404static const struct ieee80211_iface_limit
405 wlan_hdd_sta_ap_iface_limit[] = {
406 {
407 /* We need 1 extra STA interface for OBSS scan when SAP starts
408 * with HT40 in STA+SAP concurrency mode
409 */
410 .max = (1 + SAP_MAX_OBSS_STA_CNT),
411 .types = BIT(NL80211_IFTYPE_STATION),
412 },
413 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530414 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 .types = BIT(NL80211_IFTYPE_AP),
416 },
417};
418
419/* STA + P2P combination */
420static const struct ieee80211_iface_limit
421 wlan_hdd_sta_p2p_iface_limit[] = {
422 {
423 /* One reserved for dedicated P2PDEV usage */
424 .max = 2,
425 .types = BIT(NL80211_IFTYPE_STATION)
426 },
427 {
428 /* Support for two identical (GO + GO or CLI + CLI)
429 * or dissimilar (GO + CLI) P2P interfaces
430 */
431 .max = 2,
432 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
433 },
434};
435
436/* STA + AP + P2PGO combination */
437static const struct ieee80211_iface_limit
438wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
439 /* Support for AP+P2PGO interfaces */
440 {
441 .max = 2,
442 .types = BIT(NL80211_IFTYPE_STATION)
443 },
444 {
445 .max = 1,
446 .types = BIT(NL80211_IFTYPE_P2P_GO)
447 },
448 {
449 .max = 1,
450 .types = BIT(NL80211_IFTYPE_AP)
451 }
452};
453
454/* SAP + P2P combination */
455static const struct ieee80211_iface_limit
456wlan_hdd_sap_p2p_iface_limit[] = {
457 {
458 /* 1 dedicated for p2p0 which is a STA type */
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_STATION)
461 },
462 {
463 /* The p2p interface in SAP+P2P can be GO/CLI.
464 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
465 */
466 .max = 1,
467 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
468 },
469 {
470 /* SAP+GO to support only one SAP interface */
471 .max = 1,
472 .types = BIT(NL80211_IFTYPE_AP)
473 }
474};
475
476/* P2P + P2P combination */
477static const struct ieee80211_iface_limit
478wlan_hdd_p2p_p2p_iface_limit[] = {
479 {
480 /* 1 dedicated for p2p0 which is a STA type */
481 .max = 1,
482 .types = BIT(NL80211_IFTYPE_STATION)
483 },
484 {
485 /* The p2p interface in P2P+P2P can be GO/CLI.
486 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
487 */
488 .max = 2,
489 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
490 },
491};
492
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700493static const struct ieee80211_iface_limit
494 wlan_hdd_mon_iface_limit[] = {
495 {
496 .max = 3, /* Monitor interface */
497 .types = BIT(NL80211_IFTYPE_MONITOR),
498 },
499};
500
501static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502 wlan_hdd_iface_combination[] = {
503 /* STA */
504 {
505 .limits = wlan_hdd_sta_iface_limit,
506 .num_different_channels = 2,
507 .max_interfaces = 3,
508 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
509 },
510 /* ADHOC */
511 {
512 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700513 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800514 .max_interfaces = 2,
515 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
516 },
517 /* AP */
518 {
519 .limits = wlan_hdd_ap_iface_limit,
520 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530521 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
523 },
524 /* P2P */
525 {
526 .limits = wlan_hdd_p2p_iface_limit,
527 .num_different_channels = 2,
528 .max_interfaces = 2,
529 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
530 },
531 /* STA + AP */
532 {
533 .limits = wlan_hdd_sta_ap_iface_limit,
534 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530535 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
537 .beacon_int_infra_match = true,
538 },
539 /* STA + P2P */
540 {
541 .limits = wlan_hdd_sta_p2p_iface_limit,
542 .num_different_channels = 2,
543 /* one interface reserved for P2PDEV dedicated usage */
544 .max_interfaces = 4,
545 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
546 .beacon_int_infra_match = true,
547 },
548 /* STA + P2P GO + SAP */
549 {
550 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
551 /* we can allow 3 channels for three different persona
552 * but due to firmware limitation, allow max 2 concrnt channels.
553 */
554 .num_different_channels = 2,
555 /* one interface reserved for P2PDEV dedicated usage */
556 .max_interfaces = 4,
557 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
558 .beacon_int_infra_match = true,
559 },
560 /* SAP + P2P */
561 {
562 .limits = wlan_hdd_sap_p2p_iface_limit,
563 .num_different_channels = 2,
564 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
565 .max_interfaces = 3,
566 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
567 .beacon_int_infra_match = true,
568 },
569 /* P2P + P2P */
570 {
571 .limits = wlan_hdd_p2p_p2p_iface_limit,
572 .num_different_channels = 2,
573 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
574 .max_interfaces = 3,
575 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
576 .beacon_int_infra_match = true,
577 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530578 /* Monitor */
579 {
580 .limits = wlan_hdd_mon_iface_limit,
581 .max_interfaces = 3,
582 .num_different_channels = 2,
583 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
584 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586
587static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588
589#ifdef WLAN_NL80211_TESTMODE
590enum wlan_hdd_tm_attr {
591 WLAN_HDD_TM_ATTR_INVALID = 0,
592 WLAN_HDD_TM_ATTR_CMD = 1,
593 WLAN_HDD_TM_ATTR_DATA = 2,
594 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
595 WLAN_HDD_TM_ATTR_TYPE = 4,
596 /* keep last */
597 WLAN_HDD_TM_ATTR_AFTER_LAST,
598 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
599};
600
601enum wlan_hdd_tm_cmd {
602 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
603 WLAN_HDD_TM_CMD_WLAN_HB = 1,
604};
605
606#define WLAN_HDD_TM_DATA_MAX_LEN 5000
607
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530608enum wlan_hdd_vendor_ie_access_policy {
609 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
610 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
611};
612
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
614 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
615 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
616 .len = WLAN_HDD_TM_DATA_MAX_LEN},
617};
618#endif /* WLAN_NL80211_TESTMODE */
619
620#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
621static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
622 .flags = WIPHY_WOWLAN_MAGIC_PKT,
623 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
624 .pattern_min_len = 1,
625 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
626};
627#endif
628
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530630 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
631 * @flags: Pointer to the flags to Add channel switch flag.
632 *
633 * This Function adds Channel Switch support flag, if channel switch is
634 * supported by kernel.
635 * Return: void.
636 */
637#ifdef CHANNEL_SWITCH_SUPPORTED
638static inline void hdd_add_channel_switch_support(uint32_t *flags)
639{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800640 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530641 return;
642}
643#else
644static inline void hdd_add_channel_switch_support(uint32_t *flags)
645{
646 return;
647}
648#endif
649
Manikandan Mohan22b83722015-12-15 15:03:23 -0800650#ifdef FEATURE_WLAN_TDLS
651
652/* TDLS capabilities params */
653#define PARAM_MAX_TDLS_SESSION \
654 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
655#define PARAM_TDLS_FEATURE_SUPPORT \
656 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
657
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530658/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
660 * @wiphy: WIPHY structure pointer
661 * @wdev: Wireless device structure pointer
662 * @data: Pointer to the data received
663 * @data_len: Length of the data received
664 *
665 * This function provides TDLS capabilities
666 *
667 * Return: 0 on success and errno on failure
668 */
669static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
670 struct wireless_dev *wdev,
671 const void *data,
672 int data_len)
673{
674 int status;
675 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
676 struct sk_buff *skb;
677 uint32_t set = 0;
678
Jeff Johnson1f61b612016-02-12 16:28:33 -0800679 ENTER_DEV(wdev->netdev);
680
Anurag Chouhan6d760662016-02-20 16:05:43 +0530681 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800682 hdd_err("Command not allowed in FTM mode");
683 return -EPERM;
684 }
685
686 status = wlan_hdd_validate_context(hdd_ctx);
687 if (status)
688 return status;
689
690 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
691 NLMSG_HDRLEN);
692 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700693 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 goto fail;
695 }
696
697 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
700 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700701 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 goto fail;
703 }
704 } else {
705 set = set | WIFI_TDLS_SUPPORT;
706 set = set | (hdd_ctx->config->fTDLSExternalControl ?
707 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
708 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
709 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700710 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
712 hdd_ctx->max_num_tdls_sta) ||
713 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
714 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700715 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 goto fail;
717 }
718 }
719 return cfg80211_vendor_cmd_reply(skb);
720fail:
721 if (skb)
722 kfree_skb(skb);
723 return -EINVAL;
724}
725
726/**
727 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
728 * @wiphy: WIPHY structure pointer
729 * @wdev: Wireless device structure pointer
730 * @data: Pointer to the data received
731 * @data_len: Length of the data received
732 *
733 * This function provides TDLS capabilities
734 *
735 * Return: 0 on success and errno on failure
736 */
737static int
738wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
739 struct wireless_dev *wdev,
740 const void *data,
741 int data_len)
742{
743 int ret;
744
745 cds_ssr_protect(__func__);
746 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
747 data, data_len);
748 cds_ssr_unprotect(__func__);
749
750 return ret;
751}
752#endif
753
754#ifdef QCA_HT_2040_COEX
755static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
756#endif
757
758#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
759/*
760 * FUNCTION: wlan_hdd_send_avoid_freq_event
761 * This is called when wlan driver needs to send vendor specific
762 * avoid frequency range event to userspace
763 */
764int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
765 tHddAvoidFreqList *pAvoidFreqList)
766{
767 struct sk_buff *vendor_event;
768
769 ENTER();
770
771 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700772 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 return -EINVAL;
774 }
775
776 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700777 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 return -EINVAL;
779 }
780
781 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
782 NULL,
783 sizeof(tHddAvoidFreqList),
784 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
785 GFP_KERNEL);
786 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700787 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788 return -EINVAL;
789 }
790
791 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
792 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
793
794 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
795
796 EXIT();
797 return 0;
798}
799#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
800
801/* vendor specific events */
802static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
803#ifdef FEATURE_WLAN_CH_AVOID
804 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
805 .vendor_id =
806 QCA_NL80211_VENDOR_ID,
807 .subcmd =
808 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
809 },
810#endif /* FEATURE_WLAN_CH_AVOID */
811
812#ifdef WLAN_FEATURE_NAN
813 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
814 .vendor_id =
815 QCA_NL80211_VENDOR_ID,
816 .subcmd =
817 QCA_NL80211_VENDOR_SUBCMD_NAN
818 },
819#endif
820
821#ifdef WLAN_FEATURE_STATS_EXT
822 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
823 .vendor_id =
824 QCA_NL80211_VENDOR_ID,
825 .subcmd =
826 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
827 },
828#endif /* WLAN_FEATURE_STATS_EXT */
829#ifdef FEATURE_WLAN_EXTSCAN
830 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
831 .vendor_id =
832 QCA_NL80211_VENDOR_ID,
833 .subcmd =
834 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
835 },
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
837 .vendor_id =
838 QCA_NL80211_VENDOR_ID,
839 .subcmd =
840 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
841 },
842 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
843 .
844 vendor_id
845 =
846 QCA_NL80211_VENDOR_ID,
847 .subcmd =
848 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
849 },
850 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
851 .
852 vendor_id
853 =
854 QCA_NL80211_VENDOR_ID,
855 .
856 subcmd =
857 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
858 },
859 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
860 .
861 vendor_id
862 =
863 QCA_NL80211_VENDOR_ID,
864 .
865 subcmd
866 =
867 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
868 },
869 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
870 .
871 vendor_id
872 =
873 QCA_NL80211_VENDOR_ID,
874 .subcmd =
875 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
876 },
877 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
878 .vendor_id =
879 QCA_NL80211_VENDOR_ID,
880 .subcmd =
881 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
882 },
883 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
884 .
885 vendor_id
886 =
887 QCA_NL80211_VENDOR_ID,
888 .subcmd =
889 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
890 },
891 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
892 .
893 vendor_id
894 =
895 QCA_NL80211_VENDOR_ID,
896 .subcmd =
897 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
898 },
899 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
900 .
901 vendor_id
902 =
903 QCA_NL80211_VENDOR_ID,
904 .
905 subcmd
906 =
907 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
908 },
909 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
910 .
911 vendor_id
912 =
913 QCA_NL80211_VENDOR_ID,
914 .
915 subcmd =
916 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
917 },
918 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
919 .
920 vendor_id
921 =
922 QCA_NL80211_VENDOR_ID,
923 .
924 subcmd
925 =
926 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
927 },
928 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
929 .
930 vendor_id
931 =
932 QCA_NL80211_VENDOR_ID,
933 .
934 subcmd
935 =
936 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
937 },
938 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
939 .vendor_id = QCA_NL80211_VENDOR_ID,
940 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
941 },
942 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
943 .vendor_id = QCA_NL80211_VENDOR_ID,
944 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
945 },
946#endif /* FEATURE_WLAN_EXTSCAN */
947
948#ifdef WLAN_FEATURE_LINK_LAYER_STATS
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
978 },
979 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
980 .vendor_id =
981 QCA_NL80211_VENDOR_ID,
982 .subcmd =
983 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
984 },
985#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
986 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
987 .vendor_id =
988 QCA_NL80211_VENDOR_ID,
989 .subcmd =
990 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
991 },
992 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
993 .vendor_id = QCA_NL80211_VENDOR_ID,
994 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
995 },
996#ifdef WLAN_FEATURE_ROAM_OFFLOAD
997 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
998 .vendor_id =
999 QCA_NL80211_VENDOR_ID,
1000 .subcmd =
1001 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1002 },
1003#endif
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1027 },
1028 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1029 .vendor_id =
1030 QCA_NL80211_VENDOR_ID,
1031 .subcmd =
1032 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1033 },
1034#ifdef FEATURE_WLAN_EXTSCAN
1035 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1038 },
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1042 },
1043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1046 },
1047 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1048 .vendor_id = QCA_NL80211_VENDOR_ID,
1049 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1050 },
1051 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1052 .vendor_id = QCA_NL80211_VENDOR_ID,
1053 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1054 },
1055#endif /* FEATURE_WLAN_EXTSCAN */
1056 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1057 .vendor_id = QCA_NL80211_VENDOR_ID,
1058 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1059 },
1060#ifdef WLAN_FEATURE_MEMDUMP
1061 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1064 },
1065#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001066#ifdef WLAN_FEATURE_TSF
1067 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1068 .vendor_id = QCA_NL80211_VENDOR_ID,
1069 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1070 },
1071#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001072 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1073 .vendor_id = QCA_NL80211_VENDOR_ID,
1074 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1075 },
1076 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1077 .vendor_id = QCA_NL80211_VENDOR_ID,
1078 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1079 },
1080 /* OCB events */
1081 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1082 .vendor_id = QCA_NL80211_VENDOR_ID,
1083 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1084 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001085#ifdef FEATURE_LFR_SUBNET_DETECTION
1086 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1087 .vendor_id = QCA_NL80211_VENDOR_ID,
1088 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1089 },
1090#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001091
1092#ifdef WLAN_FEATURE_NAN_DATAPATH
1093 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1096 },
1097#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001098
1099 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1100 .vendor_id = QCA_NL80211_VENDOR_ID,
1101 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1102 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301103 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1104 .vendor_id = QCA_NL80211_VENDOR_ID,
1105 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1106 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301107 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1108 .vendor_id = QCA_NL80211_VENDOR_ID,
1109 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1110 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001111#ifdef WLAN_UMAC_CONVERGENCE
1112 COMMON_VENDOR_EVENTS
1113#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114};
1115
1116/**
1117 * __is_driver_dfs_capable() - get driver DFS capability
1118 * @wiphy: pointer to wireless wiphy structure.
1119 * @wdev: pointer to wireless_dev structure.
1120 * @data: Pointer to the data to be passed via vendor interface
1121 * @data_len:Length of the data to be passed
1122 *
1123 * This function is called by userspace to indicate whether or not
1124 * the driver supports DFS offload.
1125 *
1126 * Return: 0 on success, negative errno on failure
1127 */
1128static int __is_driver_dfs_capable(struct wiphy *wiphy,
1129 struct wireless_dev *wdev,
1130 const void *data,
1131 int data_len)
1132{
1133 u32 dfs_capability = 0;
1134 struct sk_buff *temp_skbuff;
1135 int ret_val;
1136 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1137
Jeff Johnson1f61b612016-02-12 16:28:33 -08001138 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139
1140 ret_val = wlan_hdd_validate_context(hdd_ctx);
1141 if (ret_val)
1142 return ret_val;
1143
Anurag Chouhan6d760662016-02-20 16:05:43 +05301144 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145 hdd_err("Command not allowed in FTM mode");
1146 return -EPERM;
1147 }
1148
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001149 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150
1151 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1152 NLMSG_HDRLEN);
1153
1154 if (temp_skbuff != NULL) {
1155 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1156 dfs_capability);
1157 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001158 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001159 kfree_skb(temp_skbuff);
1160
1161 return ret_val;
1162 }
1163
1164 return cfg80211_vendor_cmd_reply(temp_skbuff);
1165 }
1166
Jeff Johnson020db452016-06-29 14:37:26 -07001167 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001168 return -ENOMEM;
1169}
1170
1171/**
1172 * is_driver_dfs_capable() - get driver DFS capability
1173 * @wiphy: pointer to wireless wiphy structure.
1174 * @wdev: pointer to wireless_dev structure.
1175 * @data: Pointer to the data to be passed via vendor interface
1176 * @data_len:Length of the data to be passed
1177 *
1178 * This function is called by userspace to indicate whether or not
1179 * the driver supports DFS offload. This is an SSR-protected
1180 * wrapper function.
1181 *
1182 * Return: 0 on success, negative errno on failure
1183 */
1184static int is_driver_dfs_capable(struct wiphy *wiphy,
1185 struct wireless_dev *wdev,
1186 const void *data,
1187 int data_len)
1188{
1189 int ret;
1190
1191 cds_ssr_protect(__func__);
1192 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1193 cds_ssr_unprotect(__func__);
1194
1195 return ret;
1196}
1197
1198/**
1199 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1200 *
1201 * @adapter: SAP adapter pointer
1202 *
1203 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1204 * radio. So in case of DFS MCC scenario override current SAP given config
1205 * to follow concurrent SAP DFS config
1206 *
1207 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1208 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1210{
1211 hdd_adapter_t *con_sap_adapter;
1212 tsap_Config_t *sap_config, *con_sap_config;
1213 int con_ch;
1214
1215 /*
1216 * Check if AP+AP case, once primary AP chooses a DFS
1217 * channel secondary AP should always follow primary APs channel
1218 */
1219 if (!cds_concurrent_beaconing_sessions_running())
1220 return 0;
1221
1222 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1223 if (!con_sap_adapter)
1224 return 0;
1225
1226 sap_config = &adapter->sessionCtx.ap.sapConfig;
1227 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1228 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1229
1230 if (!CDS_IS_DFS_CH(con_ch))
1231 return 0;
1232
Jeff Johnson020db452016-06-29 14:37:26 -07001233 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001235 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 sap_config->channel = con_ch;
1237
1238 if (con_sap_config->acs_cfg.acs_mode == true) {
1239 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1240 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001241 hdd_err("Primary AP channel config error");
1242 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243 con_ch, con_sap_config->acs_cfg.pri_ch,
1244 con_sap_config->acs_cfg.ht_sec_ch);
1245 return -EINVAL;
1246 }
1247 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1248 * MCC restriction. So free ch list allocated in do_acs
1249 * func for Sec AP and realloc for Pri AP ch list size
1250 */
1251 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 &con_sap_config->acs_cfg,
1256 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 sizeof(uint8_t) *
1259 con_sap_config->acs_cfg.ch_list_count);
1260 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001261 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001262 return -ENOMEM;
1263 }
1264
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301265 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266 con_sap_config->acs_cfg.ch_list,
1267 con_sap_config->acs_cfg.ch_list_count);
1268
1269 } else {
1270 sap_config->acs_cfg.pri_ch = con_ch;
1271 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1272 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1273 }
1274
1275 return con_ch;
1276}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001277
1278/**
1279 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1280 * @sap_cfg: pointer to SAP config struct
1281 *
1282 * This function sets the default ACS start and end channel for the given band
1283 * and also parses the given ACS channel list.
1284 *
1285 * Return: None
1286 */
1287
1288static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1289 bool vht_enabled)
1290{
1291 int i;
1292 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1293 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001294 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1295 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001296 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1297 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001298 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1299 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001300 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1301 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001302 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1303 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001304 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1305 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001306 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1307 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308 }
1309
1310 if (ht_enabled)
1311 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1312
1313 if (vht_enabled)
1314 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1315
1316
1317 /* Parse ACS Chan list from hostapd */
1318 if (!sap_cfg->acs_cfg.ch_list)
1319 return;
1320
1321 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1322 sap_cfg->acs_cfg.end_ch =
1323 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1324 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301325 /* avoid channel as start channel */
1326 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1327 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001328 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1329 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1330 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1331 }
1332}
1333
1334
1335static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1336
1337/**
1338 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1339 * @adapter: pointer to SAP adapter struct
1340 *
1341 * This function starts the ACS procedure if there are no
1342 * constraints like MBSSID DFS restrictions.
1343 *
1344 * Return: Status of ACS Start procedure
1345 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301346int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347{
1348
1349 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1350 tsap_Config_t *sap_config;
1351 tpWLAN_SAPEventCB acs_event_callback;
1352 int status;
1353
1354 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301355 if (hdd_ctx->acs_policy.acs_channel)
1356 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1357 else
1358 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359
1360 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001361 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001363
1364 if (status > 0) {
1365 /*notify hostapd about channel override */
1366 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1367 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1368 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369 }
Jeff Johnson68755312017-02-10 11:46:55 -08001370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1372 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001373 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 return -EINVAL;
1375 }
1376
1377 acs_event_callback = hdd_hostapd_sap_event_cb;
1378
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301379 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301380 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301381 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 acs_event_callback, sap_config, adapter->dev);
1385
1386
1387 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001388 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389 return -EINVAL;
1390 }
bings394afdd2017-01-09 11:22:38 +08001391 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1392 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001393 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1394
1395 return 0;
1396}
1397
1398/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301399 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1400 * @ap_adapter: AP adapter
1401 * @nol: Non-occupancy list
1402 * @nol_len: Length of NOL
1403 *
1404 * Get the NOL for SAP
1405 *
1406 * Return: Zero on success, non-zero on failure
1407 */
1408static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1409 uint32_t *nol_len)
1410{
1411 QDF_STATUS ret;
1412
1413 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1414 nol, nol_len);
1415 if (QDF_IS_STATUS_ERROR(ret))
1416 return -EINVAL;
1417
1418 return 0;
1419}
1420
1421/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301422 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1423 * @hdd_ctx: hdd context
1424 * @acs_chan_params: external acs channel params
1425 * @sap_config: SAP config
1426 *
1427 * This API provides unsorted pcl list.
1428 * this list is a subset of the valid channel list given by hostapd.
1429 * if channel is not present in pcl, weightage will be given as zero
1430 *
1431 * Return: Zero on success, non-zero on failure
1432 */
1433static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1434 struct hdd_vendor_acs_chan_params *acs_chan_params,
1435 tsap_Config_t *sap_config)
1436{
1437 int i, j;
1438
1439 for (i = 0; i < acs_chan_params->channel_count; i++) {
1440 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1441 if (acs_chan_params->channel_list[i] ==
1442 sap_config->acs_cfg.pcl_channels[j]) {
1443 acs_chan_params->vendor_pcl_list[i] =
1444 sap_config->acs_cfg.pcl_channels[j];
1445 acs_chan_params->vendor_weight_list[i] =
1446 sap_config->acs_cfg.
1447 pcl_channels_weight_list[j];
1448 break;
1449 } else {
1450 acs_chan_params->vendor_pcl_list[i] =
1451 acs_chan_params->channel_list[i];
1452 acs_chan_params->vendor_weight_list[i] = 0;
1453 }
1454 }
1455 }
1456 if (hdd_ctx->unsafe_channel_count == 0)
1457 return;
1458 /* Update unsafe channel weight as zero */
1459 for (i = 0; i < acs_chan_params->channel_count; i++) {
1460 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1461 if (acs_chan_params->channel_list[i] ==
1462 hdd_ctx->unsafe_channel_list[j]) {
1463 acs_chan_params->vendor_weight_list[i] = 0;
1464 }
1465 }
1466 }
1467}
1468
1469/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301470 * hdd_update_reg_chan_info : This API contructs channel info
1471 * for all the given channel
1472 * @adapter: pointer to SAP adapter struct
1473 * @channel_count: channel count
1474 * @channel_list: channel list
1475 *
1476 * Return: Status of of channel information updation
1477 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301478static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301479 uint32_t channel_count,
1480 uint8_t *channel_list)
1481{
1482 int i;
1483 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301484 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301485 uint8_t bw_offset = 0, chan = 0;
1486 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1487 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1488
1489 /* memory allocation */
1490 sap_config->channel_info = qdf_mem_malloc(
1491 sizeof(struct hdd_channel_info) *
1492 channel_count);
1493 if (!sap_config->channel_info) {
1494 hdd_err("memory allocation failed");
1495 return -ENOMEM;
1496
1497 }
1498 for (i = 0; i < channel_count; i++) {
1499 icv = &sap_config->channel_info[i];
1500 chan = channel_list[i];
1501
1502 if (chan == 0)
1503 continue;
1504
1505 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1506 bw_offset = 1 << BW_40_OFFSET_BIT;
1507 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1508 bw_offset = 1 << BW_20_OFFSET_BIT;
1509 icv->freq = cds_get_channel_freq(chan);
1510 icv->ieee_chan_number = chan;
1511 icv->max_reg_power = cds_get_channel_reg_power(chan);
1512
1513 /* filling demo values */
1514 icv->max_radio_power = HDD_MAX_TX_POWER;
1515 icv->min_radio_power = HDD_MIN_TX_POWER;
1516 /* not supported in current driver */
1517 icv->max_antenna_gain = 0;
1518
1519 icv->reg_class_id = wlan_hdd_find_opclass(
1520 WLAN_HDD_GET_HAL_CTX(adapter),
1521 chan, bw_offset);
1522
1523 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1524 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1525 cds_set_channel_params(chan, 0, &ch_params);
1526 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1527 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1528 }
1529 icv->flags = 0;
1530 icv->flags = cds_get_vendor_reg_flags(chan,
1531 sap_config->acs_cfg.ch_width,
1532 sap_config->acs_cfg.is_ht_enabled,
1533 sap_config->acs_cfg.is_vht_enabled,
1534 hdd_ctx->config->enable_sub_20_channel_width);
1535
1536 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1537 icv->freq, icv->flags,
1538 icv->flagext, icv->ieee_chan_number,
1539 icv->max_reg_power, icv->max_radio_power,
1540 icv->min_radio_power, icv->reg_class_id,
1541 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1542 icv->vht_center_freq_seg1);
1543 }
1544 return 0;
1545}
1546
1547/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1548#define CHAN_INFO_ATTR_FLAGS \
1549 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1550#define CHAN_INFO_ATTR_FLAG_EXT \
1551 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1552#define CHAN_INFO_ATTR_FREQ \
1553 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1554#define CHAN_INFO_ATTR_MAX_REG_POWER \
1555 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1556#define CHAN_INFO_ATTR_MAX_POWER \
1557 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1558#define CHAN_INFO_ATTR_MIN_POWER \
1559 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1560#define CHAN_INFO_ATTR_REG_CLASS_ID \
1561 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1562#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1563 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1564#define CHAN_INFO_ATTR_VHT_SEG_0 \
1565 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1566#define CHAN_INFO_ATTR_VHT_SEG_1 \
1567 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1568
1569/**
1570 * hdd_cfg80211_update_channel_info() - add channel info attributes
1571 * @skb: pointer to sk buff
1572 * @hdd_ctx: pointer to hdd station context
1573 * @idx: attribute index
1574 *
1575 * Return: Success(0) or reason code for failure
1576 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301577static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301578hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1579 tsap_Config_t *sap_config, int idx)
1580{
1581 struct nlattr *nla_attr, *channel;
1582 struct hdd_channel_info *icv;
1583 int i;
1584
1585 nla_attr = nla_nest_start(skb, idx);
1586 if (!nla_attr)
1587 goto fail;
1588
1589 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1590 channel = nla_nest_start(skb, i);
1591 if (!channel)
1592 goto fail;
1593
1594 icv = &sap_config->channel_info[i];
1595 if (!icv) {
1596 hdd_err("channel info not found");
1597 goto fail;
1598 }
1599 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1600 icv->freq) ||
1601 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1602 icv->flags) ||
1603 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1604 icv->flagext) ||
1605 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1606 icv->max_reg_power) ||
1607 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1608 icv->max_radio_power) ||
1609 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1610 icv->min_radio_power) ||
1611 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1612 icv->reg_class_id) ||
1613 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1614 icv->max_antenna_gain) ||
1615 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1616 icv->vht_center_freq_seg0) ||
1617 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1618 icv->vht_center_freq_seg1)) {
1619 hdd_err("put fail");
1620 goto fail;
1621 }
1622 nla_nest_end(skb, channel);
1623 }
1624 nla_nest_end(skb, nla_attr);
1625 return 0;
1626fail:
1627 hdd_err("nl channel update failed");
1628 return -EINVAL;
1629}
1630#undef CHAN_INFO_ATTR_FLAGS
1631#undef CHAN_INFO_ATTR_FLAG_EXT
1632#undef CHAN_INFO_ATTR_FREQ
1633#undef CHAN_INFO_ATTR_MAX_REG_POWER
1634#undef CHAN_INFO_ATTR_MAX_POWER
1635#undef CHAN_INFO_ATTR_MIN_POWER
1636#undef CHAN_INFO_ATTR_REG_CLASS_ID
1637#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1638#undef CHAN_INFO_ATTR_VHT_SEG_0
1639#undef CHAN_INFO_ATTR_VHT_SEG_1
1640
1641/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301642 * hdd_cfg80211_update_pcl() - add pcl info attributes
1643 * @skb: pointer to sk buff
1644 * @hdd_ctx: pointer to hdd station context
1645 * @idx: attribute index
1646 * @vendor_pcl_list: PCL list
1647 * @vendor_weight_list: PCL weights
1648 *
1649 * Return: Success(0) or reason code for failure
1650 */
1651static int32_t
1652hdd_cfg80211_update_pcl(struct sk_buff *skb,
1653 uint8_t ch_list_count, int idx,
1654 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1655{
1656 struct nlattr *nla_attr, *channel;
1657 int i;
1658
1659 nla_attr = nla_nest_start(skb, idx);
1660
1661 if (!nla_attr)
1662 goto fail;
1663
1664 for (i = 0; i < ch_list_count; i++) {
1665 channel = nla_nest_start(skb, i);
1666 if (!channel)
1667 goto fail;
1668 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1669 vendor_pcl_list[i]) ||
1670 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1671 vendor_weight_list[i])) {
1672 hdd_err("put fail");
1673 goto fail;
1674 }
1675 nla_nest_end(skb, channel);
1676 }
1677 nla_nest_end(skb, nla_attr);
1678
1679 return 0;
1680fail:
1681 hdd_err("updating pcl list failed");
1682 return -EINVAL;
1683}
1684
1685static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1686{
1687 /* Get scan band */
1688 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1689 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1690 *band = eCSR_BAND_24;
1691 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1692 *band = eCSR_BAND_5G;
1693 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1694 *band = eCSR_BAND_ALL;
1695 }
1696 /* Auto is not supported currently */
1697 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1698 hdd_err("invalid band");
1699 *band = eCSR_BAND_24;
1700 }
1701}
1702
1703void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1704 uint8_t reason)
1705{
1706 struct sk_buff *skb;
1707 tsap_Config_t *sap_config;
1708 uint32_t channel_count = 0, status;
1709 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1710 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1711 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1712 struct hdd_vendor_acs_chan_params acs_chan_params;
1713 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1714 eCsrBand band = eCSR_BAND_24;
1715 eCsrPhyMode phy_mode;
1716
1717 if (!hdd_ctx) {
1718 hdd_err("HDD context is NULL");
1719 return;
1720 }
1721
1722 ENTER();
1723 sap_config = &adapter->sessionCtx.ap.sapConfig;
1724
1725 /* Get valid channels for SAP */
1726 wlan_hdd_sap_get_valid_channellist(adapter,
1727 &channel_count, channel_list);
1728
1729 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1730 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1731 /* Get phymode */
1732 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1733
1734 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1735 &(adapter->wdev),
1736 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1737 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1738 GFP_KERNEL);
1739
1740 if (!skb) {
1741 hdd_err("cfg80211_vendor_event_alloc failed");
1742 return;
1743 }
1744 /*
1745 * Application expects pcl to be a subset of channel list
1746 * Remove all channels which are not in channel list from pcl
1747 * and add weight as zero
1748 */
1749 acs_chan_params.channel_count = channel_count;
1750 acs_chan_params.channel_list = channel_list;
1751 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1752 acs_chan_params.vendor_weight_list = vendor_weight_list;
1753
1754 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1755 sap_config);
1756 /* Update values in NL buffer */
1757 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1758 reason) ||
1759 nla_put_u8(skb,
1760 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1761 false) ||
1762 nla_put_u8(skb,
1763 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1764 true) ||
1765 nla_put_u8(skb,
1766 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1767 true) ||
1768 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1769 sap_config->acs_cfg.ch_width) ||
1770 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1771 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1772 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1773 band) ||
1774 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1775 phy_mode) ||
1776 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1777 channel_count, channel_list)) {
1778 hdd_err("nla put fail");
1779 goto fail;
1780 }
1781 status = hdd_cfg80211_update_pcl(skb, channel_count,
1782 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1783 vendor_pcl_list, vendor_weight_list);
1784
1785 if (status != 0)
1786 goto fail;
1787
1788 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1789 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1790
1791 if (status != 0)
1792 goto fail;
1793
1794 cfg80211_vendor_event(skb, GFP_KERNEL);
1795 return;
1796fail:
1797 if (skb)
1798 kfree_skb(skb);
1799}
1800
1801static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1802{
1803 struct hdd_external_acs_timer_context *timer_context;
1804
1805 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1806 return 0;
1807
1808 hdd_notice("Starting vendor app based ACS");
1809 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1810 timer_context->adapter = adapter;
1811
1812 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1813 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1814 QDF_TIMER_TYPE_SW,
1815 hdd_acs_response_timeout_handler, timer_context);
1816 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1817 return 0;
1818}
1819
1820/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1822 * @wiphy: Linux wiphy struct pointer
1823 * @wdev: Linux wireless device struct pointer
1824 * @data: ACS information from hostapd
1825 * @data_len: ACS information length
1826 *
1827 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1828 * and starts ACS procedure.
1829 *
1830 * Return: ACS procedure start status
1831 */
1832
1833static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1834 struct wireless_dev *wdev,
1835 const void *data, int data_len)
1836{
1837 struct net_device *ndev = wdev->netdev;
1838 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1839 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1840 tsap_Config_t *sap_config;
1841 struct sk_buff *temp_skbuff;
1842 int status = -EINVAL, i = 0;
1843 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1844 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301845 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001846
1847 /* ***Note*** Donot set SME config related to ACS operation here because
1848 * ACS operation is not synchronouse and ACS for Second AP may come when
1849 * ACS operation for first AP is going on. So only do_acs is split to
1850 * seperate start_acs routine. Also SME-PMAC struct that is used to
1851 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1852 * config shall be set only from start_acs.
1853 */
1854
1855 /* nla_policy Policy template. Policy not applied as some attributes are
1856 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1857 *
1858 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1859 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1860 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1861 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1862 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1864 */
1865
Jeff Johnson1f61b612016-02-12 16:28:33 -08001866 ENTER_DEV(ndev);
1867
Anurag Chouhan6d760662016-02-20 16:05:43 +05301868 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869 hdd_err("Command not allowed in FTM mode");
1870 return -EPERM;
1871 }
1872
Kapil Gupta8878ad92017-02-13 11:56:04 +05301873 if (hdd_ctx->config->force_sap_acs &&
1874 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001875 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876 return -EPERM;
1877 }
1878
1879 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301880 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301882
Naveen Rawat64e477e2016-05-20 10:34:56 -07001883 if (cds_is_sub_20_mhz_enabled()) {
1884 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1885 status = -EINVAL;
1886 goto out;
1887 }
1888
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301890 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891
1892 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1893 NULL);
1894 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001895 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 goto out;
1897 }
1898
1899 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001900 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 goto out;
1902 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301903 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1904 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905
1906 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1907 ht_enabled =
1908 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1909 else
1910 ht_enabled = 0;
1911
1912 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1913 ht40_enabled =
1914 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1915 else
1916 ht40_enabled = 0;
1917
1918 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1919 vht_enabled =
1920 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1921 else
1922 vht_enabled = 0;
1923
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301924 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1925 vht_enabled = 0;
1926 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1927 }
1928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1930 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1931 } else {
1932 if (ht_enabled && ht40_enabled)
1933 ch_width = 40;
1934 else
1935 ch_width = 20;
1936 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301937
1938 /* this may be possible, when sap_force_11n_for_11ac is set */
1939 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1940 if (ht_enabled && ht40_enabled)
1941 ch_width = 40;
1942 else
1943 ch_width = 20;
1944 }
1945
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 if (ch_width == 80)
1947 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1948 else if (ch_width == 40)
1949 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1950 else
1951 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1952
1953 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1954 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1955 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1956 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1957 * since it contains the frequency values of the channels in
1958 * the channel list.
1959 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1960 * is present
1961 */
1962 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1963 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1964 sap_config->acs_cfg.ch_list_count = nla_len(
1965 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1966 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301967 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 sizeof(uint8_t) *
1969 sap_config->acs_cfg.ch_list_count);
1970 if (sap_config->acs_cfg.ch_list == NULL)
1971 goto out;
1972
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301973 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 sap_config->acs_cfg.ch_list_count);
1975 }
1976 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1977 uint32_t *freq =
1978 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1979 sap_config->acs_cfg.ch_list_count = nla_len(
1980 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1981 sizeof(uint32_t);
1982 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301983 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 sap_config->acs_cfg.ch_list_count);
1985 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001986 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 status = -ENOMEM;
1988 goto out;
1989 }
1990
1991 /* convert frequency to channel */
1992 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1993 sap_config->acs_cfg.ch_list[i] =
1994 ieee80211_frequency_to_channel(freq[i]);
1995 }
1996 }
1997
1998 hdd_debug("get pcl for DO_ACS vendor command");
1999
2000 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002001 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302002 sap_config->acs_cfg.pcl_channels,
2003 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302004 sap_config->acs_cfg.pcl_channels_weight_list,
2005 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302006 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002007 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302010 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2011 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07002012 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013 vht_enabled = 1;
2014 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2015 sap_config->acs_cfg.ch_width =
2016 hdd_ctx->config->vhtChannelWidth;
2017 /* No VHT80 in 2.4G so perform ACS accordingly */
2018 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302019 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302021 ch_width = 40;
2022 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023 }
2024
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302025 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2026
Jeff Johnson020db452016-06-29 14:37:26 -07002027 hdd_notice("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2029 ch_width, ht_enabled, vht_enabled,
2030 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2031
Kapil Gupta8878ad92017-02-13 11:56:04 +05302032 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2033 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2034
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07002036 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 sap_config->acs_cfg.ch_list_count);
2038 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07002039 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 }
2041 sap_config->acs_cfg.acs_mode = true;
2042 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002043 /* ***Note*** Completion variable usage is not allowed
2044 * here since ACS scan operation may take max 2.2 sec
2045 * for 5G band:
2046 * 9 Active channel X 40 ms active scan time +
2047 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2049 * for this long. So we split up the scanning part.
2050 */
2051 set_bit(ACS_PENDING, &adapter->event_flags);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302052 hdd_notice("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 status = 0;
2054 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302055 /* Check if vendor specific acs is enabled */
2056 if (hdd_ctx->config->vendor_acs_support) {
2057 sap_config->acs_cfg.hw_mode = hw_mode;
2058 hdd_create_acs_timer(adapter);
2059 hdd_update_acs_timer_reason(adapter,
2060 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2061 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2062 wlan_sap_set_vendor_acs(
2063 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2064 true);
2065 else
2066 wlan_sap_set_vendor_acs(
2067 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2068 false);
2069
2070 } else
2071 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 }
2073
2074out:
2075 if (0 == status) {
2076 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2077 NLMSG_HDRLEN);
2078 if (temp_skbuff != NULL)
2079 return cfg80211_vendor_cmd_reply(temp_skbuff);
2080 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002081 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2083
2084 return status;
2085}
2086
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002087/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002088 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2089 * @wiphy: Linux wiphy struct pointer
2090 * @wdev: Linux wireless device struct pointer
2091 * @data: ACS information from hostapd
2092 * @data_len: ACS information len
2093 *
2094 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2095 * and starts ACS procedure.
2096 *
2097 * Return: ACS procedure start status
2098 */
2099
2100static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2101 struct wireless_dev *wdev,
2102 const void *data, int data_len)
2103{
2104 int ret;
2105
2106 cds_ssr_protect(__func__);
2107 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2108 cds_ssr_unprotect(__func__);
2109
2110 return ret;
2111}
2112
2113/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002114 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2115 * @adapter: Pointer to adapter struct
2116 *
2117 * This function handle cleanup of what was done in DO_ACS, including free
2118 * memory.
2119 *
2120 * Return: void
2121 */
2122
2123void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2124{
2125 if (adapter == NULL)
2126 return;
2127 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2128 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2129 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2130 }
2131}
2132
2133/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002134 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2135 * @work: Linux workqueue struct pointer for ACS work
2136 *
2137 * This function starts the ACS procedure which was marked pending when an ACS
2138 * procedure was in progress for a concurrent SAP interface.
2139 *
2140 * Return: None
2141 */
2142
2143static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2144{
2145 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2146 acs_pending_work.work);
2147 wlan_hdd_cfg80211_start_acs(adapter);
2148}
2149
2150/**
2151 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2152 * @adapter: Pointer to SAP adapter struct
2153 * @pri_channel: SAP ACS procedure selected Primary channel
2154 * @sec_channel: SAP ACS procedure selected secondary channel
2155 *
2156 * This is a callback function from SAP module on ACS procedure is completed.
2157 * This function send the ACS selected channel information to hostapd
2158 *
2159 * Return: None
2160 */
2161
2162void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2163{
2164 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2165 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2166 struct sk_buff *vendor_event;
2167 int ret_val;
2168 hdd_adapter_t *con_sap_adapter;
2169 uint16_t ch_width;
2170
2171 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002172 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2174 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2175 GFP_KERNEL);
2176
2177 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002178 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 return;
2180 }
2181
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182 ret_val = nla_put_u8(vendor_event,
2183 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2184 sap_cfg->acs_cfg.pri_ch);
2185 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002186 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 kfree_skb(vendor_event);
2188 return;
2189 }
2190
2191 ret_val = nla_put_u8(vendor_event,
2192 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2193 sap_cfg->acs_cfg.ht_sec_ch);
2194 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002195 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002196 kfree_skb(vendor_event);
2197 return;
2198 }
2199
2200 ret_val = nla_put_u8(vendor_event,
2201 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2202 sap_cfg->acs_cfg.vht_seg0_center_ch);
2203 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002204 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002205 kfree_skb(vendor_event);
2206 return;
2207 }
2208
2209 ret_val = nla_put_u8(vendor_event,
2210 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2211 sap_cfg->acs_cfg.vht_seg1_center_ch);
2212 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002213 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 kfree_skb(vendor_event);
2215 return;
2216 }
2217
2218 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2219 ch_width = 80;
2220 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2221 ch_width = 40;
2222 else
2223 ch_width = 20;
2224
2225 ret_val = nla_put_u16(vendor_event,
2226 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2227 ch_width);
2228 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002229 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002230 kfree_skb(vendor_event);
2231 return;
2232 }
2233 if (sap_cfg->acs_cfg.pri_ch > 14)
2234 ret_val = nla_put_u8(vendor_event,
2235 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2236 QCA_ACS_MODE_IEEE80211A);
2237 else
2238 ret_val = nla_put_u8(vendor_event,
2239 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2240 QCA_ACS_MODE_IEEE80211G);
2241
2242 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002243 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002244 kfree_skb(vendor_event);
2245 return;
2246 }
2247
Jeff Johnson46b40792016-06-29 14:03:14 -07002248 hdd_notice("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2250 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2251 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2252
2253 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2254 /* ***Note*** As already mentioned Completion variable usage is not
2255 * allowed here since ACS scan operation may take max 2.2 sec.
2256 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2257 * operation.
2258 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2259 * when Primary AP ACS is complete and secondary AP ACS is started here
2260 * immediately, Primary AP start_bss may come inbetween ACS operation
2261 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2262 * delay. This path and below constraint will be removed on sessionizing
2263 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2264 * As per design constraint user space control application must take
2265 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2266 * this code path. Sec AP hostapd should be started after Primary AP
2267 * start beaconing which can be confirmed by getchannel iwpriv command
2268 */
2269
2270 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2271 if (con_sap_adapter &&
2272 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002273 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2274 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 /* Lets give 500ms for OBSS + START_BSS to complete */
2276 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2277 msecs_to_jiffies(500));
2278 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2279 }
2280
2281 return;
2282}
2283
2284static int
2285__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2286 struct wireless_dev *wdev,
2287 const void *data,
2288 int data_len)
2289{
2290 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2291 struct sk_buff *skb = NULL;
2292 uint32_t fset = 0;
2293 int ret;
2294
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002295 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302296
Anurag Chouhan6d760662016-02-20 16:05:43 +05302297 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002298 hdd_err("Command not allowed in FTM mode");
2299 return -EPERM;
2300 }
2301
2302 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302303 if (ret)
2304 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002305
2306 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002307 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 fset |= WIFI_FEATURE_INFRA;
2309 }
2310 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002311 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 fset |= WIFI_FEATURE_INFRA_5G;
2313 }
2314#ifdef WLAN_FEATURE_P2P
2315 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2316 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002317 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318 fset |= WIFI_FEATURE_P2P;
2319 }
2320#endif
2321 fset |= WIFI_FEATURE_SOFT_AP;
2322
2323 /* HOTSPOT is a supplicant feature, enable it by default */
2324 fset |= WIFI_FEATURE_HOTSPOT;
2325
2326#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302327 if (pHddCtx->config->extscan_enabled &&
2328 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002329 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2331 }
2332#endif
2333 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002334 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 fset |= WIFI_FEATURE_NAN;
2336 }
2337 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002338 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 fset |= WIFI_FEATURE_D2D_RTT;
2340 fset |= WIFI_FEATURE_D2AP_RTT;
2341 }
2342#ifdef FEATURE_WLAN_SCAN_PNO
2343 if (pHddCtx->config->configPNOScanSupport &&
2344 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002345 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002346 fset |= WIFI_FEATURE_PNO;
2347 }
2348#endif
2349 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2350#ifdef FEATURE_WLAN_TDLS
2351 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2352 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002353 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 fset |= WIFI_FEATURE_TDLS;
2355 }
2356 if (sme_is_feature_supported_by_fw(TDLS) &&
2357 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2358 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002359 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002360 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2361 }
2362#endif
2363#ifdef WLAN_AP_STA_CONCURRENCY
2364 fset |= WIFI_FEATURE_AP_STA;
2365#endif
2366 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002367 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368
2369 if (hdd_link_layer_stats_supported())
2370 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2371
2372 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2373 NLMSG_HDRLEN);
2374 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002375 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 return -EINVAL;
2377 }
Jeff Johnson020db452016-06-29 14:37:26 -07002378 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002380 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 goto nla_put_failure;
2382 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302383 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302384 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385nla_put_failure:
2386 kfree_skb(skb);
2387 return -EINVAL;
2388}
2389
2390/**
2391 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2392 * @wiphy: pointer to wireless wiphy structure.
2393 * @wdev: pointer to wireless_dev structure.
2394 * @data: Pointer to the data to be passed via vendor interface
2395 * @data_len:Length of the data to be passed
2396 *
2397 * Return: Return the Success or Failure code.
2398 */
2399static int
2400wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2401 struct wireless_dev *wdev,
2402 const void *data, int data_len)
2403{
2404 int ret = 0;
2405
2406 cds_ssr_protect(__func__);
2407 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2408 data, data_len);
2409 cds_ssr_unprotect(__func__);
2410
2411 return ret;
2412}
2413
2414/**
2415 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2416 * @wiphy: pointer to wireless wiphy structure.
2417 * @wdev: pointer to wireless_dev structure.
2418 * @data: Pointer to the data to be passed via vendor interface
2419 * @data_len:Length of the data to be passed
2420 *
2421 * Set the MAC address that is to be used for scanning.
2422 *
2423 * Return: Return the Success or Failure code.
2424 */
2425static int
2426__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2427 struct wireless_dev *wdev,
2428 const void *data,
2429 int data_len)
2430{
2431 tpSirScanMacOui pReqMsg = NULL;
2432 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2433 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302434 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 int ret;
2436
Jeff Johnson1f61b612016-02-12 16:28:33 -08002437 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438
Anurag Chouhan6d760662016-02-20 16:05:43 +05302439 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 hdd_err("Command not allowed in FTM mode");
2441 return -EPERM;
2442 }
2443
2444 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302445 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447
2448 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002449 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 return -ENOTSUPP;
2451 }
2452
2453 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2454 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002455 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 return -EINVAL;
2457 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302458 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002460 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 return -ENOMEM;
2462 }
2463 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002464 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 goto fail;
2466 }
2467 nla_memcpy(&pReqMsg->oui[0],
2468 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2469 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002470 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471 pReqMsg->oui[1], pReqMsg->oui[2]);
2472 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302473 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002474 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 goto fail;
2476 }
2477 return 0;
2478fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302479 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 return -EINVAL;
2481}
2482
2483/**
2484 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2485 * @wiphy: pointer to wireless wiphy structure.
2486 * @wdev: pointer to wireless_dev structure.
2487 * @data: Pointer to the data to be passed via vendor interface
2488 * @data_len:Length of the data to be passed
2489 *
2490 * Set the MAC address that is to be used for scanning. This is an
2491 * SSR-protecting wrapper function.
2492 *
2493 * Return: Return the Success or Failure code.
2494 */
2495static int
2496wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2497 struct wireless_dev *wdev,
2498 const void *data,
2499 int data_len)
2500{
2501 int ret;
2502
2503 cds_ssr_protect(__func__);
2504 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2505 data, data_len);
2506 cds_ssr_unprotect(__func__);
2507
2508 return ret;
2509}
2510
2511/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302512 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2513 * @wiphy: pointer phy adapter
2514 * @wdev: pointer to wireless device structure
2515 * @data: pointer to data buffer
2516 * @data_len: length of data
2517 *
2518 * This routine will give concurrency matrix
2519 *
2520 * Return: int status code
2521 */
2522static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2523 struct wireless_dev *wdev,
2524 const void *data,
2525 int data_len)
2526{
2527 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2528 uint8_t i, feature_sets, max_feature_sets;
2529 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2530 struct sk_buff *reply_skb;
2531 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2532 int ret;
2533
2534 ENTER_DEV(wdev->netdev);
2535
2536 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2537 hdd_err("Command not allowed in FTM mode");
2538 return -EPERM;
2539 }
2540
2541 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302542 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302543 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302544
2545 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2546 data, data_len, NULL)) {
2547 hdd_err("Invalid ATTR");
2548 return -EINVAL;
2549 }
2550
2551 /* Parse and fetch max feature set */
2552 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2553 hdd_err("Attr max feature set size failed");
2554 return -EINVAL;
2555 }
2556 max_feature_sets = nla_get_u32(tb[
2557 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2558 hdd_info("Max feature set size: %d", max_feature_sets);
2559
2560 /* Fill feature combination matrix */
2561 feature_sets = 0;
2562 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002563 WIFI_FEATURE_P2P;
2564 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2565 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302566 /* Add more feature combinations here */
2567
2568 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002569 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302570 hdd_info("Feature set matrix");
2571 for (i = 0; i < feature_sets; i++)
2572 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2573
2574 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2575 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2576 if (!reply_skb) {
2577 hdd_err("Feature set matrix: buffer alloc fail");
2578 return -ENOMEM;
2579 }
2580
2581 if (nla_put_u32(reply_skb,
2582 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2583 feature_sets) ||
2584 nla_put(reply_skb,
2585 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2586 sizeof(u32) * feature_sets,
2587 feature_set_matrix)) {
2588 hdd_err("nla put fail");
2589 kfree_skb(reply_skb);
2590 return -EINVAL;
2591 }
2592 return cfg80211_vendor_cmd_reply(reply_skb);
2593}
2594
2595/**
2596 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2597 * @wiphy: pointer to wireless wiphy structure.
2598 * @wdev: pointer to wireless_dev structure.
2599 * @data: Pointer to the data to be passed via vendor interface
2600 * @data_len:Length of the data to be passed
2601 *
2602 * Retrieves the concurrency feature set matrix
2603 *
2604 * Return: 0 on success, negative errno on failure
2605 */
2606static int
2607wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2608 struct wireless_dev *wdev,
2609 const void *data,
2610 int data_len)
2611{
2612 int ret;
2613
2614 cds_ssr_protect(__func__);
2615 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2616 data, data_len);
2617 cds_ssr_unprotect(__func__);
2618
2619 return ret;
2620}
2621
2622/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2624 * @feature_flags: pointer to the byte array of features.
2625 * @feature: Feature to be turned ON in the byte array.
2626 *
2627 * Return: None
2628 *
2629 * This is called to turn ON or SET the feature flag for the requested feature.
2630 **/
2631#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002632static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2633 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002634{
2635 uint32_t index;
2636 uint8_t bit_mask;
2637
2638 index = feature / NUM_BITS_IN_BYTE;
2639 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2640 feature_flags[index] |= bit_mask;
2641}
2642
2643/**
2644 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2645 * @wiphy: pointer to wireless wiphy structure.
2646 * @wdev: pointer to wireless_dev structure.
2647 * @data: Pointer to the data to be passed via vendor interface
2648 * @data_len:Length of the data to be passed
2649 *
2650 * This is called when wlan driver needs to send supported feature set to
2651 * supplicant upon a request/query from the supplicant.
2652 *
2653 * Return: Return the Success or Failure code.
2654 **/
2655#define MAX_CONCURRENT_CHAN_ON_24G 2
2656#define MAX_CONCURRENT_CHAN_ON_5G 2
2657static int
2658__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2659 struct wireless_dev *wdev,
2660 const void *data, int data_len)
2661{
2662 struct sk_buff *skb = NULL;
2663 uint32_t dbs_capability = 0;
2664 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302665 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 int ret_val;
2667
2668 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2669 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2670
Jeff Johnson1f61b612016-02-12 16:28:33 -08002671 ENTER_DEV(wdev->netdev);
2672
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2674 if (ret_val)
2675 return ret_val;
2676
Anurag Chouhan6d760662016-02-20 16:05:43 +05302677 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 hdd_err("Command not allowed in FTM mode");
2679 return -EPERM;
2680 }
2681
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002682 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002683 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 wlan_hdd_cfg80211_set_feature(feature_flags,
2685 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2686 }
2687
2688 wlan_hdd_cfg80211_set_feature(feature_flags,
2689 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2690 if (wma_is_scan_simultaneous_capable())
2691 wlan_hdd_cfg80211_set_feature(feature_flags,
2692 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002693
2694 if (wma_is_p2p_lo_capable())
2695 wlan_hdd_cfg80211_set_feature(feature_flags,
2696 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002698 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2699 NLMSG_HDRLEN);
2700
2701 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002702 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 return -ENOMEM;
2704 }
2705
2706 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2707 sizeof(feature_flags), feature_flags))
2708 goto nla_put_failure;
2709
2710 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302711 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002712 if (one_by_one_dbs)
2713 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2714
2715 if (two_by_two_dbs)
2716 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2717
2718 if (!one_by_one_dbs && !two_by_two_dbs)
2719 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2720 } else {
2721 hdd_err("wma_get_dbs_hw_mode failed");
2722 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2723 }
2724
2725 hdd_info("dbs_capability is %d", dbs_capability);
2726
2727 if (nla_put_u32(skb,
2728 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2729 MAX_CONCURRENT_CHAN_ON_24G))
2730 goto nla_put_failure;
2731
2732 if (nla_put_u32(skb,
2733 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2734 MAX_CONCURRENT_CHAN_ON_5G))
2735 goto nla_put_failure;
2736
2737 return cfg80211_vendor_cmd_reply(skb);
2738
2739nla_put_failure:
2740 kfree_skb(skb);
2741 return -EINVAL;
2742}
2743
2744/**
2745 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2746 * @wiphy: pointer to wireless wiphy structure.
2747 * @wdev: pointer to wireless_dev structure.
2748 * @data: Pointer to the data to be passed via vendor interface
2749 * @data_len:Length of the data to be passed
2750 *
2751 * This is called when wlan driver needs to send supported feature set to
2752 * supplicant upon a request/query from the supplicant.
2753 *
2754 * Return: Return the Success or Failure code.
2755 */
2756static int
2757wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2758 struct wireless_dev *wdev,
2759 const void *data, int data_len)
2760{
2761 int ret;
2762
2763 cds_ssr_protect(__func__);
2764 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2765 data, data_len);
2766 cds_ssr_unprotect(__func__);
2767
2768 return ret;
2769}
2770
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302771#define PARAM_NUM_NW \
2772 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2773#define PARAM_SET_BSSID \
2774 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2775#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2776#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777
2778/**
2779 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2780 * @wiphy: The wiphy structure
2781 * @wdev: The wireless device
2782 * @data: Data passed by framework
2783 * @data_len: Parameters to be configured passed as data
2784 *
2785 * The roaming related parameters are configured by the framework
2786 * using this interface.
2787 *
2788 * Return: Return either success or failure code.
2789 */
2790static int
2791__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2792 struct wireless_dev *wdev, const void *data, int data_len)
2793{
2794 struct net_device *dev = wdev->netdev;
2795 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2796 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2797 uint8_t session_id;
2798 struct roam_ext_params roam_params;
2799 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302800 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2802 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2803 int rem, i;
2804 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002805 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 int ret;
2807
Jeff Johnson1f61b612016-02-12 16:28:33 -08002808 ENTER_DEV(dev);
2809
Anurag Chouhan6d760662016-02-20 16:05:43 +05302810 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 hdd_err("Command not allowed in FTM mode");
2812 return -EPERM;
2813 }
2814
2815 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302816 if (ret)
2817 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818
2819 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2820 data, data_len,
2821 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002822 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 return -EINVAL;
2824 }
2825 /* Parse and fetch Command Type*/
2826 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002827 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 goto fail;
2829 }
2830 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302831 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2833 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002834 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835 goto fail;
2836 }
2837 req_id = nla_get_u32(
2838 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002839 hdd_debug("Req Id (%d)", req_id);
2840 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 switch (cmd_type) {
2842 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2843 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302844 if (tb[PARAM_NUM_NW]) {
2845 count = nla_get_u32(
2846 tb[PARAM_NUM_NW]);
2847 } else {
2848 hdd_err("Number of networks is not provided");
2849 goto fail;
2850 }
2851
2852 if (count &&
2853 tb[PRAM_SSID_LIST]) {
2854 nla_for_each_nested(curr_attr,
2855 tb[PRAM_SSID_LIST], rem) {
2856 if (nla_parse(tb2,
2857 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2858 nla_data(curr_attr), nla_len(curr_attr),
2859 NULL)) {
2860 hdd_err("nla_parse failed");
2861 goto fail;
2862 }
2863 /* Parse and Fetch allowed SSID list*/
2864 if (!tb2[PARAM_LIST_SSID]) {
2865 hdd_err("attr allowed ssid failed");
2866 goto fail;
2867 }
2868 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2869 /*
2870 * Upper Layers include a null termination
2871 * character. Check for the actual permissible
2872 * length of SSID and also ensure not to copy
2873 * the NULL termination character to the driver
2874 * buffer.
2875 */
2876 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2877 ((buf_len - 1) <=
2878 SIR_MAC_MAX_SSID_LENGTH)) {
2879 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302881 tb2[PARAM_LIST_SSID], buf_len - 1);
2882 roam_params.ssid_allowed_list[i].length
2883 = buf_len - 1;
2884 hdd_debug("SSID[%d]: %.*s,length = %d",
2885 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 roam_params.ssid_allowed_list[i].length,
2887 roam_params.ssid_allowed_list[i].ssId,
2888 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302889 i++;
2890 } else {
2891 hdd_err("Invalid buffer length");
2892 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 }
2894 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302895 if (i != count) {
2896 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2897 i, count);
2898 goto fail;
2899 }
2900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002902 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002903 roam_params.num_ssid_allowed_list);
2904 sme_update_roam_params(pHddCtx->hHal, session_id,
2905 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2906 break;
2907 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2908 /* Parse and fetch 5G Boost Threshold */
2909 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002910 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 goto fail;
2912 }
2913 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2914 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002915 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 roam_params.raise_rssi_thresh_5g);
2917 /* Parse and fetch 5G Penalty Threshold */
2918 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002919 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 goto fail;
2921 }
2922 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2923 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002924 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 roam_params.drop_rssi_thresh_5g);
2926 /* Parse and fetch 5G Boost Factor */
2927 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002928 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 goto fail;
2930 }
2931 roam_params.raise_factor_5g = nla_get_u32(
2932 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002933 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 roam_params.raise_factor_5g);
2935 /* Parse and fetch 5G Penalty factor */
2936 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002937 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002938 goto fail;
2939 }
2940 roam_params.drop_factor_5g = nla_get_u32(
2941 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002942 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 roam_params.drop_factor_5g);
2944 /* Parse and fetch 5G Max Boost */
2945 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002946 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 goto fail;
2948 }
2949 roam_params.max_raise_rssi_5g = nla_get_u32(
2950 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 roam_params.max_raise_rssi_5g);
2953 /* Parse and fetch Rssi Diff */
2954 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002955 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002956 goto fail;
2957 }
2958 roam_params.rssi_diff = nla_get_s32(
2959 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002960 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 roam_params.rssi_diff);
2962 /* Parse and fetch Alert Rssi Threshold */
2963 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002964 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 goto fail;
2966 }
2967 roam_params.alert_rssi_threshold = nla_get_u32(
2968 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002969 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002970 roam_params.alert_rssi_threshold);
2971 sme_update_roam_params(pHddCtx->hHal, session_id,
2972 roam_params,
2973 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2974 break;
2975 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2976 /* Parse and fetch Activate Good Rssi Roam */
2977 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002978 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979 goto fail;
2980 }
2981 roam_params.good_rssi_roam = nla_get_s32(
2982 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002983 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 roam_params.good_rssi_roam);
2985 sme_update_roam_params(pHddCtx->hHal, session_id,
2986 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2987 break;
2988 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2989 /* Parse and fetch number of preferred BSSID */
2990 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002991 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 goto fail;
2993 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002994 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002996 if (count > MAX_BSSID_FAVORED) {
2997 hdd_err("Preferred BSSID count %u exceeds max %u",
2998 count, MAX_BSSID_FAVORED);
2999 goto fail;
3000 }
3001 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 i = 0;
3003 nla_for_each_nested(curr_attr,
3004 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3005 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003006
3007 if (i == count) {
3008 hdd_warn("Ignoring excess Preferred BSSID");
3009 break;
3010 }
3011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 if (nla_parse(tb2,
3013 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3014 nla_data(curr_attr), nla_len(curr_attr),
3015 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003016 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 goto fail;
3018 }
3019 /* Parse and fetch MAC address */
3020 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003021 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022 goto fail;
3023 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003024 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303026 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003027 hdd_debug(MAC_ADDRESS_STR,
3028 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 /* Parse and fetch preference factor*/
3030 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003031 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003032 goto fail;
3033 }
3034 roam_params.bssid_favored_factor[i] = nla_get_u32(
3035 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003036 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 roam_params.bssid_favored_factor[i]);
3038 i++;
3039 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003040 if (i < count)
3041 hdd_warn("Num Preferred BSSID %u less than expected %u",
3042 i, count);
3043 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044 sme_update_roam_params(pHddCtx->hHal, session_id,
3045 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3046 break;
3047 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3048 /* Parse and fetch number of blacklist BSSID */
3049 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003050 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 goto fail;
3052 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003053 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003055 if (count > MAX_BSSID_AVOID_LIST) {
3056 hdd_err("Blacklist BSSID count %u exceeds max %u",
3057 count, MAX_BSSID_AVOID_LIST);
3058 goto fail;
3059 }
3060 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303062
3063 if (count &&
3064 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3065 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3067 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003068
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303069 if (i == count) {
3070 hdd_warn("Ignoring excess Blacklist BSSID");
3071 break;
3072 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003073
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303074 if (nla_parse(tb2,
3075 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3076 nla_data(curr_attr), nla_len(curr_attr),
3077 NULL)) {
3078 hdd_err("nla_parse failed");
3079 goto fail;
3080 }
3081 /* Parse and fetch MAC address */
3082 if (!tb2[PARAM_SET_BSSID]) {
3083 hdd_err("attr blacklist addr failed");
3084 goto fail;
3085 }
3086 nla_memcpy(
3087 roam_params.bssid_avoid_list[i].bytes,
3088 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3089 hdd_debug(MAC_ADDRESS_STR,
3090 MAC_ADDR_ARRAY(
3091 roam_params.bssid_avoid_list[i].bytes));
3092 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003094 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003095 if (i < count)
3096 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3097 i, count);
3098 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 sme_update_roam_params(pHddCtx->hHal, session_id,
3100 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3101 break;
3102 }
3103 return 0;
3104fail:
3105 return -EINVAL;
3106}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303107#undef PARAM_NUM_NW
3108#undef PARAM_SET_BSSID
3109#undef PRAM_SSID_LIST
3110#undef PARAM_LIST_SSID
3111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112
3113/**
3114 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3115 * @wiphy: pointer to wireless wiphy structure.
3116 * @wdev: pointer to wireless_dev structure.
3117 * @data: Pointer to the data to be passed via vendor interface
3118 * @data_len:Length of the data to be passed
3119 *
3120 * Return: Return the Success or Failure code.
3121 */
3122static int
3123wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3124 struct wireless_dev *wdev,
3125 const void *data,
3126 int data_len)
3127{
3128 int ret;
3129
3130 cds_ssr_protect(__func__);
3131 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3132 data, data_len);
3133 cds_ssr_unprotect(__func__);
3134
3135 return ret;
3136}
3137
3138static const struct nla_policy
3139wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3140 +1] = {
3141 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3142};
3143
3144/**
3145 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3146 * @hdd_ctx: HDD context
3147 * @device_mode: device mode
3148 * Return: bool
3149 */
3150static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003151 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152{
3153 hdd_adapter_t *adapter;
3154 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3155 hdd_ap_ctx_t *ap_ctx;
3156 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303157 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303159 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 &adapter_node);
3161
3162 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303163 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 adapter = adapter_node->pAdapter;
3165
3166 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003167 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 ap_ctx =
3169 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3170
3171 /*
3172 * if there is SAP already running on DFS channel,
3173 * do not disable scan on dfs channels. Note that
3174 * with SAP on DFS, there cannot be conurrency on
3175 * single radio. But then we can have multiple
3176 * radios !!
3177 */
3178 if (CHANNEL_STATE_DFS ==
3179 cds_get_channel_state(
3180 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003181 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 return true;
3183 }
3184 }
3185
3186 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003187 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 sta_ctx =
3189 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3190
3191 /*
3192 * if STA is already connected on DFS channel,
3193 * do not disable scan on dfs channels
3194 */
3195 if (hdd_conn_is_connected(sta_ctx) &&
3196 (CHANNEL_STATE_DFS ==
3197 cds_get_channel_state(
3198 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003199 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200 return true;
3201 }
3202 }
3203
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303204 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 adapter_node,
3206 &next);
3207 adapter_node = next;
3208 }
3209
3210 return false;
3211}
3212
3213/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003214 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3215 * @hdd_ctx: HDD context within host driver
3216 * @adapter: Adapter pointer
3217 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3218 *
3219 * Loops through devices to see who is operating on DFS channels
3220 * and then disables/enables DFS channels by calling SME API.
3221 * Fails the disable request if any device is active on a DFS channel.
3222 *
3223 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003225
3226int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3227 hdd_adapter_t *adapter,
3228 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303231 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233
3234 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3235 if (no_dfs_flag) {
3236 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003237 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238
3239 if (true == status)
3240 return -EOPNOTSUPP;
3241
3242 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003243 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
3245 if (true == status)
3246 return -EOPNOTSUPP;
3247 }
3248
3249 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3250
3251 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3252
3253 /*
3254 * call the SME API to tunnel down the new channel list
3255 * to the firmware
3256 */
3257 status = sme_handle_dfs_chan_scan(
3258 h_hal, hdd_ctx->config->enableDFSChnlScan);
3259
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303260 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 ret_val = 0;
3262
3263 /*
3264 * Clear the SME scan cache also. Note that the
3265 * clearing of scan results is independent of session;
3266 * so no need to iterate over
3267 * all sessions
3268 */
3269 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303270 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271 ret_val = -EPERM;
3272 }
3273
3274 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003275 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 ret_val = 0;
3277 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003278 return ret_val;
3279}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003281/**
3282 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3283 * @wiphy: corestack handler
3284 * @wdev: wireless device
3285 * @data: data
3286 * @data_len: data length
3287 * Return: success(0) or reason code for failure
3288 */
3289static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3290 struct wireless_dev *wdev,
3291 const void *data,
3292 int data_len)
3293{
3294 struct net_device *dev = wdev->netdev;
3295 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3296 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3297 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3298 int ret_val;
3299 uint32_t no_dfs_flag = 0;
3300
Jeff Johnson1f61b612016-02-12 16:28:33 -08003301 ENTER_DEV(dev);
3302
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003303 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303304 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003305 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003306
3307 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3308 data, data_len,
3309 wlan_hdd_set_no_dfs_flag_config_policy)) {
3310 hdd_err("invalid attr");
3311 return -EINVAL;
3312 }
3313
3314 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3315 hdd_err("attr dfs flag failed");
3316 return -EINVAL;
3317 }
3318
3319 no_dfs_flag = nla_get_u32(
3320 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3321
Jeff Johnson020db452016-06-29 14:37:26 -07003322 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003323
3324 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003325 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003326 return -EINVAL;
3327 }
3328
3329 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3330 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 return ret_val;
3332}
3333
3334/**
3335 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3336 *
3337 * @wiphy: wiphy device pointer
3338 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003339 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340 * @data_len: Buffer length
3341 *
3342 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3343 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3344 *
3345 * Return: EOK or other error codes.
3346 */
3347
3348static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3349 struct wireless_dev *wdev,
3350 const void *data,
3351 int data_len)
3352{
3353 int ret;
3354
3355 cds_ssr_protect(__func__);
3356 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3357 data, data_len);
3358 cds_ssr_unprotect(__func__);
3359
3360 return ret;
3361}
3362
Manikandan Mohan80dea792016-04-28 16:36:48 -07003363static const struct nla_policy
3364wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3365 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3366};
3367
3368/**
3369 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3370 * @wiphy: wiphy device pointer
3371 * @wdev: wireless device pointer
3372 * @data: Vendor command data buffer
3373 * @data_len: Buffer length
3374 *
3375 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3376 * setup WISA Mode features.
3377 *
3378 * Return: Success(0) or reason code for failure
3379 */
3380static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3381 struct wireless_dev *wdev, const void *data, int data_len)
3382{
3383 struct net_device *dev = wdev->netdev;
3384 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3385 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3386 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3387 struct sir_wisa_params wisa;
3388 int ret_val;
3389 QDF_STATUS status;
3390 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003391 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3392 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003393
3394 ENTER_DEV(dev);
3395 ret_val = wlan_hdd_validate_context(hdd_ctx);
3396 if (ret_val)
3397 goto err;
3398
3399 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3400 hdd_err("Command not allowed in FTM mode");
3401 return -EPERM;
3402 }
3403
3404 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3405 wlan_hdd_wisa_cmd_policy)) {
3406 hdd_err("Invalid WISA cmd attributes");
3407 ret_val = -EINVAL;
3408 goto err;
3409 }
3410 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3411 hdd_err("Invalid WISA mode");
3412 ret_val = -EINVAL;
3413 goto err;
3414 }
3415
3416 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3417 hdd_info("WISA Mode: %d", wisa_mode);
3418 wisa.mode = wisa_mode;
3419 wisa.vdev_id = adapter->sessionId;
3420 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003421 if (!QDF_IS_STATUS_SUCCESS(status)) {
3422 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003423 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003424 }
3425 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003426 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003427 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3428 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003429 adapter->sessionId),
3430 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003431err:
3432 EXIT();
3433 return ret_val;
3434}
3435
3436/**
3437 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3438 * @wiphy: corestack handler
3439 * @wdev: wireless device
3440 * @data: data
3441 * @data_len: data length
3442 *
3443 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3444 * setup WISA mode features.
3445 *
3446 * Return: Success(0) or reason code for failure
3447 */
3448static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3449 struct wireless_dev *wdev,
3450 const void *data,
3451 int data_len)
3452{
3453 int ret;
3454
3455 cds_ssr_protect(__func__);
3456 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3457 cds_ssr_unprotect(__func__);
3458
3459 return ret;
3460}
3461
Anurag Chouhan96919482016-07-13 16:36:57 +05303462/*
3463 * define short names for the global vendor params
3464 * used by __wlan_hdd_cfg80211_get_station_cmd()
3465 */
3466#define STATION_INVALID \
3467 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3468#define STATION_INFO \
3469 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3470#define STATION_ASSOC_FAIL_REASON \
3471 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3472#define STATION_MAX \
3473 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3474
3475static const struct nla_policy
3476hdd_get_station_policy[STATION_MAX + 1] = {
3477 [STATION_INFO] = {.type = NLA_FLAG},
3478 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3479};
3480
3481/**
3482 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3483 * @hdd_ctx: HDD context within host driver
3484 * @wdev: wireless device
3485 *
3486 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3487 * Validate cmd attributes and send the station info to upper layers.
3488 *
3489 * Return: Success(0) or reason code for failure
3490 */
3491static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3492 hdd_adapter_t *adapter)
3493{
3494 struct sk_buff *skb = NULL;
3495 uint32_t nl_buf_len;
3496 hdd_station_ctx_t *hdd_sta_ctx;
3497
3498 nl_buf_len = NLMSG_HDRLEN;
3499 nl_buf_len += sizeof(uint32_t);
3500 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3501
3502 if (!skb) {
3503 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3504 return -ENOMEM;
3505 }
3506
3507 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3508
3509 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3510 hdd_sta_ctx->conn_info.assoc_status_code)) {
3511 hdd_err("put fail");
3512 goto fail;
3513 }
3514 return cfg80211_vendor_cmd_reply(skb);
3515fail:
3516 if (skb)
3517 kfree_skb(skb);
3518 return -EINVAL;
3519}
3520
3521/**
3522 * hdd_map_auth_type() - transform auth type specific to
3523 * vendor command
3524 * @auth_type: csr auth type
3525 *
3526 * Return: Success(0) or reason code for failure
3527 */
3528static int hdd_convert_auth_type(uint32_t auth_type)
3529{
3530 uint32_t ret_val;
3531
3532 switch (auth_type) {
3533 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3534 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3535 break;
3536 case eCSR_AUTH_TYPE_SHARED_KEY:
3537 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3538 break;
3539 case eCSR_AUTH_TYPE_WPA:
3540 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3541 break;
3542 case eCSR_AUTH_TYPE_WPA_PSK:
3543 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3544 break;
3545 case eCSR_AUTH_TYPE_AUTOSWITCH:
3546 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3547 break;
3548 case eCSR_AUTH_TYPE_WPA_NONE:
3549 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3550 break;
3551 case eCSR_AUTH_TYPE_RSN:
3552 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3553 break;
3554 case eCSR_AUTH_TYPE_RSN_PSK:
3555 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3556 break;
3557 case eCSR_AUTH_TYPE_FT_RSN:
3558 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3559 break;
3560 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3561 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3562 break;
3563 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3564 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3565 break;
3566 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3567 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3568 break;
3569 case eCSR_AUTH_TYPE_CCKM_WPA:
3570 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3571 break;
3572 case eCSR_AUTH_TYPE_CCKM_RSN:
3573 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3574 break;
3575 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3576 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3577 break;
3578 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3579 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3580 break;
3581 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3582 case eCSR_AUTH_TYPE_FAILED:
3583 case eCSR_AUTH_TYPE_NONE:
3584 default:
3585 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3586 break;
3587 }
3588 return ret_val;
3589}
3590
3591/**
3592 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3593 * vendor command
3594 * @dot11mode: dot11mode
3595 *
3596 * Return: Success(0) or reason code for failure
3597 */
3598static int hdd_convert_dot11mode(uint32_t dot11mode)
3599{
3600 uint32_t ret_val;
3601
3602 switch (dot11mode) {
3603 case eCSR_CFG_DOT11_MODE_11A:
3604 ret_val = QCA_WLAN_802_11_MODE_11A;
3605 break;
3606 case eCSR_CFG_DOT11_MODE_11B:
3607 ret_val = QCA_WLAN_802_11_MODE_11B;
3608 break;
3609 case eCSR_CFG_DOT11_MODE_11G:
3610 ret_val = QCA_WLAN_802_11_MODE_11G;
3611 break;
3612 case eCSR_CFG_DOT11_MODE_11N:
3613 ret_val = QCA_WLAN_802_11_MODE_11N;
3614 break;
3615 case eCSR_CFG_DOT11_MODE_11AC:
3616 ret_val = QCA_WLAN_802_11_MODE_11AC;
3617 break;
3618 case eCSR_CFG_DOT11_MODE_AUTO:
3619 case eCSR_CFG_DOT11_MODE_ABG:
3620 default:
3621 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3622 }
3623 return ret_val;
3624}
3625
3626/**
3627 * hdd_add_tx_bitrate() - add tx bitrate attribute
3628 * @skb: pointer to sk buff
3629 * @hdd_sta_ctx: pointer to hdd station context
3630 * @idx: attribute index
3631 *
3632 * Return: Success(0) or reason code for failure
3633 */
3634static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3635 hdd_station_ctx_t *hdd_sta_ctx,
3636 int idx)
3637{
3638 struct nlattr *nla_attr;
3639 uint32_t bitrate, bitrate_compat;
3640
3641 nla_attr = nla_nest_start(skb, idx);
3642 if (!nla_attr)
3643 goto fail;
3644 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3645 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3646
3647 /* report 16-bit bitrate only if we can */
3648 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3649 if (bitrate > 0 &&
3650 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3651 hdd_err("put fail");
3652 goto fail;
3653 }
3654 if (bitrate_compat > 0 &&
3655 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3656 hdd_err("put fail");
3657 goto fail;
3658 }
3659 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3660 hdd_sta_ctx->conn_info.txrate.nss)) {
3661 hdd_err("put fail");
3662 goto fail;
3663 }
3664 nla_nest_end(skb, nla_attr);
3665 return 0;
3666fail:
3667 return -EINVAL;
3668}
3669
3670/**
3671 * hdd_add_sta_info() - add station info attribute
3672 * @skb: pointer to sk buff
3673 * @hdd_sta_ctx: pointer to hdd station context
3674 * @idx: attribute index
3675 *
3676 * Return: Success(0) or reason code for failure
3677 */
3678static int32_t hdd_add_sta_info(struct sk_buff *skb,
3679 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3680{
3681 struct nlattr *nla_attr;
3682
3683 nla_attr = nla_nest_start(skb, idx);
3684 if (!nla_attr)
3685 goto fail;
3686 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3687 (hdd_sta_ctx->conn_info.signal + 100))) {
3688 hdd_err("put fail");
3689 goto fail;
3690 }
3691 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3692 goto fail;
3693 nla_nest_end(skb, nla_attr);
3694 return 0;
3695fail:
3696 return -EINVAL;
3697}
3698
3699/**
3700 * hdd_add_survey_info() - add survey info attribute
3701 * @skb: pointer to sk buff
3702 * @hdd_sta_ctx: pointer to hdd station context
3703 * @idx: attribute index
3704 *
3705 * Return: Success(0) or reason code for failure
3706 */
3707static int32_t hdd_add_survey_info(struct sk_buff *skb,
3708 hdd_station_ctx_t *hdd_sta_ctx,
3709 int idx)
3710{
3711 struct nlattr *nla_attr;
3712
3713 nla_attr = nla_nest_start(skb, idx);
3714 if (!nla_attr)
3715 goto fail;
3716 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3717 hdd_sta_ctx->conn_info.freq) ||
3718 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3719 (hdd_sta_ctx->conn_info.noise + 100))) {
3720 hdd_err("put fail");
3721 goto fail;
3722 }
3723 nla_nest_end(skb, nla_attr);
3724 return 0;
3725fail:
3726 return -EINVAL;
3727}
3728
3729/**
3730 * hdd_add_link_standard_info() - add link info attribute
3731 * @skb: pointer to sk buff
3732 * @hdd_sta_ctx: pointer to hdd station context
3733 * @idx: attribute index
3734 *
3735 * Return: Success(0) or reason code for failure
3736 */
3737static int32_t
3738hdd_add_link_standard_info(struct sk_buff *skb,
3739 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3740{
3741 struct nlattr *nla_attr;
3742
3743 nla_attr = nla_nest_start(skb, idx);
3744 if (!nla_attr)
3745 goto fail;
3746 if (nla_put(skb,
3747 NL80211_ATTR_SSID,
3748 hdd_sta_ctx->conn_info.SSID.SSID.length,
3749 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3750 hdd_err("put fail");
3751 goto fail;
3752 }
3753 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3754 goto fail;
3755 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3756 goto fail;
3757 nla_nest_end(skb, nla_attr);
3758 return 0;
3759fail:
3760 return -EINVAL;
3761}
3762
3763/**
3764 * hdd_add_ap_standard_info() - add ap info attribute
3765 * @skb: pointer to sk buff
3766 * @hdd_sta_ctx: pointer to hdd station context
3767 * @idx: attribute index
3768 *
3769 * Return: Success(0) or reason code for failure
3770 */
3771static int32_t
3772hdd_add_ap_standard_info(struct sk_buff *skb,
3773 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3774{
3775 struct nlattr *nla_attr;
3776
3777 nla_attr = nla_nest_start(skb, idx);
3778 if (!nla_attr)
3779 goto fail;
3780 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3781 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3782 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3783 &hdd_sta_ctx->conn_info.vht_caps)) {
3784 hdd_err("put fail");
3785 goto fail;
3786 }
3787 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3788 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3789 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3790 &hdd_sta_ctx->conn_info.ht_caps)) {
3791 hdd_err("put fail");
3792 goto fail;
3793 }
3794 nla_nest_end(skb, nla_attr);
3795 return 0;
3796fail:
3797 return -EINVAL;
3798}
3799
3800/**
3801 * hdd_get_station_info() - send BSS information to supplicant
3802 * @hdd_ctx: pointer to hdd context
3803 * @adapter: pointer to adapter
3804 *
3805 * Return: 0 if success else error status
3806 */
3807static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3808 hdd_adapter_t *adapter)
3809{
3810 struct sk_buff *skb = NULL;
3811 uint8_t *tmp_hs20 = NULL;
3812 uint32_t nl_buf_len;
3813 hdd_station_ctx_t *hdd_sta_ctx;
3814
3815 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3816
3817 nl_buf_len = NLMSG_HDRLEN;
3818 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3819 sizeof(hdd_sta_ctx->conn_info.freq) +
3820 sizeof(hdd_sta_ctx->conn_info.noise) +
3821 sizeof(hdd_sta_ctx->conn_info.signal) +
3822 (sizeof(uint32_t) * 2) +
3823 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3824 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3825 sizeof(hdd_sta_ctx->conn_info.authType) +
3826 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3827 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3828 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3829 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3830 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3831 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3832 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3833 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3834 1);
3835 }
3836 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3837 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3838 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3839 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3840
3841
3842 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3843 if (!skb) {
3844 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3845 return -ENOMEM;
3846 }
3847
3848 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3849 LINK_INFO_STANDARD_NL80211_ATTR)) {
3850 hdd_err("put fail");
3851 goto fail;
3852 }
3853 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3854 AP_INFO_STANDARD_NL80211_ATTR)) {
3855 hdd_err("put fail");
3856 goto fail;
3857 }
3858 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3859 hdd_sta_ctx->conn_info.roam_count) ||
3860 nla_put_u32(skb, INFO_AKM,
3861 hdd_convert_auth_type(
3862 hdd_sta_ctx->conn_info.authType)) ||
3863 nla_put_u32(skb, WLAN802_11_MODE,
3864 hdd_convert_dot11mode(
3865 hdd_sta_ctx->conn_info.dot11Mode))) {
3866 hdd_err("put fail");
3867 goto fail;
3868 }
3869 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3870 if (nla_put(skb, HT_OPERATION,
3871 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3872 &hdd_sta_ctx->conn_info.ht_operation)) {
3873 hdd_err("put fail");
3874 goto fail;
3875 }
3876 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3877 if (nla_put(skb, VHT_OPERATION,
3878 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3879 &hdd_sta_ctx->conn_info.vht_operation)) {
3880 hdd_err("put fail");
3881 goto fail;
3882 }
3883 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3884 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3885 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3886 tmp_hs20 + 1)) {
3887 hdd_err("put fail");
3888 goto fail;
3889 }
3890
3891 return cfg80211_vendor_cmd_reply(skb);
3892fail:
3893 if (skb)
3894 kfree_skb(skb);
3895 return -EINVAL;
3896}
3897
3898/**
3899 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3900 * @wiphy: corestack handler
3901 * @wdev: wireless device
3902 * @data: data
3903 * @data_len: data length
3904 *
3905 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3906 * Validate cmd attributes and send the station info to upper layers.
3907 *
3908 * Return: Success(0) or reason code for failure
3909 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303910static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303911__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3912 struct wireless_dev *wdev,
3913 const void *data,
3914 int data_len)
3915{
3916 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3917 struct net_device *dev = wdev->netdev;
3918 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3919 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3920 int32_t status;
3921
3922 ENTER_DEV(dev);
3923 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3924 hdd_err("Command not allowed in FTM mode");
3925 status = -EPERM;
3926 goto out;
3927 }
3928
3929 status = wlan_hdd_validate_context(hdd_ctx);
3930 if (0 != status)
3931 goto out;
3932
3933
3934 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3935 data, data_len, NULL);
3936 if (status) {
3937 hdd_err("Invalid ATTR");
3938 goto out;
3939 }
3940
3941 /* Parse and fetch Command Type*/
3942 if (tb[STATION_INFO]) {
3943 status = hdd_get_station_info(hdd_ctx, adapter);
3944 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3945 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3946 } else {
3947 hdd_err("get station info cmd type failed");
3948 status = -EINVAL;
3949 goto out;
3950 }
3951 EXIT();
3952out:
3953 return status;
3954}
3955
3956/**
3957 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3958 * @wiphy: corestack handler
3959 * @wdev: wireless device
3960 * @data: data
3961 * @data_len: data length
3962 *
3963 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3964 * Validate cmd attributes and send the station info to upper layers.
3965 *
3966 * Return: Success(0) or reason code for failure
3967 */
3968static int32_t
3969hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3970 struct wireless_dev *wdev,
3971 const void *data,
3972 int data_len)
3973{
3974 int ret;
3975
3976 cds_ssr_protect(__func__);
3977 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3978 cds_ssr_unprotect(__func__);
3979
3980 return ret;
3981}
3982
3983/*
3984 * undef short names defined for get station command
3985 * used by __wlan_hdd_cfg80211_get_station_cmd()
3986 */
3987#undef STATION_INVALID
3988#undef STATION_INFO
3989#undef STATION_ASSOC_FAIL_REASON
3990#undef STATION_MAX
3991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3993/**
3994 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3995 * @wiphy: pointer to wireless wiphy structure.
3996 * @wdev: pointer to wireless_dev structure.
3997 * @data: Pointer to the Key data
3998 * @data_len:Length of the data passed
3999 *
4000 * This is called when wlan driver needs to save the keys received via
4001 * vendor specific command.
4002 *
4003 * Return: Return the Success or Failure code.
4004 */
4005static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4006 struct wireless_dev *wdev,
4007 const void *data, int data_len)
4008{
4009 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4010 struct net_device *dev = wdev->netdev;
4011 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4012 hdd_context_t *hdd_ctx_ptr;
4013 int status;
4014
Jeff Johnson1f61b612016-02-12 16:28:33 -08004015 ENTER_DEV(dev);
4016
Anurag Chouhan6d760662016-02-20 16:05:43 +05304017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018 hdd_err("Command not allowed in FTM mode");
4019 return -EPERM;
4020 }
4021
4022 if ((data == NULL) || (data_len == 0) ||
4023 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004024 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025 return -EINVAL;
4026 }
4027
4028 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4029 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004030 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 return -EINVAL;
4032 }
4033
4034 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304035 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4038 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004039 true,
4040 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304041 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4042 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4044 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4045 return 0;
4046}
4047
4048/**
4049 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4050 * @wiphy: pointer to wireless wiphy structure.
4051 * @wdev: pointer to wireless_dev structure.
4052 * @data: Pointer to the Key data
4053 * @data_len:Length of the data passed
4054 *
4055 * This is called when wlan driver needs to save the keys received via
4056 * vendor specific command.
4057 *
4058 * Return: Return the Success or Failure code.
4059 */
4060static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4061 struct wireless_dev *wdev,
4062 const void *data, int data_len)
4063{
4064 int ret;
4065
4066 cds_ssr_protect(__func__);
4067 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4068 cds_ssr_unprotect(__func__);
4069
4070 return ret;
4071}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004072#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073
4074static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4075 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4076 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4077 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004078 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079};
4080
4081/**
4082 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4083 * @wiphy: pointer to wireless wiphy structure.
4084 * @wdev: pointer to wireless_dev structure.
4085 * @data: Pointer to the data to be passed via vendor interface
4086 * @data_len:Length of the data to be passed
4087 *
4088 * This is called when wlan driver needs to send wifi driver related info
4089 * (driver/fw version) to the user space application upon request.
4090 *
4091 * Return: Return the Success or Failure code.
4092 */
4093static int
4094__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4095 struct wireless_dev *wdev,
4096 const void *data, int data_len)
4097{
4098 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4099 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004100 tSirVersionString driver_version;
4101 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004103 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004104 struct sk_buff *reply_skb;
4105 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106
Jeff Johnson1f61b612016-02-12 16:28:33 -08004107 ENTER_DEV(wdev->netdev);
4108
Anurag Chouhan6d760662016-02-20 16:05:43 +05304109 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004110 hdd_err("Command not allowed in FTM mode");
4111 return -EPERM;
4112 }
4113
4114 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304115 if (status)
4116 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004117
4118 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4119 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004120 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 return -EINVAL;
4122 }
4123
4124 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004125 hdd_err("Rcvd req for Driver version");
4126 strlcpy(driver_version, QWLAN_VERSIONSTR,
4127 sizeof(driver_version));
4128 skb_len += strlen(driver_version) + 1;
4129 count++;
4130 }
4131
4132 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4133 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4135 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004136 snprintf(firmware_version, sizeof(firmware_version),
4137 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4138 skb_len += strlen(firmware_version) + 1;
4139 count++;
4140 }
4141
4142 if (count == 0) {
4143 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144 return -EINVAL;
4145 }
4146
Ryan Hsu7ac88852016-04-28 10:20:34 -07004147 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4148 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004151 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152 return -ENOMEM;
4153 }
4154
Ryan Hsu7ac88852016-04-28 10:20:34 -07004155 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4156 if (nla_put_string(reply_skb,
4157 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4158 driver_version))
4159 goto error_nla_fail;
4160 }
4161
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304162 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004163 if (nla_put_string(reply_skb,
4164 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4165 firmware_version))
4166 goto error_nla_fail;
4167 }
4168
4169 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4170 if (nla_put_u32(reply_skb,
4171 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4172 hdd_ctx->radio_index))
4173 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174 }
4175
4176 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004177
4178error_nla_fail:
4179 hdd_err("nla put fail");
4180 kfree_skb(reply_skb);
4181 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004182}
4183
4184/**
4185 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4186 * @wiphy: pointer to wireless wiphy structure.
4187 * @wdev: pointer to wireless_dev structure.
4188 * @data: Pointer to the data to be passed via vendor interface
4189 * @data_len:Length of the data to be passed
4190 *
4191 * This is called when wlan driver needs to send wifi driver related info
4192 * (driver/fw version) to the user space application upon request.
4193 *
4194 * Return: Return the Success or Failure code.
4195 */
4196static int
4197wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4198 struct wireless_dev *wdev,
4199 const void *data, int data_len)
4200{
4201 int ret;
4202
4203 cds_ssr_protect(__func__);
4204 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4205 cds_ssr_unprotect(__func__);
4206
4207 return ret;
4208}
4209
4210/**
4211 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4212 * @wiphy: pointer to wireless wiphy structure.
4213 * @wdev: pointer to wireless_dev structure.
4214 * @data: Pointer to the data to be passed via vendor interface
4215 * @data_len:Length of the data to be passed
4216 *
4217 * This is called by userspace to know the supported logger features
4218 *
4219 * Return: Return the Success or Failure code.
4220 */
4221static int
4222__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4223 struct wireless_dev *wdev,
4224 const void *data, int data_len)
4225{
4226 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4227 int status;
4228 uint32_t features;
4229 struct sk_buff *reply_skb = NULL;
4230
Jeff Johnson1f61b612016-02-12 16:28:33 -08004231 ENTER_DEV(wdev->netdev);
4232
Anurag Chouhan6d760662016-02-20 16:05:43 +05304233 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004234 hdd_err("Command not allowed in FTM mode");
4235 return -EPERM;
4236 }
4237
4238 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304239 if (status)
4240 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004241
4242 features = 0;
4243
4244 if (hdd_is_memdump_supported())
4245 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4246 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4247 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4248 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4249
4250 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4251 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4252 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004253 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 return -ENOMEM;
4255 }
4256
Jeff Johnson020db452016-06-29 14:37:26 -07004257 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004258 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4259 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004260 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 kfree_skb(reply_skb);
4262 return -EINVAL;
4263 }
4264
4265 return cfg80211_vendor_cmd_reply(reply_skb);
4266}
4267
4268/**
4269 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4270 * @wiphy: pointer to wireless wiphy structure.
4271 * @wdev: pointer to wireless_dev structure.
4272 * @data: Pointer to the data to be passed via vendor interface
4273 * @data_len:Length of the data to be passed
4274 *
4275 * This is called by userspace to know the supported logger features
4276 *
4277 * Return: Return the Success or Failure code.
4278 */
4279static int
4280wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4281 struct wireless_dev *wdev,
4282 const void *data, int data_len)
4283{
4284 int ret;
4285
4286 cds_ssr_protect(__func__);
4287 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4288 data, data_len);
4289 cds_ssr_unprotect(__func__);
4290
4291 return ret;
4292}
4293
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004294#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004295/**
4296 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304297 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298 * @bssid: pointer to bssid of roamed AP.
4299 * @req_rsn_ie: Pointer to request RSN IE
4300 * @req_rsn_len: Length of the request RSN IE
4301 * @rsp_rsn_ie: Pointer to response RSN IE
4302 * @rsp_rsn_len: Length of the response RSN IE
4303 * @roam_info_ptr: Pointer to the roaming related information
4304 *
4305 * This is called when wlan driver needs to send the roaming and
4306 * authorization information after roaming.
4307 *
4308 * The information that would be sent is the request RSN IE, response
4309 * RSN IE and BSSID of the newly roamed AP.
4310 *
4311 * If the Authorized status is authenticated, then additional parameters
4312 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4313 * supplicant.
4314 *
4315 * The supplicant upon receiving this event would ignore the legacy
4316 * cfg80211_roamed call and use the entire information from this event.
4317 * The cfg80211_roamed should still co-exist since the kernel will
4318 * make use of the parameters even if the supplicant ignores it.
4319 *
4320 * Return: Return the Success or Failure code.
4321 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304322int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4324 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4325{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304326 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004327 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004328 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329 ENTER();
4330
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304331 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004332 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004334 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004335 !roam_info_ptr->roamSynchInProgress)
4336 return 0;
4337
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304339 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004340 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4341 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4342 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004343 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4345 GFP_KERNEL);
4346
4347 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004348 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 return -EINVAL;
4350 }
4351
4352 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4353 ETH_ALEN, bssid) ||
4354 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4355 req_rsn_len, req_rsn_ie) ||
4356 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4357 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004358 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 goto nla_put_failure;
4360 }
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 if (roam_info_ptr->synchAuthStatus ==
4363 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004364 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004365 if (nla_put_u8(skb,
4366 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4367 hdd_err("nla put fail");
4368 goto nla_put_failure;
4369 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004370 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4371 /* if FT or CCKM connection: dont send replay counter */
4372 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4373 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4374 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4375 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4376 nla_put(skb,
4377 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4378 SIR_REPLAY_CTR_LEN,
4379 roam_info_ptr->replay_ctr)) {
4380 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004381 hdd_err("failed to send replay counter.");
4382 goto nla_put_failure;
4383 }
4384 if (nla_put(skb,
4385 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4386 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4387 nla_put(skb,
4388 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4389 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4390 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 goto nla_put_failure;
4392 }
4393 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004394 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4396 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004397 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 goto nla_put_failure;
4399 }
4400 }
4401
Jeff Johnson020db452016-06-29 14:37:26 -07004402 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004403 roam_info_ptr->subnet_change_status);
4404
4405 /*
4406 * Add subnet change status if subnet has changed
4407 * 0 = unchanged
4408 * 1 = changed
4409 * 2 = unknown
4410 */
4411 if (roam_info_ptr->subnet_change_status) {
4412 if (nla_put_u8(skb,
4413 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4414 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004415 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004416 goto nla_put_failure;
4417 }
4418 }
4419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004420 cfg80211_vendor_event(skb, GFP_KERNEL);
4421 return 0;
4422
4423nla_put_failure:
4424 kfree_skb(skb);
4425 return -EINVAL;
4426}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004427#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428
4429static const struct nla_policy
4430wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4431
4432 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4433 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4434 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304435 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304436 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4437 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004438 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4439 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4440 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4441 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4442 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304443 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444};
4445
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304447 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4448 *
4449 * @adapter: Pointer to HDD adapter
4450 * @ie_data: Pointer to Scan IEs buffer
4451 * @ie_len: Length of Scan IEs
4452 *
4453 * Return: 0 on success; error number otherwise
4454 */
4455static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4456 uint8_t *ie_data, uint8_t ie_len)
4457{
4458 hdd_scaninfo_t *scan_info = NULL;
4459 scan_info = &adapter->scan_info;
4460
4461 if (scan_info->default_scan_ies) {
4462 qdf_mem_free(scan_info->default_scan_ies);
4463 scan_info->default_scan_ies = NULL;
4464 }
4465
4466 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4467 if (!scan_info->default_scan_ies)
4468 return -ENOMEM;
4469
4470 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4471 scan_info->default_scan_ies_len = ie_len;
4472 return 0;
4473}
4474
4475/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4477 * vendor command
4478 *
4479 * @wiphy: wiphy device pointer
4480 * @wdev: wireless device pointer
4481 * @data: Vendor command data buffer
4482 * @data_len: Buffer length
4483 *
4484 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4485 *
4486 * Return: Error code.
4487 */
4488static int
4489__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4490 struct wireless_dev *wdev,
4491 const void *data,
4492 int data_len)
4493{
4494 struct net_device *dev = wdev->netdev;
4495 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4496 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4497 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4498 int ret_val = 0;
4499 u32 modulated_dtim;
4500 u16 stats_avg_factor;
4501 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304502 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004503 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004504 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304505 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304506 int attr_len;
4507 int access_policy = 0;
4508 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4509 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304510 uint16_t scan_ie_len = 0;
4511 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304512 struct sir_set_tx_rx_aggregation_size request;
4513 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004514 uint8_t retry, delay;
4515 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304516 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304517
Jeff Johnson1f61b612016-02-12 16:28:33 -08004518 ENTER_DEV(dev);
4519
Anurag Chouhan6d760662016-02-20 16:05:43 +05304520 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 hdd_err("Command not allowed in FTM mode");
4522 return -EPERM;
4523 }
4524
4525 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304526 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528
4529 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4530 data, data_len,
4531 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004532 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 return -EINVAL;
4534 }
4535
Krunal Sonie3531942016-04-12 17:43:53 -07004536 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4537 ftm_capab = nla_get_u32(tb[
4538 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4539 hdd_ctx->config->fine_time_meas_cap =
4540 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4541 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304542 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004543 hdd_ctx->config->fine_time_meas_cap);
4544 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4545 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4546 hdd_ctx->config->fine_time_meas_cap);
4547 }
4548
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004549 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4550 modulated_dtim = nla_get_u32(
4551 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4552
4553 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4554 adapter->sessionId,
4555 modulated_dtim);
4556
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304557 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 ret_val = -EPERM;
4559 }
4560
Kapil Gupta6213c012016-09-02 19:39:09 +05304561 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4562 qpower = nla_get_u8(
4563 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4564 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4565 ret_val = -EINVAL;
4566 }
4567
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4569 stats_avg_factor = nla_get_u16(
4570 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4571 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4572 adapter->sessionId,
4573 stats_avg_factor);
4574
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304575 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 ret_val = -EPERM;
4577 }
4578
4579
4580 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4581 guard_time = nla_get_u32(
4582 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4583 status = sme_configure_guard_time(hdd_ctx->hHal,
4584 adapter->sessionId,
4585 guard_time);
4586
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304587 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 ret_val = -EPERM;
4589 }
4590
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304591 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4592 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4593 attr_len = nla_len(
4594 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4595 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4596 hdd_info("Invalid value. attr_len %d",
4597 attr_len);
4598 return -EINVAL;
4599 }
4600
4601 nla_memcpy(&vendor_ie,
4602 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4603 attr_len);
4604 vendor_ie_present = true;
4605 hdd_info("Access policy vendor ie present.attr_len %d",
4606 attr_len);
4607 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4608 &vendor_ie[0], attr_len);
4609 }
4610
4611 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4612 access_policy = (int) nla_get_u32(
4613 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4614 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4615 (access_policy >
4616 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4617 hdd_info("Invalid value. access_policy %d",
4618 access_policy);
4619 return -EINVAL;
4620 }
4621 access_policy_present = true;
4622 hdd_info("Access policy present. access_policy %d",
4623 access_policy);
4624 }
4625
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004626 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4627 retry = nla_get_u8(tb[
4628 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4629 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4630 CFG_NON_AGG_RETRY_MAX : retry;
4631 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4632 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4633 retry, PDEV_CMD);
4634 }
4635
4636 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4637 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4638 retry = retry > CFG_AGG_RETRY_MAX ?
4639 CFG_AGG_RETRY_MAX : retry;
4640
4641 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4642 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4643 CFG_AGG_RETRY_MIN : retry;
4644 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4645 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4646 retry, PDEV_CMD);
4647 }
4648
4649 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4650 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4651 retry = retry > CFG_MGMT_RETRY_MAX ?
4652 CFG_MGMT_RETRY_MAX : retry;
4653 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4654 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4655 retry, PDEV_CMD);
4656 }
4657
4658 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4659 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4660 retry = retry > CFG_CTRL_RETRY_MAX ?
4661 CFG_CTRL_RETRY_MAX : retry;
4662 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4663 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4664 retry, PDEV_CMD);
4665 }
4666
4667 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4668 delay = nla_get_u8(tb[
4669 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4670 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4671 CFG_PROPAGATION_DELAY_MAX : delay;
4672 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4673 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4674 delay, PDEV_CMD);
4675 }
4676
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304677 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4678 tx_fail_count = nla_get_u32(
4679 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4680 if (tx_fail_count) {
4681 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4682 adapter->sessionId, tx_fail_count);
4683 if (QDF_STATUS_SUCCESS != status) {
4684 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4685 status);
4686 return -EINVAL;
4687 }
4688 }
4689 }
4690
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304691 if (vendor_ie_present && access_policy_present) {
4692 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4693 access_policy =
4694 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304695 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304696 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304697 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304698
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304699 hdd_info("calling sme_update_access_policy_vendor_ie");
4700 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4701 adapter->sessionId, &vendor_ie[0],
4702 access_policy);
4703 if (QDF_STATUS_SUCCESS != status) {
4704 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304705 return -EINVAL;
4706 }
4707 }
4708
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304709 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4710 set_value = nla_get_u8(
4711 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4712 hdd_info("set_value: %d", set_value);
4713 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4714 }
4715
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304716 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4717 scan_ie_len = nla_len(
4718 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4719 hdd_info("Received default scan IE of len %d session %d device mode %d",
4720 scan_ie_len, adapter->sessionId,
4721 adapter->device_mode);
4722 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4723 scan_ie = (uint8_t *) nla_data(tb
4724 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304725
4726 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4727 scan_ie_len))
4728 hdd_err("Failed to save default scan IEs");
4729
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304730 if (adapter->device_mode == QDF_STA_MODE) {
4731 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4732 adapter->sessionId, scan_ie,
4733 scan_ie_len);
4734 if (QDF_STATUS_SUCCESS != status)
4735 ret_val = -EPERM;
4736 }
4737 } else
4738 ret_val = -EPERM;
4739 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304740
4741 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4742 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4743 /* if one is specified, both must be specified */
4744 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4745 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4746 hdd_err("Both TX and RX MPDU Aggregation required");
4747 return -EINVAL;
4748 }
4749
4750 request.tx_aggregation_size = nla_get_u8(
4751 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4752 request.rx_aggregation_size = nla_get_u8(
4753 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4754 request.vdev_id = adapter->sessionId;
4755
4756 if (request.tx_aggregation_size >=
4757 CFG_TX_AGGREGATION_SIZE_MIN &&
4758 request.tx_aggregation_size <=
4759 CFG_TX_AGGREGATION_SIZE_MAX &&
4760 request.rx_aggregation_size >=
4761 CFG_RX_AGGREGATION_SIZE_MIN &&
4762 request.rx_aggregation_size <=
4763 CFG_RX_AGGREGATION_SIZE_MAX) {
4764 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4765 if (qdf_status != QDF_STATUS_SUCCESS) {
4766 hdd_err("failed to set aggr sizes err %d",
4767 qdf_status);
4768 ret_val = -EPERM;
4769 }
4770 } else {
4771 hdd_err("TX %d RX %d MPDU aggr size not in range",
4772 request.tx_aggregation_size,
4773 request.rx_aggregation_size);
4774 ret_val = -EINVAL;
4775 }
4776 }
4777
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304778 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4779 uint8_t ignore_assoc_disallowed;
4780
4781 ignore_assoc_disallowed
4782 = nla_get_u8(tb[
4783 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4784 hdd_info("Set ignore_assoc_disallowed value - %d",
4785 ignore_assoc_disallowed);
4786 if ((ignore_assoc_disallowed <
4787 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4788 (ignore_assoc_disallowed >
4789 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4790 return -EPERM;
4791
4792 sme_update_session_param(hdd_ctx->hHal,
4793 adapter->sessionId,
4794 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4795 ignore_assoc_disallowed);
4796 }
4797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 return ret_val;
4799}
4800
4801/**
4802 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4803 * vendor command
4804 *
4805 * @wiphy: wiphy device pointer
4806 * @wdev: wireless device pointer
4807 * @data: Vendor command data buffer
4808 * @data_len: Buffer length
4809 *
4810 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4811 *
4812 * Return: EOK or other error codes.
4813 */
4814static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4815 struct wireless_dev *wdev,
4816 const void *data,
4817 int data_len)
4818{
4819 int ret;
4820
4821 cds_ssr_protect(__func__);
4822 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4823 data, data_len);
4824 cds_ssr_unprotect(__func__);
4825
4826 return ret;
4827}
4828
4829static const struct
4830nla_policy
4831qca_wlan_vendor_wifi_logger_start_policy
4832[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4833 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4834 = {.type = NLA_U32 },
4835 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4836 = {.type = NLA_U32 },
4837 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4838 = {.type = NLA_U32 },
4839};
4840
4841/**
4842 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4843 * or disable the collection of packet statistics from the firmware
4844 * @wiphy: WIPHY structure pointer
4845 * @wdev: Wireless device structure pointer
4846 * @data: Pointer to the data received
4847 * @data_len: Length of the data received
4848 *
4849 * This function enables or disables the collection of packet statistics from
4850 * the firmware
4851 *
4852 * Return: 0 on success and errno on failure
4853 */
4854static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4855 struct wireless_dev *wdev,
4856 const void *data,
4857 int data_len)
4858{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304859 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4861 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4862 struct sir_wifi_start_log start_log;
4863
Jeff Johnson1f61b612016-02-12 16:28:33 -08004864 ENTER_DEV(wdev->netdev);
4865
Anurag Chouhan6d760662016-02-20 16:05:43 +05304866 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 hdd_err("Command not allowed in FTM mode");
4868 return -EPERM;
4869 }
4870
4871 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304872 if (status)
4873 return status;
4874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875
4876 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4877 data, data_len,
4878 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004879 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 return -EINVAL;
4881 }
4882
4883 /* Parse and fetch ring id */
4884 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004885 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886 return -EINVAL;
4887 }
4888 start_log.ring_id = nla_get_u32(
4889 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004890 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891
4892 /* Parse and fetch verbose level */
4893 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004894 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 return -EINVAL;
4896 }
4897 start_log.verbose_level = nla_get_u32(
4898 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004899 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900
4901 /* Parse and fetch flag */
4902 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004903 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 return -EINVAL;
4905 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304906 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304908 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004909
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304910 /* size is buff size which can be set using iwpriv command*/
4911 start_log.size = 0;
4912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4914
4915 if (start_log.ring_id == RING_ID_WAKELOCK) {
4916 /* Start/stop wakelock events */
4917 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4918 cds_set_wakelock_logging(true);
4919 else
4920 cds_set_wakelock_logging(false);
4921 return 0;
4922 }
4923
4924 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304925 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004926 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 status);
4928 return -EINVAL;
4929 }
4930 return 0;
4931}
4932
4933/**
4934 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4935 * or disable the collection of packet statistics from the firmware
4936 * @wiphy: WIPHY structure pointer
4937 * @wdev: Wireless device structure pointer
4938 * @data: Pointer to the data received
4939 * @data_len: Length of the data received
4940 *
4941 * This function is used to enable or disable the collection of packet
4942 * statistics from the firmware
4943 *
4944 * Return: 0 on success and errno on failure
4945 */
4946static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4947 struct wireless_dev *wdev,
4948 const void *data,
4949 int data_len)
4950{
4951 int ret = 0;
4952
4953 cds_ssr_protect(__func__);
4954 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4955 wdev, data, data_len);
4956 cds_ssr_unprotect(__func__);
4957
4958 return ret;
4959}
4960
4961static const struct
4962nla_policy
4963qca_wlan_vendor_wifi_logger_get_ring_data_policy
4964[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4965 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4966 = {.type = NLA_U32 },
4967};
4968
4969/**
4970 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4971 * @wiphy: WIPHY structure pointer
4972 * @wdev: Wireless device structure pointer
4973 * @data: Pointer to the data received
4974 * @data_len: Length of the data received
4975 *
4976 * This function is used to flush or retrieve the per packet statistics from
4977 * the driver
4978 *
4979 * Return: 0 on success and errno on failure
4980 */
4981static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4982 struct wireless_dev *wdev,
4983 const void *data,
4984 int data_len)
4985{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304986 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987 uint32_t ring_id;
4988 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4989 struct nlattr *tb
4990 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4991
Jeff Johnson1f61b612016-02-12 16:28:33 -08004992 ENTER_DEV(wdev->netdev);
4993
Anurag Chouhan6d760662016-02-20 16:05:43 +05304994 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004995 hdd_err("Command not allowed in FTM mode");
4996 return -EPERM;
4997 }
4998
4999 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305000 if (status)
5001 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002
5003 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5004 data, data_len,
5005 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005006 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 return -EINVAL;
5008 }
5009
5010 /* Parse and fetch ring id */
5011 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005012 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013 return -EINVAL;
5014 }
5015
5016 ring_id = nla_get_u32(
5017 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5018
5019 if (ring_id == RING_ID_PER_PACKET_STATS) {
5020 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07005021 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305022 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5023 /*
5024 * As part of DRIVER ring ID, flush both driver and fw logs.
5025 * For other Ring ID's driver doesn't have any rings to flush
5026 */
5027 hdd_notice("Bug report triggered by framework");
5028
5029 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5030 WLAN_LOG_INDICATOR_FRAMEWORK,
5031 WLAN_LOG_REASON_CODE_UNUSED,
5032 true, false);
5033 if (QDF_STATUS_SUCCESS != status) {
5034 hdd_err("Failed to trigger bug report");
5035 return -EINVAL;
5036 }
5037 } else {
5038 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5039 WLAN_LOG_INDICATOR_FRAMEWORK,
5040 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042 return 0;
5043}
5044
5045/**
5046 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5047 * @wiphy: WIPHY structure pointer
5048 * @wdev: Wireless device structure pointer
5049 * @data: Pointer to the data received
5050 * @data_len: Length of the data received
5051 *
5052 * This function is used to flush or retrieve the per packet statistics from
5053 * the driver
5054 *
5055 * Return: 0 on success and errno on failure
5056 */
5057static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5058 struct wireless_dev *wdev,
5059 const void *data,
5060 int data_len)
5061{
5062 int ret = 0;
5063
5064 cds_ssr_protect(__func__);
5065 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5066 wdev, data, data_len);
5067 cds_ssr_unprotect(__func__);
5068
5069 return ret;
5070}
5071
5072#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5073/**
5074 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5075 * @hdd_ctx: HDD context
5076 * @request_id: [input] request id
5077 * @pattern_id: [output] pattern id
5078 *
5079 * This function loops through request id to pattern id array
5080 * if the slot is available, store the request id and return pattern id
5081 * if entry exists, return the pattern id
5082 *
5083 * Return: 0 on success and errno on failure
5084 */
5085static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5086 uint32_t request_id,
5087 uint8_t *pattern_id)
5088{
5089 uint32_t i;
5090
5091 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5092 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5093 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5094 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5095 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5096 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5097 return 0;
5098 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5099 request_id) {
5100 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5101 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5102 return 0;
5103 }
5104 }
5105 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5106 return -EINVAL;
5107}
5108
5109/**
5110 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5111 * @hdd_ctx: HDD context
5112 * @request_id: [input] request id
5113 * @pattern_id: [output] pattern id
5114 *
5115 * This function loops through request id to pattern id array
5116 * reset request id to 0 (slot available again) and
5117 * return pattern id
5118 *
5119 * Return: 0 on success and errno on failure
5120 */
5121static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5122 uint32_t request_id,
5123 uint8_t *pattern_id)
5124{
5125 uint32_t i;
5126
5127 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5128 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5129 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5130 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5131 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5132 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5133 return 0;
5134 }
5135 }
5136 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5137 return -EINVAL;
5138}
5139
5140
5141/*
5142 * define short names for the global vendor params
5143 * used by __wlan_hdd_cfg80211_offloaded_packets()
5144 */
5145#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5146#define PARAM_REQUEST_ID \
5147 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5148#define PARAM_CONTROL \
5149 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5150#define PARAM_IP_PACKET \
5151 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5152#define PARAM_SRC_MAC_ADDR \
5153 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5154#define PARAM_DST_MAC_ADDR \
5155 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5156#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5157
5158/**
5159 * wlan_hdd_add_tx_ptrn() - add tx pattern
5160 * @adapter: adapter pointer
5161 * @hdd_ctx: hdd context
5162 * @tb: nl attributes
5163 *
5164 * This function reads the NL attributes and forms a AddTxPtrn message
5165 * posts it to SME.
5166 *
5167 */
5168static int
5169wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5170 struct nlattr **tb)
5171{
5172 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305173 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174 uint32_t request_id, ret, len;
5175 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305176 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177 uint16_t eth_type = htons(ETH_P_IP);
5178
5179 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005180 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 return -ENOTSUPP;
5182 }
5183
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305184 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005186 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187 return -ENOMEM;
5188 }
5189
5190 /* Parse and fetch request Id */
5191 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005192 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005193 goto fail;
5194 }
5195
5196 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5197 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005198 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 return -EINVAL;
5200 }
Jeff Johnson77848112016-06-29 14:52:06 -07005201 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202
5203 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005204 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 goto fail;
5206 }
5207 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005208 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 goto fail;
5212 }
5213
5214 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005215 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 goto fail;
5217 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005218 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305219 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005220 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005221 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222
Anurag Chouhanc5548422016-02-24 18:33:27 +05305223 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005224 &adapter->macAddressCurrent)) {
5225 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 goto fail;
5227 }
5228
5229 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005230 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 goto fail;
5232 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305233 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005234 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 MAC_ADDR_ARRAY(dst_addr.bytes));
5236
5237 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 goto fail;
5240 }
5241 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005242 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
5244 if (add_req->ucPtrnSize < 0 ||
5245 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5246 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005247 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248 add_req->ucPtrnSize);
5249 goto fail;
5250 }
5251
5252 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305253 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305254 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305255 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305256 QDF_MAC_ADDR_SIZE);
5257 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305258 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 len += 2;
5260
5261 /*
5262 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5263 * ------------------------------------------------------------
5264 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5265 * ------------------------------------------------------------
5266 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305267 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268 nla_data(tb[PARAM_IP_PACKET]),
5269 add_req->ucPtrnSize);
5270 add_req->ucPtrnSize += len;
5271
5272 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5273 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005274 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 goto fail;
5276 }
5277 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005278 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005279
5280 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305281 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005282 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283 goto fail;
5284 }
5285
5286 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305287 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005288 return 0;
5289
5290fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305291 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 return -EINVAL;
5293}
5294
5295/**
5296 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5297 * @adapter: adapter pointer
5298 * @hdd_ctx: hdd context
5299 * @tb: nl attributes
5300 *
5301 * This function reads the NL attributes and forms a DelTxPtrn message
5302 * posts it to SME.
5303 *
5304 */
5305static int
5306wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5307 struct nlattr **tb)
5308{
5309 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305310 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005311 uint32_t request_id, ret;
5312 uint8_t pattern_id = 0;
5313
5314 /* Parse and fetch request Id */
5315 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005316 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 return -EINVAL;
5318 }
5319 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5320 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005321 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 return -EINVAL;
5323 }
5324
5325 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5326 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005327 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 return -EINVAL;
5329 }
5330
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305331 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005333 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 return -ENOMEM;
5335 }
5336
Anurag Chouhanc5548422016-02-24 18:33:27 +05305337 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005338 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005340 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341 request_id, del_req->ucPtrnId);
5342
5343 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305344 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005345 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 goto fail;
5347 }
5348
5349 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305350 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 return 0;
5352
5353fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305354 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355 return -EINVAL;
5356}
5357
5358
5359/**
5360 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5361 * @wiphy: Pointer to wireless phy
5362 * @wdev: Pointer to wireless device
5363 * @data: Pointer to data
5364 * @data_len: Data length
5365 *
5366 * Return: 0 on success, negative errno on failure
5367 */
5368static int
5369__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5370 struct wireless_dev *wdev,
5371 const void *data,
5372 int data_len)
5373{
5374 struct net_device *dev = wdev->netdev;
5375 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5376 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5377 struct nlattr *tb[PARAM_MAX + 1];
5378 uint8_t control;
5379 int ret;
5380 static const struct nla_policy policy[PARAM_MAX + 1] = {
5381 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5382 [PARAM_CONTROL] = { .type = NLA_U32 },
5383 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305384 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305386 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 [PARAM_PERIOD] = { .type = NLA_U32 },
5388 };
5389
Jeff Johnson1f61b612016-02-12 16:28:33 -08005390 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391
Anurag Chouhan6d760662016-02-20 16:05:43 +05305392 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005393 hdd_err("Command not allowed in FTM mode");
5394 return -EPERM;
5395 }
5396
5397 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305398 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005399 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400
5401 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005402 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403 return -ENOTSUPP;
5404 }
5405
5406 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005407 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408 return -EINVAL;
5409 }
5410
5411 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005412 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 return -EINVAL;
5414 }
5415 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005416 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417
5418 if (control == WLAN_START_OFFLOADED_PACKETS)
5419 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005420 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005422
5423 hdd_err("Invalid control: %d", control);
5424
5425 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426}
5427
5428/*
5429 * done with short names for the global vendor params
5430 * used by __wlan_hdd_cfg80211_offloaded_packets()
5431 */
5432#undef PARAM_MAX
5433#undef PARAM_REQUEST_ID
5434#undef PARAM_CONTROL
5435#undef PARAM_IP_PACKET
5436#undef PARAM_SRC_MAC_ADDR
5437#undef PARAM_DST_MAC_ADDR
5438#undef PARAM_PERIOD
5439
5440/**
5441 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5442 * @wiphy: wiphy structure pointer
5443 * @wdev: Wireless device structure pointer
5444 * @data: Pointer to the data received
5445 * @data_len: Length of @data
5446 *
5447 * Return: 0 on success; errno on failure
5448 */
5449static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5450 struct wireless_dev *wdev,
5451 const void *data,
5452 int data_len)
5453{
5454 int ret = 0;
5455
5456 cds_ssr_protect(__func__);
5457 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5458 wdev, data, data_len);
5459 cds_ssr_unprotect(__func__);
5460
5461 return ret;
5462}
5463#endif
5464
5465/*
5466 * define short names for the global vendor params
5467 * used by __wlan_hdd_cfg80211_monitor_rssi()
5468 */
5469#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5470#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5471#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5472#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5473#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5474
5475/**
5476 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5477 * @wiphy: Pointer to wireless phy
5478 * @wdev: Pointer to wireless device
5479 * @data: Pointer to data
5480 * @data_len: Data length
5481 *
5482 * Return: 0 on success, negative errno on failure
5483 */
5484static int
5485__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5486 struct wireless_dev *wdev,
5487 const void *data,
5488 int data_len)
5489{
5490 struct net_device *dev = wdev->netdev;
5491 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5492 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5493 struct nlattr *tb[PARAM_MAX + 1];
5494 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305495 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 int ret;
5497 uint32_t control;
5498 static const struct nla_policy policy[PARAM_MAX + 1] = {
5499 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5500 [PARAM_CONTROL] = { .type = NLA_U32 },
5501 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5502 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5503 };
5504
Jeff Johnson1f61b612016-02-12 16:28:33 -08005505 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305507 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5508 hdd_err("invalid session id: %d", adapter->sessionId);
5509 return -EINVAL;
5510 }
5511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005512 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305513 if (ret)
5514 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515
5516 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005517 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 return -ENOTSUPP;
5519 }
5520
5521 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005522 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 return -EINVAL;
5524 }
5525
5526 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005527 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 return -EINVAL;
5529 }
5530
5531 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005532 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 return -EINVAL;
5534 }
5535
5536 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5537 req.session_id = adapter->sessionId;
5538 control = nla_get_u32(tb[PARAM_CONTROL]);
5539
5540 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5541 req.control = true;
5542 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005543 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 return -EINVAL;
5545 }
5546
5547 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005548 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 return -EINVAL;
5550 }
5551
5552 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5553 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5554
5555 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005556 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 req.min_rssi, req.max_rssi);
5558 return -EINVAL;
5559 }
Jeff Johnson77848112016-06-29 14:52:06 -07005560 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561 req.min_rssi, req.max_rssi);
5562
5563 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5564 req.control = false;
5565 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005566 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567 return -EINVAL;
5568 }
Jeff Johnson77848112016-06-29 14:52:06 -07005569 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 req.request_id, req.session_id, req.control);
5571
5572 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305573 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 return -EINVAL;
5576 }
5577
5578 return 0;
5579}
5580
5581/*
5582 * done with short names for the global vendor params
5583 * used by __wlan_hdd_cfg80211_monitor_rssi()
5584 */
5585#undef PARAM_MAX
5586#undef PARAM_CONTROL
5587#undef PARAM_REQUEST_ID
5588#undef PARAM_MAX_RSSI
5589#undef PARAM_MIN_RSSI
5590
5591/**
5592 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5593 * @wiphy: wiphy structure pointer
5594 * @wdev: Wireless device structure pointer
5595 * @data: Pointer to the data received
5596 * @data_len: Length of @data
5597 *
5598 * Return: 0 on success; errno on failure
5599 */
5600static int
5601wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5602 const void *data, int data_len)
5603{
5604 int ret;
5605
5606 cds_ssr_protect(__func__);
5607 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5608 cds_ssr_unprotect(__func__);
5609
5610 return ret;
5611}
5612
5613/**
5614 * hdd_rssi_threshold_breached() - rssi breached NL event
5615 * @hddctx: HDD context
5616 * @data: rssi breached event data
5617 *
5618 * This function reads the rssi breached event %data and fill in the skb with
5619 * NL attributes and send up the NL event.
5620 *
5621 * Return: none
5622 */
5623void hdd_rssi_threshold_breached(void *hddctx,
5624 struct rssi_breach_event *data)
5625{
5626 hdd_context_t *hdd_ctx = hddctx;
5627 struct sk_buff *skb;
5628
5629 ENTER();
5630
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305631 if (wlan_hdd_validate_context(hdd_ctx))
5632 return;
5633 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005634 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635 return;
5636 }
5637
5638 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5639 NULL,
5640 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5641 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5642 GFP_KERNEL);
5643
5644 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005645 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646 return;
5647 }
5648
Jeff Johnson77848112016-06-29 14:52:06 -07005649 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005651 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5653
5654 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5655 data->request_id) ||
5656 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5657 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5658 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5659 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005660 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661 goto fail;
5662 }
5663
5664 cfg80211_vendor_event(skb, GFP_KERNEL);
5665 return;
5666
5667fail:
5668 kfree_skb(skb);
5669 return;
5670}
5671
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305672static const struct nla_policy
5673ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5674 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5675};
5676
5677/**
5678 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5679 * @wiphy: Pointer to wireless phy
5680 * @wdev: Pointer to wireless device
5681 * @data: Pointer to data
5682 * @data_len: Length of @data
5683 *
5684 * Return: 0 on success, negative errno on failure
5685 */
5686static int
5687__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5688 struct wireless_dev *wdev,
5689 const void *data, int data_len)
5690{
5691 int status;
5692 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5693 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005694 struct net_device *dev = wdev->netdev;
5695 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305696
5697 ENTER_DEV(wdev->netdev);
5698
5699 status = wlan_hdd_validate_context(pHddCtx);
5700 if (0 != status)
5701 return status;
5702 if (!pHddCtx->config->fhostNSOffload) {
5703 hdd_err("ND Offload not supported");
5704 return -EINVAL;
5705 }
5706
5707 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5708 (struct nlattr *)data,
5709 data_len, ns_offload_set_policy)) {
5710 hdd_err("nla_parse failed");
5711 return -EINVAL;
5712 }
5713
5714 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5715 hdd_err("ND Offload flag attribute not present");
5716 return -EINVAL;
5717 }
5718
5719 pHddCtx->ns_offload_enable =
5720 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5721
Dustin Brownd8279d22016-09-07 14:52:57 -07005722 /* update ns offload in case it is already enabled/disabled */
5723 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5724
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305725 return 0;
5726}
5727
5728/**
5729 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5730 * @wiphy: pointer to wireless wiphy structure.
5731 * @wdev: pointer to wireless_dev structure.
5732 * @data: Pointer to the data to be passed via vendor interface
5733 * @data_len:Length of the data to be passed
5734 *
5735 * Return: Return the Success or Failure code.
5736 */
5737static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5738 struct wireless_dev *wdev,
5739 const void *data, int data_len)
5740{
5741 int ret;
5742
5743 cds_ssr_protect(__func__);
5744 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5745 cds_ssr_unprotect(__func__);
5746
5747 return ret;
5748}
5749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5751 * @wiphy: Pointer to wireless phy
5752 * @wdev: Pointer to wireless device
5753 * @data: Pointer to data
5754 * @data_len: Data length
5755 *
5756 * This function return the preferred frequency list generated by the policy
5757 * manager.
5758 *
5759 * Return: success or failure code
5760 */
5761static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5762 struct wireless_dev
5763 *wdev, const void *data,
5764 int data_len)
5765{
5766 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5767 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305768 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305769 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005770 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305771 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005772 enum cds_con_mode intf_mode;
5773 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5774 struct sk_buff *reply_skb;
5775
Jeff Johnson1f61b612016-02-12 16:28:33 -08005776 ENTER_DEV(wdev->netdev);
5777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778 ret = wlan_hdd_validate_context(hdd_ctx);
5779 if (ret)
5780 return -EINVAL;
5781
5782 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5783 data, data_len, NULL)) {
5784 hdd_err("Invalid ATTR");
5785 return -EINVAL;
5786 }
5787
5788 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5789 hdd_err("attr interface type failed");
5790 return -EINVAL;
5791 }
5792
5793 intf_mode = nla_get_u32(tb
5794 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5795
5796 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5797 hdd_err("Invalid interface type");
5798 return -EINVAL;
5799 }
5800
5801 hdd_debug("Userspace requested pref freq list");
5802
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305803 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5804 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305805 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 hdd_err("Get pcl failed");
5807 return -EINVAL;
5808 }
5809
5810 /* convert channel number to frequency */
5811 for (i = 0; i < pcl_len; i++) {
5812 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5813 freq_list[i] =
5814 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005815 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005816 else
5817 freq_list[i] =
5818 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005819 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820 }
5821
5822 /* send the freq_list back to supplicant */
5823 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5824 sizeof(u32) *
5825 pcl_len +
5826 NLMSG_HDRLEN);
5827
5828 if (!reply_skb) {
5829 hdd_err("Allocate reply_skb failed");
5830 return -EINVAL;
5831 }
5832
5833 if (nla_put_u32(reply_skb,
5834 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5835 intf_mode) ||
5836 nla_put(reply_skb,
5837 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5838 sizeof(uint32_t) * pcl_len,
5839 freq_list)) {
5840 hdd_err("nla put fail");
5841 kfree_skb(reply_skb);
5842 return -EINVAL;
5843 }
5844
5845 return cfg80211_vendor_cmd_reply(reply_skb);
5846}
5847
5848/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5849 * @wiphy: Pointer to wireless phy
5850 * @wdev: Pointer to wireless device
5851 * @data: Pointer to data
5852 * @data_len: Data length
5853 *
5854 * This function return the preferred frequency list generated by the policy
5855 * manager.
5856 *
5857 * Return: success or failure code
5858 */
5859static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5860 struct wireless_dev
5861 *wdev, const void *data,
5862 int data_len)
5863{
5864 int ret = 0;
5865
5866 cds_ssr_protect(__func__);
5867 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5868 data, data_len);
5869 cds_ssr_unprotect(__func__);
5870
5871 return ret;
5872}
5873
5874/**
5875 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5876 * @wiphy: Pointer to wireless phy
5877 * @wdev: Pointer to wireless device
5878 * @data: Pointer to data
5879 * @data_len: Data length
5880 *
5881 * Return: 0 on success, negative errno on failure
5882 */
5883static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5884 struct wireless_dev *wdev,
5885 const void *data,
5886 int data_len)
5887{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305888 struct net_device *ndev = wdev->netdev;
5889 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005890 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5891 int ret = 0;
5892 enum cds_con_mode intf_mode;
5893 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5894 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895
Jeff Johnson1f61b612016-02-12 16:28:33 -08005896 ENTER_DEV(ndev);
5897
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898 ret = wlan_hdd_validate_context(hdd_ctx);
5899 if (ret)
5900 return ret;
5901
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005902 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5903 data, data_len, NULL)) {
5904 hdd_err("Invalid ATTR");
5905 return -EINVAL;
5906 }
5907
5908 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5909 hdd_err("attr interface type failed");
5910 return -EINVAL;
5911 }
5912
5913 intf_mode = nla_get_u32(tb
5914 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5915
5916 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5917 hdd_err("Invalid interface type");
5918 return -EINVAL;
5919 }
5920
5921 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5922 hdd_err("attr probable freq failed");
5923 return -EINVAL;
5924 }
5925
5926 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5927 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5928
5929 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005930 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 channel_hint, HW_MODE_20_MHZ)) {
5932 hdd_err("Set channel hint failed due to concurrency check");
5933 return -EINVAL;
5934 }
5935
Krunal Soni09e55032016-06-07 10:06:55 -07005936 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5937 hdd_warn("Remain On Channel Pending");
5938
Krunal Soni3091bcc2016-06-23 12:28:21 -07005939 ret = qdf_reset_connection_update();
5940 if (!QDF_IS_STATUS_SUCCESS(ret))
5941 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005942
Krunal Soni3091bcc2016-06-23 12:28:21 -07005943 ret = cds_current_connections_update(adapter->sessionId,
5944 channel_hint,
5945 SIR_UPDATE_REASON_SET_OPER_CHAN);
5946 if (QDF_STATUS_E_FAILURE == ret) {
5947 /* return in the failure case */
5948 hdd_err("ERROR: connections update failed!!");
5949 return -EINVAL;
5950 }
5951
5952 if (QDF_STATUS_SUCCESS == ret) {
5953 /*
5954 * Success is the only case for which we expect hw mode
5955 * change to take place, hence we need to wait.
5956 * For any other return value it should be a pass
5957 * through
5958 */
5959 ret = qdf_wait_for_connection_update();
5960 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5961 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 return -EINVAL;
5963 }
5964
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005965 }
5966
5967 return 0;
5968}
5969
5970/**
5971 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5972 * @wiphy: Pointer to wireless phy
5973 * @wdev: Pointer to wireless device
5974 * @data: Pointer to data
5975 * @data_len: Data length
5976 *
5977 * Return: 0 on success, negative errno on failure
5978 */
5979static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5980 struct wireless_dev *wdev,
5981 const void *data,
5982 int data_len)
5983{
5984 int ret = 0;
5985
5986 cds_ssr_protect(__func__);
5987 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5988 data, data_len);
5989 cds_ssr_unprotect(__func__);
5990
5991 return ret;
5992}
5993
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305994static const struct
5995nla_policy
5996qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5997 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5998};
5999
6000/**
6001 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6002 * @wiphy: WIPHY structure pointer
6003 * @wdev: Wireless device structure pointer
6004 * @data: Pointer to the data received
6005 * @data_len: Length of the data received
6006 *
6007 * This function is used to get link properties like nss, rate flags and
6008 * operating frequency for the active connection with the given peer.
6009 *
6010 * Return: 0 on success and errno on failure
6011 */
6012static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6013 struct wireless_dev *wdev,
6014 const void *data,
6015 int data_len)
6016{
6017 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6018 struct net_device *dev = wdev->netdev;
6019 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6020 hdd_station_ctx_t *hdd_sta_ctx;
6021 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306022 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306023 uint32_t sta_id;
6024 struct sk_buff *reply_skb;
6025 uint32_t rate_flags = 0;
6026 uint8_t nss;
6027 uint8_t final_rate_flags = 0;
6028 uint32_t freq;
6029
Jeff Johnson1f61b612016-02-12 16:28:33 -08006030 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306031
Anurag Chouhan6d760662016-02-20 16:05:43 +05306032 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306033 hdd_err("Command not allowed in FTM mode");
6034 return -EPERM;
6035 }
6036
6037 if (0 != wlan_hdd_validate_context(hdd_ctx))
6038 return -EINVAL;
6039
6040 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6041 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006042 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306043 return -EINVAL;
6044 }
6045
6046 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006047 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306048 adapter->device_mode);
6049 return -EINVAL;
6050 }
6051
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306052 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306053 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006054 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306055 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6056
Krunal Sonib4326f22016-03-10 13:05:51 -08006057 if (adapter->device_mode == QDF_STA_MODE ||
6058 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306059 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6060 if ((hdd_sta_ctx->conn_info.connState !=
6061 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306062 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306063 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006064 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306065 MAC_ADDR_ARRAY(peer_mac));
6066 return -EINVAL;
6067 }
6068
6069 nss = hdd_sta_ctx->conn_info.nss;
6070 freq = cds_chan_to_freq(
6071 hdd_sta_ctx->conn_info.operationChannel);
6072 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006073 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6074 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306075
6076 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6077 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306078 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306079 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306080 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306081 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306082 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306083 break;
6084 }
6085
6086 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006087 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306088 MAC_ADDR_ARRAY(peer_mac));
6089 return -EINVAL;
6090 }
6091
6092 nss = adapter->aStaInfo[sta_id].nss;
6093 freq = cds_chan_to_freq(
6094 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6095 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6096 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006097 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306098 MAC_ADDR_ARRAY(peer_mac));
6099 return -EINVAL;
6100 }
6101
6102 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6103 if (rate_flags & eHAL_TX_RATE_VHT80) {
6104 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006105#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306106 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006107#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306108 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6109 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006110#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306111 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006112#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306113 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6114 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6115 } else if (rate_flags &
6116 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6117 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006118#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306119 if (rate_flags & eHAL_TX_RATE_HT40)
6120 final_rate_flags |=
6121 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006122#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306123 }
6124
6125 if (rate_flags & eHAL_TX_RATE_SGI) {
6126 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6127 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6128 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6129 }
6130 }
6131
6132 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6133 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6134
6135 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006136 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306137 return -EINVAL;
6138 }
6139
6140 if (nla_put_u8(reply_skb,
6141 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6142 nss) ||
6143 nla_put_u8(reply_skb,
6144 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6145 final_rate_flags) ||
6146 nla_put_u32(reply_skb,
6147 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6148 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006149 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306150 kfree_skb(reply_skb);
6151 return -EINVAL;
6152 }
6153
6154 return cfg80211_vendor_cmd_reply(reply_skb);
6155}
6156
6157/**
6158 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6159 * properties.
6160 * @wiphy: WIPHY structure pointer
6161 * @wdev: Wireless device structure pointer
6162 * @data: Pointer to the data received
6163 * @data_len: Length of the data received
6164 *
6165 * This function is used to get link properties like nss, rate flags and
6166 * operating frequency for the active connection with the given peer.
6167 *
6168 * Return: 0 on success and errno on failure
6169 */
6170static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6171 struct wireless_dev *wdev,
6172 const void *data,
6173 int data_len)
6174{
6175 int ret = 0;
6176
6177 cds_ssr_protect(__func__);
6178 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6179 wdev, data, data_len);
6180 cds_ssr_unprotect(__func__);
6181
6182 return ret;
6183}
6184
Peng Xu278d0122015-09-24 16:34:17 -07006185static const struct
6186nla_policy
6187qca_wlan_vendor_ota_test_policy
6188[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6189 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6190};
6191
6192/**
6193 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6194 * @wiphy: Pointer to wireless phy
6195 * @wdev: Pointer to wireless device
6196 * @data: Pointer to data
6197 * @data_len: Data length
6198 *
6199 * Return: 0 on success, negative errno on failure
6200 */
6201static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6202 struct wireless_dev *wdev,
6203 const void *data,
6204 int data_len)
6205{
6206 struct net_device *dev = wdev->netdev;
6207 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6208 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6209 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6210 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6211 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306212 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006213 uint32_t current_roam_state;
6214
Jeff Johnson1f61b612016-02-12 16:28:33 -08006215 ENTER_DEV(dev);
6216
Anurag Chouhan6d760662016-02-20 16:05:43 +05306217 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006218 hdd_err("Command not allowed in FTM mode");
6219 return -EPERM;
6220 }
6221
6222 if (0 != wlan_hdd_validate_context(hdd_ctx))
6223 return -EINVAL;
6224
6225 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6226 data, data_len,
6227 qca_wlan_vendor_ota_test_policy)) {
6228 hdd_err("invalid attr");
6229 return -EINVAL;
6230 }
6231
6232 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6233 hdd_err("attr ota test failed");
6234 return -EINVAL;
6235 }
6236
6237 ota_enable = nla_get_u8(
6238 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6239
6240 hdd_info(" OTA test enable = %d", ota_enable);
6241 if (ota_enable != 1) {
6242 hdd_err("Invalid value, only enable test mode is supported!");
6243 return -EINVAL;
6244 }
6245
6246 current_roam_state =
6247 sme_get_current_roam_state(hal, adapter->sessionId);
6248 status = sme_stop_roaming(hal, adapter->sessionId,
6249 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306250 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006251 hdd_err("Enable/Disable roaming failed");
6252 return -EINVAL;
6253 }
6254
6255 status = sme_ps_enable_disable(hal, adapter->sessionId,
6256 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306257 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006258 hdd_err("Enable/Disable power save failed");
6259 /* restore previous roaming setting */
6260 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6261 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6262 status = sme_start_roaming(hal, adapter->sessionId,
6263 eCsrHddIssued);
6264 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6265 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6266 status = sme_stop_roaming(hal, adapter->sessionId,
6267 eCsrHddIssued);
6268
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306269 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006270 hdd_err("Restoring roaming state failed");
6271
6272 return -EINVAL;
6273 }
6274
6275
6276 return 0;
6277}
6278
6279/**
6280 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6281 * @wiphy: Pointer to wireless phy
6282 * @wdev: Pointer to wireless device
6283 * @data: Pointer to data
6284 * @data_len: Data length
6285 *
6286 * Return: 0 on success, negative errno on failure
6287 */
6288static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6289 struct wireless_dev *wdev,
6290 const void *data,
6291 int data_len)
6292{
6293 int ret = 0;
6294
6295 cds_ssr_protect(__func__);
6296 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6297 cds_ssr_unprotect(__func__);
6298
6299 return ret;
6300}
6301
Peng Xu4d67c8f2015-10-16 16:02:26 -07006302/**
6303 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6304 * @wiphy: Pointer to wireless phy
6305 * @wdev: Pointer to wireless device
6306 * @data: Pointer to data
6307 * @data_len: Data length
6308 *
6309 * Return: 0 on success, negative errno on failure
6310 */
6311static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6312 struct wireless_dev *wdev,
6313 const void *data,
6314 int data_len)
6315{
6316 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6317 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006318 hdd_adapter_t *adapter;
6319 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006320 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6321 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006322 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006323
Jeff Johnson1f61b612016-02-12 16:28:33 -08006324 ENTER_DEV(dev);
6325
Peng Xu4d67c8f2015-10-16 16:02:26 -07006326 ret = wlan_hdd_validate_context(hdd_ctx);
6327 if (ret)
6328 return ret;
6329
6330 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6331
6332 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6333 data, data_len, NULL)) {
6334 hdd_err("Invalid ATTR");
6335 return -EINVAL;
6336 }
6337
6338 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6339 hdd_err("attr tx power scale failed");
6340 return -EINVAL;
6341 }
6342
6343 scale_value = nla_get_u8(tb
6344 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6345
6346 if (scale_value > MAX_TXPOWER_SCALE) {
6347 hdd_err("Invalid tx power scale level");
6348 return -EINVAL;
6349 }
6350
Peng Xu62c8c432016-05-09 15:23:02 -07006351 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006352
Peng Xu62c8c432016-05-09 15:23:02 -07006353 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006354 hdd_err("Set tx power scale failed");
6355 return -EINVAL;
6356 }
6357
6358 return 0;
6359}
6360
6361/**
6362 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6363 * @wiphy: Pointer to wireless phy
6364 * @wdev: Pointer to wireless device
6365 * @data: Pointer to data
6366 * @data_len: Data length
6367 *
6368 * Return: 0 on success, negative errno on failure
6369 */
6370static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6371 struct wireless_dev *wdev,
6372 const void *data,
6373 int data_len)
6374{
Peng Xu62c8c432016-05-09 15:23:02 -07006375 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006376
6377 cds_ssr_protect(__func__);
6378 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6379 data, data_len);
6380 cds_ssr_unprotect(__func__);
6381
6382 return ret;
6383}
6384
6385/**
6386 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6387 * @wiphy: Pointer to wireless phy
6388 * @wdev: Pointer to wireless device
6389 * @data: Pointer to data
6390 * @data_len: Data length
6391 *
6392 * Return: 0 on success, negative errno on failure
6393 */
6394static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6395 struct wireless_dev *wdev,
6396 const void *data,
6397 int data_len)
6398{
6399 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6400 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006401 hdd_adapter_t *adapter;
6402 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006403 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6404 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006405 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006406
Jeff Johnson1f61b612016-02-12 16:28:33 -08006407 ENTER_DEV(dev);
6408
Peng Xu4d67c8f2015-10-16 16:02:26 -07006409 ret = wlan_hdd_validate_context(hdd_ctx);
6410 if (ret)
6411 return ret;
6412
6413 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6414
6415 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6416 data, data_len, NULL)) {
6417 hdd_err("Invalid ATTR");
6418 return -EINVAL;
6419 }
6420
6421 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6422 hdd_err("attr tx power decrease db value failed");
6423 return -EINVAL;
6424 }
6425
6426 scale_value = nla_get_u8(tb
6427 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6428
Peng Xu62c8c432016-05-09 15:23:02 -07006429 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6430 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006431
Peng Xu62c8c432016-05-09 15:23:02 -07006432 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006433 hdd_err("Set tx power decrease db failed");
6434 return -EINVAL;
6435 }
6436
6437 return 0;
6438}
6439
6440/**
6441 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6442 * @wiphy: Pointer to wireless phy
6443 * @wdev: Pointer to wireless device
6444 * @data: Pointer to data
6445 * @data_len: Data length
6446 *
6447 * Return: 0 on success, negative errno on failure
6448 */
6449static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6450 struct wireless_dev *wdev,
6451 const void *data,
6452 int data_len)
6453{
Peng Xu62c8c432016-05-09 15:23:02 -07006454 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006455
6456 cds_ssr_protect(__func__);
6457 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6458 data, data_len);
6459 cds_ssr_unprotect(__func__);
6460
6461 return ret;
6462}
Peng Xu8fdaa492016-06-22 10:20:47 -07006463
6464/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306465 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6466 * @wiphy: Pointer to wireless phy
6467 * @wdev: Pointer to wireless device
6468 * @data: Pointer to data
6469 * @data_len: Data length
6470 *
6471 * Processes the conditional channel switch request and invokes the helper
6472 * APIs to process the channel switch request.
6473 *
6474 * Return: 0 on success, negative errno on failure
6475 */
6476static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6477 struct wireless_dev *wdev,
6478 const void *data,
6479 int data_len)
6480{
6481 int ret;
6482 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6483 struct net_device *dev = wdev->netdev;
6484 hdd_adapter_t *adapter;
6485 struct nlattr
6486 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6487 uint32_t freq_len, i;
6488 uint32_t *freq;
6489 uint8_t chans[QDF_MAX_NUM_CHAN];
6490
6491 ENTER_DEV(dev);
6492
6493 ret = wlan_hdd_validate_context(hdd_ctx);
6494 if (ret)
6495 return ret;
6496
6497 if (!hdd_ctx->config->enableDFSMasterCap) {
6498 hdd_err("DFS master capability is not present in the driver");
6499 return -EINVAL;
6500 }
6501
6502 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6503 hdd_err("Command not allowed in FTM mode");
6504 return -EPERM;
6505 }
6506
6507 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6508 if (adapter->device_mode != QDF_SAP_MODE) {
6509 hdd_err("Invalid device mode %d", adapter->device_mode);
6510 return -EINVAL;
6511 }
6512
6513 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6514 data, data_len, NULL)) {
6515 hdd_err("Invalid ATTR");
6516 return -EINVAL;
6517 }
6518
6519 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6520 hdd_err("Frequency list is missing");
6521 return -EINVAL;
6522 }
6523
6524 freq_len = nla_len(
6525 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6526 sizeof(uint32_t);
6527
6528 if (freq_len > QDF_MAX_NUM_CHAN) {
6529 hdd_err("insufficient space to hold channels");
6530 return -ENOMEM;
6531 }
6532
6533 hdd_debug("freq_len=%d", freq_len);
6534
6535 freq = nla_data(
6536 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6537
6538
6539 for (i = 0; i < freq_len; i++) {
6540 if (freq[i] == 0)
6541 chans[i] = 0;
6542 else
6543 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6544
6545 hdd_debug("freq[%d]=%d", i, freq[i]);
6546 }
6547
6548 /*
6549 * The input frequency list from user space is designed to be a
6550 * priority based frequency list. This is only to accommodate any
6551 * future request. But, current requirement is only to perform CAC
6552 * on a single channel. So, the first entry from the list is picked.
6553 *
6554 * If channel is zero, any channel in the available outdoor regulatory
6555 * domain will be selected.
6556 */
6557 ret = wlan_hdd_request_pre_cac(chans[0]);
6558 if (ret) {
6559 hdd_err("pre cac request failed with reason:%d", ret);
6560 return ret;
6561 }
6562
6563 return 0;
6564}
6565
6566/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006567 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6568 * @wiphy: Pointer to wireless phy
6569 * @wdev: Pointer to wireless device
6570 * @data: Pointer to data
6571 * @data_len: Data length
6572 *
6573 * This function is to process the p2p listen offload start vendor
6574 * command. It parses the input parameters and invoke WMA API to
6575 * send the command to firmware.
6576 *
6577 * Return: 0 on success, negative errno on failure
6578 */
6579static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6580 struct wireless_dev *wdev,
6581 const void *data,
6582 int data_len)
6583{
6584 int ret;
6585 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6586 struct net_device *dev = wdev->netdev;
6587 hdd_adapter_t *adapter;
6588 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6589 struct sir_p2p_lo_start params;
6590 QDF_STATUS status;
6591
6592 ENTER_DEV(dev);
6593
6594 ret = wlan_hdd_validate_context(hdd_ctx);
6595 if (ret)
6596 return ret;
6597
6598 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6599 hdd_err("Command not allowed in FTM mode");
6600 return -EPERM;
6601 }
6602
6603 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6604 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6605 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6606 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6607 hdd_err("Invalid device mode %d", adapter->device_mode);
6608 return -EINVAL;
6609 }
6610
6611 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6612 data, data_len, NULL)) {
6613 hdd_err("Invalid ATTR");
6614 return -EINVAL;
6615 }
6616
6617 memset(&params, 0, sizeof(params));
6618
6619 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6620 params.ctl_flags = 1; /* set to default value */
6621 else
6622 params.ctl_flags = nla_get_u32(tb
6623 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6624
6625 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6626 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6627 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6628 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6629 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6630 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6631 hdd_err("Attribute parsing failed");
6632 return -EINVAL;
6633 }
6634
6635 params.vdev_id = adapter->sessionId;
6636 params.freq = nla_get_u32(tb
6637 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6638 if ((params.freq != 2412) && (params.freq != 2437) &&
6639 (params.freq != 2462)) {
6640 hdd_err("Invalid listening channel: %d", params.freq);
6641 return -EINVAL;
6642 }
6643
6644 params.period = nla_get_u32(tb
6645 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6646 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6647 hdd_err("Invalid period: %d", params.period);
6648 return -EINVAL;
6649 }
6650
6651 params.interval = nla_get_u32(tb
6652 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6653 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6654 hdd_err("Invalid interval: %d", params.interval);
6655 return -EINVAL;
6656 }
6657
6658 params.count = nla_get_u32(tb
6659 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006660 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006661 hdd_err("Invalid count: %d", params.count);
6662 return -EINVAL;
6663 }
6664
6665 params.device_types = nla_data(tb
6666 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6667 if (params.device_types == NULL) {
6668 hdd_err("Invalid device types");
6669 return -EINVAL;
6670 }
6671
6672 params.dev_types_len = nla_len(tb
6673 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6674 if (params.dev_types_len < 8) {
6675 hdd_err("Invalid device type length: %d", params.dev_types_len);
6676 return -EINVAL;
6677 }
6678
6679 params.probe_resp_tmplt = nla_data(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6681 if (params.probe_resp_tmplt == NULL) {
6682 hdd_err("Invalid probe response template");
6683 return -EINVAL;
6684 }
6685
6686 params.probe_resp_len = nla_len(tb
6687 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6688 if (params.probe_resp_len == 0) {
6689 hdd_err("Invalid probe resp template length: %d",
6690 params.probe_resp_len);
6691 return -EINVAL;
6692 }
6693
6694 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6695 params.freq, params.period, params.interval, params.count);
6696
6697 status = wma_p2p_lo_start(&params);
6698
6699 if (!QDF_IS_STATUS_SUCCESS(status)) {
6700 hdd_err("P2P LO start failed");
6701 return -EINVAL;
6702 }
6703
6704 return 0;
6705}
6706
6707
6708/**
6709 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6710 * @wiphy: Pointer to wireless phy
6711 * @wdev: Pointer to wireless device
6712 * @data: Pointer to data
6713 * @data_len: Data length
6714 *
6715 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6716 * to process p2p listen offload start vendor command.
6717 *
6718 * Return: 0 on success, negative errno on failure
6719 */
6720static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6721 struct wireless_dev *wdev,
6722 const void *data,
6723 int data_len)
6724{
6725 int ret = 0;
6726
6727 cds_ssr_protect(__func__);
6728 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6729 data, data_len);
6730 cds_ssr_unprotect(__func__);
6731
6732 return ret;
6733}
6734
6735/**
6736 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6737 * @wiphy: Pointer to wireless phy
6738 * @wdev: Pointer to wireless device
6739 * @data: Pointer to data
6740 * @data_len: Data length
6741 *
6742 * This function is to process the p2p listen offload stop vendor
6743 * command. It invokes WMA API to send command to firmware.
6744 *
6745 * Return: 0 on success, negative errno on failure
6746 */
6747static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6748 struct wireless_dev *wdev,
6749 const void *data,
6750 int data_len)
6751{
6752 QDF_STATUS status;
6753 hdd_adapter_t *adapter;
6754 struct net_device *dev = wdev->netdev;
6755
6756 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6757 hdd_err("Command not allowed in FTM mode");
6758 return -EPERM;
6759 }
6760
6761 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6762 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6763 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6764 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6765 hdd_err("Invalid device mode");
6766 return -EINVAL;
6767 }
6768
6769 status = wma_p2p_lo_stop(adapter->sessionId);
6770
6771 if (!QDF_IS_STATUS_SUCCESS(status)) {
6772 hdd_err("P2P LO stop failed");
6773 return -EINVAL;
6774 }
6775
6776 return 0;
6777}
6778
6779/**
6780 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6781 * @wiphy: Pointer to wireless phy
6782 * @wdev: Pointer to wireless device
6783 * @data: Pointer to data
6784 * @data_len: Data length
6785 *
6786 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6787 * to process p2p listen offload stop vendor command.
6788 *
6789 * Return: 0 on success, negative errno on failure
6790 */
6791static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6792 struct wireless_dev *wdev,
6793 const void *data,
6794 int data_len)
6795{
6796 int ret = 0;
6797
6798 cds_ssr_protect(__func__);
6799 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6800 data, data_len);
6801 cds_ssr_unprotect(__func__);
6802
6803 return ret;
6804}
6805
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306806/**
6807 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6808 * @wiphy: Pointer to wireless phy
6809 * @wdev: Pointer to wireless device
6810 * @data: Pointer to data
6811 * @data_len: Data length
6812 *
6813 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6814 * to process the conditional channel switch request.
6815 *
6816 * Return: 0 on success, negative errno on failure
6817 */
6818static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6819 struct wireless_dev *wdev,
6820 const void *data,
6821 int data_len)
6822{
6823 int ret;
6824
6825 cds_ssr_protect(__func__);
6826 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6827 data, data_len);
6828 cds_ssr_unprotect(__func__);
6829
6830 return ret;
6831}
6832
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306833/*
6834 * define short names for the global vendor params
6835 * used by __wlan_hdd_cfg80211_bpf_offload()
6836 */
6837#define BPF_INVALID \
6838 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6839#define BPF_SET_RESET \
6840 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6841#define BPF_VERSION \
6842 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6843#define BPF_FILTER_ID \
6844 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6845#define BPF_PACKET_SIZE \
6846 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6847#define BPF_CURRENT_OFFSET \
6848 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6849#define BPF_PROGRAM \
6850 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6851#define BPF_MAX \
6852 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006853
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306854static const struct nla_policy
6855wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6856 [BPF_SET_RESET] = {.type = NLA_U32},
6857 [BPF_VERSION] = {.type = NLA_U32},
6858 [BPF_FILTER_ID] = {.type = NLA_U32},
6859 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6860 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6861 [BPF_PROGRAM] = {.type = NLA_U8},
6862};
6863
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006864struct bpf_offload_priv {
6865 struct sir_bpf_get_offload bpf_get_offload;
6866};
6867
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306868/**
6869 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006870 * @context: opaque context originally passed to SME. HDD always passes
6871 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306872 * @bpf_get_offload: struct for get offload
6873 *
6874 * This function receives the response/data from the lower layer and
6875 * checks to see if the thread is still waiting then post the results to
6876 * upper layer, if the request has timed out then ignore.
6877 *
6878 * Return: None
6879 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006880static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006881 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306882{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006883 struct hdd_request *request;
6884 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306885
6886 ENTER();
6887
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006888 request = hdd_request_get(context);
6889 if (!request) {
6890 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306891 return;
6892 }
6893
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006894 priv = hdd_request_priv(request);
6895 priv->bpf_get_offload = *data;
6896 hdd_request_complete(request);
6897 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306898}
6899
6900/**
6901 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6902 * @hdd_context: hdd_context
6903 * @bpf_get_offload: struct for get offload
6904 *
6905 * Return: 0 on success, error number otherwise.
6906 */
6907static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6908 struct sir_bpf_get_offload *bpf_get_offload)
6909{
6910 struct sk_buff *skb;
6911 uint32_t nl_buf_len;
6912
6913 ENTER();
6914
6915 nl_buf_len = NLMSG_HDRLEN;
6916 nl_buf_len +=
6917 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6918 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6919
6920 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6921 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006922 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306923 return -ENOMEM;
6924 }
6925
Jeff Johnson77848112016-06-29 14:52:06 -07006926 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306927 bpf_get_offload->bpf_version,
6928 bpf_get_offload->max_bytes_for_bpf_inst);
6929
6930 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6931 bpf_get_offload->max_bytes_for_bpf_inst) ||
6932 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006933 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306934 goto nla_put_failure;
6935 }
6936
6937 cfg80211_vendor_cmd_reply(skb);
6938 EXIT();
6939 return 0;
6940
6941nla_put_failure:
6942 kfree_skb(skb);
6943 return -EINVAL;
6944}
6945
6946/**
6947 * hdd_get_bpf_offload - Get BPF offload Capabilities
6948 * @hdd_ctx: Hdd context
6949 *
6950 * Return: 0 on success, errno on failure
6951 */
6952static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6953{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306954 QDF_STATUS status;
6955 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006956 void *cookie;
6957 struct hdd_request *request;
6958 struct bpf_offload_priv *priv;
6959 static const struct hdd_request_params params = {
6960 .priv_size = sizeof(*priv),
6961 .timeout_ms = WLAN_WAIT_TIME_BPF,
6962 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306963
6964 ENTER();
6965
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006966 request = hdd_request_alloc(&params);
6967 if (!request) {
6968 hdd_err("Unable to allocate request");
6969 return -EINVAL;
6970 }
6971 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306972
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006973 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6974 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006975 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306976 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006977 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006978 ret = qdf_status_to_os_return(status);
6979 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306980 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006981 ret = hdd_request_wait_for_response(request);
6982 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006983 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006984 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306985 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006986 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306987 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006988 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306989 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006990 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306991
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006992cleanup:
6993 /*
6994 * either we never sent a request to SME, we sent a request to
6995 * SME and timed out, or we sent a request to SME, received a
6996 * response from SME, and posted the response to userspace.
6997 * regardless we are done with the request.
6998 */
6999 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007001
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307002 return ret;
7003}
7004
7005/**
7006 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7007 * @hdd_ctx: Hdd context
7008 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307009 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307010 *
7011 * Return: 0 on success; errno on failure
7012 */
7013static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7014 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307015 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307016{
7017 struct sir_bpf_set_offload *bpf_set_offload;
7018 QDF_STATUS status;
7019 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307020 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307021
7022 ENTER();
7023
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307024 if (adapter->device_mode == QDF_STA_MODE ||
7025 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7026 if (!hdd_conn_is_connected(
7027 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7028 hdd_err("Not in Connected state!");
7029 return -ENOTSUPP;
7030 }
7031 }
7032
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307033 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7034 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007035 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307036 return -ENOMEM;
7037 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307038
7039 /* Parse and fetch bpf packet size */
7040 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007041 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307042 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307043 goto fail;
7044 }
7045 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7046
7047 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007048 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307049 goto post_sme;
7050 }
7051
7052 /* Parse and fetch bpf program */
7053 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007054 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307055 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307056 goto fail;
7057 }
7058
7059 prog_len = nla_len(tb[BPF_PROGRAM]);
7060 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307061
7062 if (bpf_set_offload->program == NULL) {
7063 hdd_err("qdf_mem_malloc failed for bpf offload program");
7064 ret = -ENOMEM;
7065 goto fail;
7066 }
7067
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307068 bpf_set_offload->current_length = prog_len;
7069 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307070 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307071
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307072 hdd_info("BPF set instructions");
7073 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7074 bpf_set_offload->program, prog_len);
7075
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076 /* Parse and fetch filter Id */
7077 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007078 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307079 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307080 goto fail;
7081 }
7082 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7083
7084 /* Parse and fetch current offset */
7085 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007086 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307087 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307088 goto fail;
7089 }
7090 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7091
7092post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007093 hdd_notice("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307094 bpf_set_offload->session_id,
7095 bpf_set_offload->version,
7096 bpf_set_offload->filter_id,
7097 bpf_set_offload->total_length,
7098 bpf_set_offload->current_length,
7099 bpf_set_offload->current_offset);
7100
7101 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7102 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007103 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307104 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307105 goto fail;
7106 }
7107 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108
7109fail:
7110 if (bpf_set_offload->current_length)
7111 qdf_mem_free(bpf_set_offload->program);
7112 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307113 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307114}
7115
7116/**
7117 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7118 * @wiphy: wiphy structure pointer
7119 * @wdev: Wireless device structure pointer
7120 * @data: Pointer to the data received
7121 * @data_len: Length of @data
7122 *
7123 * Return: 0 on success; errno on failure
7124 */
7125static int
7126__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7127 struct wireless_dev *wdev,
7128 const void *data, int data_len)
7129{
7130 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7131 struct net_device *dev = wdev->netdev;
7132 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7133 struct nlattr *tb[BPF_MAX + 1];
7134 int ret_val, packet_filter_subcmd;
7135
7136 ENTER();
7137
7138 ret_val = wlan_hdd_validate_context(hdd_ctx);
7139 if (ret_val)
7140 return ret_val;
7141
7142 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007143 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307144 return -EINVAL;
7145 }
7146
7147 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007148 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307149 return -ENOTSUPP;
7150 }
7151
7152 if (nla_parse(tb, BPF_MAX, data, data_len,
7153 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007154 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307155 return -EINVAL;
7156 }
7157
7158 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007159 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307160 return -EINVAL;
7161 }
7162
7163 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7164
7165 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7166 return hdd_get_bpf_offload(hdd_ctx);
7167 else
7168 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307169 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307170}
7171
7172/**
7173 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7174 * @wiphy: wiphy structure pointer
7175 * @wdev: Wireless device structure pointer
7176 * @data: Pointer to the data received
7177 * @data_len: Length of @data
7178 *
7179 * Return: 0 on success; errno on failure
7180 */
7181
7182static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7183 struct wireless_dev *wdev,
7184 const void *data, int data_len)
7185{
7186 int ret;
7187
7188 cds_ssr_protect(__func__);
7189 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7190 cds_ssr_unprotect(__func__);
7191
7192 return ret;
7193}
7194
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307195/**
7196 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7197 * @pre_cac_adapter: AP adapter used for pre cac
7198 * @status: Status (true or false)
7199 * @handle: Global handle
7200 *
7201 * Sets the status of pre cac i.e., whether the pre cac is active or not
7202 *
7203 * Return: Zero on success, non-zero on failure
7204 */
7205static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7206 bool status, tHalHandle handle)
7207{
7208 QDF_STATUS ret;
7209
7210 ret = wlan_sap_set_pre_cac_status(
7211 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7212 if (QDF_IS_STATUS_ERROR(ret))
7213 return -EINVAL;
7214
7215 return 0;
7216}
7217
7218/**
7219 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7220 * @ap_adapter: AP adapter
7221 * @chan_before_pre_cac: Channel
7222 *
7223 * Saves the channel which the AP was beaconing on before moving to the pre
7224 * cac channel. If radar is detected on the pre cac channel, this saved
7225 * channel will be used for AP operations.
7226 *
7227 * Return: Zero on success, non-zero on failure
7228 */
7229static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7230 uint8_t chan_before_pre_cac)
7231{
7232 QDF_STATUS ret;
7233
7234 ret = wlan_sap_set_chan_before_pre_cac(
7235 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7236 if (QDF_IS_STATUS_ERROR(ret))
7237 return -EINVAL;
7238
7239 return 0;
7240}
7241
7242/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307243 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7244 * are in nol list from provided channel list
7245 * @adapter: AP adapter
7246 * @channel_count: channel count
7247 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307248 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307249 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307250 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307251static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7252 uint32_t *channel_count,
7253 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307254{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307255 uint8_t i, j;
7256 uint32_t nol_len = 0;
7257 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7258 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7259 uint32_t chan_count;
7260 bool found;
7261 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307262
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307263 if (!hdd_ctx) {
7264 hdd_err("hdd ctx not found");
7265 *channel_count = 0;
7266 return;
7267 }
7268
7269 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7270 hdd_err("invalid channel count %d", *channel_count);
7271 return;
7272 }
7273
7274 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7275 if (nol_len == 0)
7276 return;
7277
7278 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7279 chan_count = *channel_count;
7280 qdf_mem_zero(channel_list, chan_count);
7281 *channel_count = 0;
7282
7283 for (i = 0 ; i < chan_count; i++) {
7284 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7285 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7286 continue;
7287 found = false;
7288 for (j = 0; j < nol_len; j++) {
7289 if (tmp_chan_list[i] == nol[j]) {
7290 found = true;
7291 hdd_notice("skipped channel %d due to nol",
7292 nol[j]);
7293 break;
7294 }
7295 }
7296 if (!found) {
7297 channel_list[*channel_count] = tmp_chan_list[i];
7298 *channel_count = *channel_count + 1;
7299 }
7300 }
7301}
7302
7303int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7304 uint32_t *channel_count,
7305 uint8_t *channel_list)
7306{
7307 tsap_Config_t *sap_config;
7308
7309 sap_config = &adapter->sessionCtx.ap.sapConfig;
7310
7311 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7312 sap_config->acs_cfg.ch_list_count);
7313 *channel_count = sap_config->acs_cfg.ch_list_count;
7314 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7315
7316 if (*channel_count == 0) {
7317 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307318 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307319 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307320
7321 return 0;
7322}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307323
7324/**
7325 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7326 * @hdd_ctx: HDD context
7327 * @ap_adapter: AP adapter
7328 * @channel: Channel requested by userspace
7329 * @pre_cac_chan: Pointer to the pre CAC channel
7330 *
7331 * Validates the channel provided by userspace. If user provided channel 0,
7332 * a valid outdoor channel must be selected from the regulatory channel.
7333 *
7334 * Return: Zero on success and non zero value on error
7335 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007336static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7337 hdd_adapter_t *ap_adapter,
7338 uint8_t channel,
7339 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307340{
7341 uint32_t i, j;
7342 QDF_STATUS status;
7343 int ret;
7344 uint8_t nol[QDF_MAX_NUM_CHAN];
7345 uint32_t nol_len = 0, weight_len = 0;
7346 bool found;
7347 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7348 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7349 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7350
7351 if (0 == channel) {
7352 /* Channel is not obtained from PCL because PCL may not have
7353 * the entire channel list. For example: if SAP is up on
7354 * channel 6 and PCL is queried for the next SAP interface,
7355 * if SCC is preferred, the PCL will contain only the channel
7356 * 6. But, we are in need of a DFS channel. So, going with the
7357 * first channel from the valid channel list.
7358 */
7359 status = cds_get_valid_chans(channel_list, &len);
7360 if (QDF_IS_STATUS_ERROR(status)) {
7361 hdd_err("Failed to get channel list");
7362 return -EINVAL;
7363 }
7364 cds_update_with_safe_channel_list(channel_list, &len,
7365 pcl_weights, weight_len);
7366 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7367 for (i = 0; i < len; i++) {
7368 found = false;
7369 for (j = 0; j < nol_len; j++) {
7370 if (channel_list[i] == nol[j]) {
7371 found = true;
7372 break;
7373 }
7374 }
7375 if (found)
7376 continue;
7377 if (CDS_IS_DFS_CH(channel_list[i])) {
7378 *pre_cac_chan = channel_list[i];
7379 break;
7380 }
7381 }
7382 if (*pre_cac_chan == 0) {
7383 hdd_err("unable to find outdoor channel");
7384 return -EINVAL;
7385 }
7386 } else {
7387 /* Only when driver selects a channel, check is done for
7388 * unnsafe and NOL channels. When user provides a fixed channel
7389 * the user is expected to take care of this.
7390 */
7391 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7392 !CDS_IS_DFS_CH(channel)) {
7393 hdd_err("Invalid channel for pre cac:%d", channel);
7394 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307395 }
Jeff Johnson68755312017-02-10 11:46:55 -08007396
7397 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307398 }
7399 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7400 return 0;
7401}
7402
7403/**
7404 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7405 * @channel: Channel option provided by userspace
7406 *
7407 * Sets the driver to the required hardware mode and start an adapater for
7408 * pre CAC which will mimic an AP.
7409 *
7410 * Return: Zero on success, non-zero value on error
7411 */
7412int wlan_hdd_request_pre_cac(uint8_t channel)
7413{
Krunal Sonib37bb352016-12-20 14:12:21 -08007414 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307415 hdd_context_t *hdd_ctx;
7416 int ret;
7417 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7418 hdd_ap_ctx_t *hdd_ap_ctx;
7419 QDF_STATUS status;
7420 struct wiphy *wiphy;
7421 struct net_device *dev;
7422 struct cfg80211_chan_def chandef;
7423 enum nl80211_channel_type channel_type;
7424 uint32_t freq;
7425 struct ieee80211_channel *chan;
7426 tHalHandle handle;
7427 bool val;
7428
7429 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7430 if (0 != wlan_hdd_validate_context(hdd_ctx))
7431 return -EINVAL;
7432
7433 if (cds_get_connection_count() > 1) {
7434 hdd_err("pre cac not allowed in concurrency");
7435 return -EINVAL;
7436 }
7437
7438 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7439 if (!ap_adapter) {
7440 hdd_err("unable to get SAP adapter");
7441 return -EINVAL;
7442 }
7443
7444 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7445 if (!handle) {
7446 hdd_err("Invalid handle");
7447 return -EINVAL;
7448 }
7449
7450 val = wlan_sap_is_pre_cac_active(handle);
7451 if (val) {
7452 hdd_err("pre cac is already in progress");
7453 return -EINVAL;
7454 }
7455
7456 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7457 if (!hdd_ap_ctx) {
7458 hdd_err("SAP context is NULL");
7459 return -EINVAL;
7460 }
7461
7462 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7463 hdd_err("SAP is already on DFS channel:%d",
7464 hdd_ap_ctx->operatingChannel);
7465 return -EINVAL;
7466 }
7467
7468 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7469 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7470 hdd_ap_ctx->operatingChannel);
7471 return -EINVAL;
7472 }
7473
Krunal Sonib37bb352016-12-20 14:12:21 -08007474 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7475 if (!mac_addr) {
7476 hdd_err("can't add virtual intf: Not getting valid mac addr");
7477 return -EINVAL;
7478 }
7479
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307480 hdd_info("channel:%d", channel);
7481
7482 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7483 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007484 if (ret != 0) {
7485 hdd_err("can't validate pre-cac channel");
7486 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307487 }
7488
7489 hdd_debug("starting pre cac SAP adapter");
7490
7491 /* Starting a SAP adapter:
7492 * Instead of opening an adapter, we could just do a SME open session
7493 * for AP type. But, start BSS would still need an adapter.
7494 * So, this option is not taken.
7495 *
7496 * hdd open adapter is going to register this precac interface with
7497 * user space. This interface though exposed to user space will be in
7498 * DOWN state. Consideration was done to avoid this registration to the
7499 * user space. But, as part of SAP operations multiple events are sent
7500 * to user space. Some of these events received from unregistered
7501 * interface was causing crashes. So, retaining the registration.
7502 *
7503 * So, this interface would remain registered and will remain in DOWN
7504 * state for the CAC duration. We will add notes in the feature
7505 * announcement to not use this temporary interface for any activity
7506 * from user space.
7507 */
7508 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007509 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307510 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307511 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007512 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307513 }
7514
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307515 /*
7516 * This interface is internally created by the driver. So, no interface
7517 * up comes for this interface from user space and hence starting
7518 * the adapter internally.
7519 */
7520 if (hdd_start_adapter(pre_cac_adapter)) {
7521 hdd_err("error starting the pre cac adapter");
7522 goto close_pre_cac_adapter;
7523 }
7524
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307525 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7526
7527 wiphy = hdd_ctx->wiphy;
7528 dev = pre_cac_adapter->dev;
7529
7530 /* Since this is only a dummy interface lets us use the IEs from the
7531 * other active SAP interface. In regular scenarios, these IEs would
7532 * come from the user space entity
7533 */
7534 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7535 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7536 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7537 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307538 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307539 }
7540 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7541 ap_adapter->sessionCtx.ap.beacon,
7542 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7543 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7544 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7545 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7546 ap_adapter->sessionCtx.ap.sapConfig.authType;
7547
7548 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7549 * to operate on the same bandwidth as that of the 2.4GHz operations.
7550 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7551 */
7552 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7553 case CH_WIDTH_20MHZ:
7554 channel_type = NL80211_CHAN_HT20;
7555 break;
7556 case CH_WIDTH_40MHZ:
7557 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7558 ap_adapter->sessionCtx.ap.sapConfig.channel)
7559 channel_type = NL80211_CHAN_HT40PLUS;
7560 else
7561 channel_type = NL80211_CHAN_HT40MINUS;
7562 break;
7563 default:
7564 channel_type = NL80211_CHAN_NO_HT;
7565 break;
7566 }
7567
7568 freq = cds_chan_to_freq(pre_cac_chan);
7569 chan = __ieee80211_get_channel(wiphy, freq);
7570 if (!chan) {
7571 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307572 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307573 }
7574
7575 cfg80211_chandef_create(&chandef, chan, channel_type);
7576
7577 hdd_debug("orig width:%d channel_type:%d freq:%d",
7578 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7579 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007580 /*
7581 * Doing update after opening and starting pre-cac adapter will make
7582 * sure that driver won't do hardware mode change if there are any
7583 * initial hick-ups or issues in pre-cac adapter's configuration.
7584 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7585 * connection update should result in DBS mode
7586 */
7587 status = cds_update_and_wait_for_connection_update(
7588 ap_adapter->sessionId,
7589 pre_cac_chan,
7590 SIR_UPDATE_REASON_PRE_CAC);
7591 if (QDF_IS_STATUS_ERROR(status)) {
7592 hdd_err("error in moving to DBS mode");
7593 goto stop_close_pre_cac_adapter;
7594 }
7595
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307596
7597 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7598 if (0 != ret) {
7599 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307600 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307601 }
7602
7603 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7604 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007605 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307606 if (QDF_IS_STATUS_ERROR(status)) {
7607 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307608 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307609 }
7610
7611 /*
7612 * The pre cac status is set here. But, it would not be reset explicitly
7613 * anywhere, since after the pre cac success/failure, the pre cac
7614 * adapter itself would be removed.
7615 */
7616 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7617 if (0 != ret) {
7618 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307619 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307620 }
7621
7622 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7623 hdd_ap_ctx->operatingChannel);
7624 if (0 != ret) {
7625 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307626 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307627 }
7628
7629 ap_adapter->pre_cac_chan = pre_cac_chan;
7630
7631 return 0;
7632
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307633stop_close_pre_cac_adapter:
7634 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307635 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7636 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307637close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307638 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007639release_intf_addr_and_return_failure:
7640 /*
7641 * Release the interface address as the adapter
7642 * failed to start, if you don't release then next
7643 * adapter which is trying to come wouldn't get valid
7644 * mac address. Remember we have limited pool of mac addresses
7645 */
7646 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307647 return -EINVAL;
7648}
7649
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307650static const struct nla_policy
7651wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7652 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7653};
7654
Agrawal Ashish65634612016-08-18 13:24:32 +05307655static const struct nla_policy
7656wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7657 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7658 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7659};
7660
7661/**
7662 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7663 * @wiphy: Pointer to wireless phy
7664 * @wdev: Pointer to wireless device
7665 * @data: Pointer to data
7666 * @data_len: Length of @data
7667 *
7668 * This function parses the incoming NL vendor command data attributes and
7669 * updates the SAP context about channel_hint and DFS mode.
7670 * If channel_hint is set, SAP will choose that channel
7671 * as operating channel.
7672 *
7673 * If DFS mode is enabled, driver will include DFS channels
7674 * in ACS else driver will skip DFS channels.
7675 *
7676 * Return: 0 on success, negative errno on failure
7677 */
7678static int
7679__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7680 struct wireless_dev *wdev,
7681 const void *data, int data_len)
7682{
7683 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7684 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7685 int ret;
7686 struct acs_dfs_policy *acs_policy;
7687 int mode = DFS_MODE_NONE;
7688 int channel_hint = 0;
7689
7690 ENTER_DEV(wdev->netdev);
7691
7692 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7693 hdd_err("Command not allowed in FTM mode");
7694 return -EINVAL;
7695 }
7696
7697 ret = wlan_hdd_validate_context(hdd_ctx);
7698 if (0 != ret)
7699 return ret;
7700
7701 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7702 data, data_len,
7703 wlan_hdd_set_acs_dfs_config_policy)) {
7704 hdd_err("invalid attr");
7705 return -EINVAL;
7706 }
7707
7708 acs_policy = &hdd_ctx->acs_policy;
7709 /*
7710 * SCM sends this attribute to restrict SAP from choosing
7711 * DFS channels from ACS.
7712 */
7713 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7714 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7715
7716 if (!IS_DFS_MODE_VALID(mode)) {
7717 hdd_err("attr acs dfs mode is not valid");
7718 return -EINVAL;
7719 }
7720 acs_policy->acs_dfs_mode = mode;
7721
7722 /*
7723 * SCM sends this attribute to provide an active channel,
7724 * to skip redundant ACS between drivers, and save driver start up time
7725 */
7726 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7727 channel_hint = nla_get_u8(
7728 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7729
7730 if (!IS_CHANNEL_VALID(channel_hint)) {
7731 hdd_err("acs channel is not valid");
7732 return -EINVAL;
7733 }
7734 acs_policy->acs_channel = channel_hint;
7735
7736 return 0;
7737}
7738
7739/**
7740 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7741 * @wiphy: wiphy structure pointer
7742 * @wdev: Wireless device structure pointer
7743 * @data: Pointer to the data received
7744 * @data_len: Length of @data
7745 *
7746 * This function parses the incoming NL vendor command data attributes and
7747 * updates the SAP context about channel_hint and DFS mode.
7748 *
7749 * Return: 0 on success; errno on failure
7750 */
7751static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7752 struct wireless_dev *wdev,
7753 const void *data, int data_len)
7754{
7755 int ret;
7756
7757 cds_ssr_protect(__func__);
7758 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7759 cds_ssr_unprotect(__func__);
7760
7761 return ret;
7762}
7763
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307764/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307765 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7766 * @mode : cfg80211 dfs mode
7767 *
7768 * Return: return csr sta roam dfs mode else return NONE
7769 */
7770static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7771 enum dfs_mode mode)
7772{
7773 switch (mode) {
7774 case DFS_MODE_ENABLE:
7775 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7776 break;
7777 case DFS_MODE_DISABLE:
7778 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7779 break;
7780 case DFS_MODE_DEPRIORITIZE:
7781 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7782 break;
7783 default:
7784 hdd_err("STA Roam policy dfs mode is NONE");
7785 return CSR_STA_ROAM_POLICY_NONE;
7786 }
7787}
7788
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307789/*
7790 * hdd_get_sap_operating_band: Get current operating channel
7791 * for sap.
7792 * @hdd_ctx: hdd context
7793 *
7794 * Return : Corresponding band for SAP operating channel
7795 */
7796uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7797{
7798 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7799 QDF_STATUS status;
7800 hdd_adapter_t *adapter;
7801 uint8_t operating_channel = 0;
7802 uint8_t sap_operating_band = 0;
7803 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7804 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7805 adapter = adapter_node->pAdapter;
7806
7807 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7808 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7809 &next);
7810 adapter_node = next;
7811 continue;
7812 }
7813 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7814 if (IS_24G_CH(operating_channel))
7815 sap_operating_band = eCSR_BAND_24;
7816 else if (IS_5G_CH(operating_channel))
7817 sap_operating_band = eCSR_BAND_5G;
7818 else
7819 sap_operating_band = eCSR_BAND_ALL;
7820 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7821 &next);
bings373b99b2017-01-23 10:35:08 +08007822 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307823 }
7824 return sap_operating_band;
7825}
7826
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307827static const struct nla_policy
7828wlan_hdd_set_sta_roam_config_policy[
7829QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7830 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7831 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7832};
7833
7834/**
7835 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7836 * for station connection or roaming.
7837 * @wiphy: Pointer to wireless phy
7838 * @wdev: Pointer to wireless device
7839 * @data: Pointer to data
7840 * @data_len: Length of @data
7841 *
7842 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7843 * channels needs to be skipped in scanning or not.
7844 * If dfs_mode is disabled, driver will not scan DFS channels.
7845 * If skip_unsafe_channels is set, driver will skip unsafe channels
7846 * in Scanning.
7847 *
7848 * Return: 0 on success, negative errno on failure
7849 */
7850static int
7851__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7852 struct wireless_dev *wdev,
7853 const void *data, int data_len)
7854{
7855 struct net_device *dev = wdev->netdev;
7856 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7857 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7858 struct nlattr *tb[
7859 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7860 int ret;
7861 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7862 enum dfs_mode mode = DFS_MODE_NONE;
7863 bool skip_unsafe_channels = false;
7864 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307865 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307866
7867 ENTER_DEV(dev);
7868
7869 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7870 hdd_err("Command not allowed in FTM mode");
7871 return -EINVAL;
7872 }
7873
7874 ret = wlan_hdd_validate_context(hdd_ctx);
7875 if (0 != ret)
7876 return ret;
7877 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7878 data, data_len,
7879 wlan_hdd_set_sta_roam_config_policy)) {
7880 hdd_err("invalid attr");
7881 return -EINVAL;
7882 }
7883 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7884 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7885 if (!IS_DFS_MODE_VALID(mode)) {
7886 hdd_err("attr sta roam dfs mode policy is not valid");
7887 return -EINVAL;
7888 }
7889
7890 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7891
7892 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7893 skip_unsafe_channels = nla_get_u8(
7894 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307895 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307896 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307897 skip_unsafe_channels, adapter->sessionId,
7898 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307899
7900 if (!QDF_IS_STATUS_SUCCESS(status)) {
7901 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7902 return -EINVAL;
7903 }
7904 return 0;
7905}
7906
7907/**
7908 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7909 * connection and roaming for station.
7910 * @wiphy: wiphy structure pointer
7911 * @wdev: Wireless device structure pointer
7912 * @data: Pointer to the data received
7913 * @data_len: Length of @data
7914 *
7915 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7916 * channels needs to be skipped in scanning or not.
7917 * If dfs_mode is disabled, driver will not scan DFS channels.
7918 * If skip_unsafe_channels is set, driver will skip unsafe channels
7919 * in Scanning.
7920 * Return: 0 on success; errno on failure
7921 */
7922static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7923 struct wireless_dev *wdev,
7924 const void *data, int data_len)
7925{
7926 int ret;
7927
7928 cds_ssr_protect(__func__);
7929 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7930 cds_ssr_unprotect(__func__);
7931
7932 return ret;
7933}
7934
Agrawal Ashish467dde42016-09-08 18:44:22 +05307935#ifdef FEATURE_WLAN_CH_AVOID
7936/**
7937 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7938 * is on unsafe channel.
7939 * @wiphy: wiphy structure pointer
7940 * @wdev: Wireless device structure pointer
7941 * @data: Pointer to the data received
7942 * @data_len: Length of @data
7943 *
7944 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7945 * on any of unsafe channels.
7946 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7947 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7948 *
7949 * Return: 0 on success; errno on failure
7950 */
7951static int
7952__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7953 struct wireless_dev *wdev,
7954 const void *data, int data_len)
7955{
7956 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7957 int ret;
7958 uint16_t unsafe_channel_count;
7959 int unsafe_channel_index;
7960 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7961
7962 ENTER_DEV(wdev->netdev);
7963
7964 if (!qdf_ctx) {
7965 cds_err("qdf_ctx is NULL");
7966 return -EINVAL;
7967 }
7968
7969 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7970 hdd_err("Command not allowed in FTM mode");
7971 return -EINVAL;
7972 }
7973
7974 ret = wlan_hdd_validate_context(hdd_ctx);
7975 if (0 != ret)
7976 return ret;
7977 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7978 &(hdd_ctx->unsafe_channel_count),
7979 sizeof(hdd_ctx->unsafe_channel_list));
7980
7981 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7982 (uint16_t)NUM_CHANNELS);
7983 for (unsafe_channel_index = 0;
7984 unsafe_channel_index < unsafe_channel_count;
7985 unsafe_channel_index++) {
7986 hdd_info("Channel %d is not safe",
7987 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7988 }
7989 hdd_unsafe_channel_restart_sap(hdd_ctx);
7990 return 0;
7991}
7992
7993/**
7994 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7995 * is on unsafe channel.
7996 * @wiphy: wiphy structure pointer
7997 * @wdev: Wireless device structure pointer
7998 * @data: Pointer to the data received
7999 * @data_len: Length of @data
8000 *
8001 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8002 * on any of unsafe channels.
8003 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8004 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8005 *
8006 * Return: 0 on success; errno on failure
8007 */
8008static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8009 struct wireless_dev *wdev,
8010 const void *data, int data_len)
8011{
8012 int ret;
8013
8014 cds_ssr_protect(__func__);
8015 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8016 cds_ssr_unprotect(__func__);
8017
8018 return ret;
8019}
8020
8021#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308022/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308023 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8024 * SAP is on unsafe channel.
8025 * @wiphy: wiphy structure pointer
8026 * @wdev: Wireless device structure pointer
8027 * @data: Pointer to the data received
8028 * @data_len: Length of @data
8029 *
8030 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8031 * driver.
8032 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8033 * will initiate restart of sap.
8034 *
8035 * Return: 0 on success; errno on failure
8036 */
8037static int
8038__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8039 struct wireless_dev *wdev,
8040 const void *data, int data_len)
8041{
8042 struct net_device *ndev = wdev->netdev;
8043 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8044 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8045 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8046 uint8_t config_channel = 0;
8047 hdd_ap_ctx_t *ap_ctx;
8048 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308049 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308050
8051 ENTER();
8052
8053 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008054 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308055 return -EINVAL;
8056 }
8057
8058 ret = wlan_hdd_validate_context(hdd_ctx);
8059 if (0 != ret)
8060 return -EINVAL;
8061
8062 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8063 data, data_len,
8064 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008065 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308066 return -EINVAL;
8067 }
8068
8069 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8070 if (!test_bit(SOFTAP_BSS_STARTED,
8071 &hostapd_adapter->event_flags)) {
8072 hdd_err("SAP is not started yet. Restart sap will be invalid");
8073 return -EINVAL;
8074 }
8075
8076 config_channel =
8077 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8078
8079 if (!((IS_24G_CH(config_channel)) ||
8080 (IS_5G_CH(config_channel)))) {
8081 hdd_err("Channel %d is not valid to restart SAP",
8082 config_channel);
8083 return -ENOTSUPP;
8084 }
8085
8086 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8087 ap_ctx->sapConfig.channel = config_channel;
8088 ap_ctx->sapConfig.ch_params.ch_width =
8089 ap_ctx->sapConfig.ch_width_orig;
8090
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008091 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308092 ap_ctx->sapConfig.sec_ch,
8093 &ap_ctx->sapConfig.ch_params);
8094
8095 cds_restart_sap(hostapd_adapter);
8096 }
8097
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308098 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8099 uint32_t freq_len, i;
8100 uint32_t *freq;
8101 uint8_t chans[QDF_MAX_NUM_CHAN];
8102
8103 hdd_debug("setting mandatory freq/chan list");
8104
8105 freq_len = nla_len(
8106 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8107 sizeof(uint32_t);
8108
8109 if (freq_len > QDF_MAX_NUM_CHAN) {
8110 hdd_err("insufficient space to hold channels");
8111 return -ENOMEM;
8112 }
8113
8114 freq = nla_data(
8115 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8116
8117 hdd_debug("freq_len=%d", freq_len);
8118
8119 for (i = 0; i < freq_len; i++) {
8120 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8121 hdd_debug("freq[%d]=%d", i, freq[i]);
8122 }
8123
8124 status = cds_set_sap_mandatory_channels(chans, freq_len);
8125 if (QDF_IS_STATUS_ERROR(status))
8126 return -EINVAL;
8127 }
8128
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308129 return 0;
8130}
8131
8132/**
8133 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8134 * @wiphy: wiphy structure pointer
8135 * @wdev: Wireless device structure pointer
8136 * @data: Pointer to the data received
8137 * @data_len: Length of @data
8138 *
8139 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8140 * driver.
8141 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8142 * will initiate restart of sap.
8143 *
8144 * Return: 0 on success; errno on failure
8145 */
8146static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8147 struct wireless_dev *wdev,
8148 const void *data, int data_len)
8149{
8150 int ret;
8151
8152 cds_ssr_protect(__func__);
8153 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8154 wdev, data, data_len);
8155 cds_ssr_unprotect(__func__);
8156
8157 return ret;
8158}
8159
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308160#undef BPF_INVALID
8161#undef BPF_SET_RESET
8162#undef BPF_VERSION
8163#undef BPF_ID
8164#undef BPF_PACKET_SIZE
8165#undef BPF_CURRENT_OFFSET
8166#undef BPF_PROGRAM
8167#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308168
8169/**
8170 * define short names for the global vendor params
8171 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8172 */
8173#define PARAM_TOTAL_CMD_EVENT_WAKE \
8174 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8175#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8176 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8177#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8178 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8179#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8180 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8181#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8182 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8183#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8184 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8185#define PARAM_TOTAL_RX_DATA_WAKE \
8186 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8187#define PARAM_RX_UNICAST_CNT \
8188 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8189#define PARAM_RX_MULTICAST_CNT \
8190 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8191#define PARAM_RX_BROADCAST_CNT \
8192 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8193#define PARAM_ICMP_PKT \
8194 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8195#define PARAM_ICMP6_PKT \
8196 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8197#define PARAM_ICMP6_RA \
8198 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8199#define PARAM_ICMP6_NA \
8200 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8201#define PARAM_ICMP6_NS \
8202 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8203#define PARAM_ICMP4_RX_MULTICAST_CNT \
8204 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8205#define PARAM_ICMP6_RX_MULTICAST_CNT \
8206 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8207#define PARAM_OTHER_RX_MULTICAST_CNT \
8208 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308209#define PARAM_RSSI_BREACH_CNT \
8210 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8211#define PARAM_LOW_RSSI_CNT \
8212 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8213#define PARAM_GSCAN_CNT \
8214 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8215#define PARAM_PNO_COMPLETE_CNT \
8216 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8217#define PARAM_PNO_MATCH_CNT \
8218 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8219
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308220
8221
8222/**
8223 * hdd_send_wakelock_stats() - API to send wakelock stats
8224 * @ctx: context to be passed to callback
8225 * @data: data passed to callback
8226 *
8227 * This function is used to send wake lock stats to HAL layer
8228 *
8229 * Return: 0 on success, error number otherwise.
8230 */
8231static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8232 const struct sir_wake_lock_stats *data)
8233{
8234 struct sk_buff *skb;
8235 uint32_t nl_buf_len;
8236 uint32_t total_rx_data_wake, rx_multicast_cnt;
8237 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308238 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308239
8240 ENTER();
8241
8242 nl_buf_len = NLMSG_HDRLEN;
8243 nl_buf_len +=
8244 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8245 (NLMSG_HDRLEN + sizeof(uint32_t));
8246
8247 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8248
8249 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008250 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308251 return -ENOMEM;
8252 }
8253
Jeff Johnson64943bd2016-08-23 13:14:06 -07008254 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308255 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008256 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308257 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008258 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308259 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008260 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308261 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008262 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308263 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008264 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308265 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008266 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308267 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008268 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8269 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308270 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308271 hdd_info("wow_rssi_breach_wake_up_count %d",
8272 data->wow_rssi_breach_wake_up_count);
8273 hdd_info("wow_low_rssi_wake_up_count %d",
8274 data->wow_low_rssi_wake_up_count);
8275 hdd_info("wow_gscan_wake_up_count %d",
8276 data->wow_gscan_wake_up_count);
8277 hdd_info("wow_pno_complete_wake_up_count %d",
8278 data->wow_pno_complete_wake_up_count);
8279 hdd_info("wow_pno_match_wake_up_count %d",
8280 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308281
8282 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308283 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308284
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308285 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308286 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308287
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308288 rx_multicast_cnt =
8289 data->wow_ipv4_mcast_wake_up_count +
8290 ipv6_rx_multicast_addr_cnt;
8291
8292 total_rx_data_wake =
8293 data->wow_ucast_wake_up_count +
8294 data->wow_bcast_wake_up_count +
8295 rx_multicast_cnt;
8296
8297 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8298 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8299 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8300 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8301 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8302 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8303 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8304 total_rx_data_wake) ||
8305 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8306 data->wow_ucast_wake_up_count) ||
8307 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8308 rx_multicast_cnt) ||
8309 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8310 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308311 nla_put_u32(skb, PARAM_ICMP_PKT,
8312 data->wow_icmpv4_count) ||
8313 nla_put_u32(skb, PARAM_ICMP6_PKT,
8314 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308315 nla_put_u32(skb, PARAM_ICMP6_RA,
8316 data->wow_ipv6_mcast_ra_stats) ||
8317 nla_put_u32(skb, PARAM_ICMP6_NA,
8318 data->wow_ipv6_mcast_na_stats) ||
8319 nla_put_u32(skb, PARAM_ICMP6_NS,
8320 data->wow_ipv6_mcast_ns_stats) ||
8321 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8322 data->wow_ipv4_mcast_wake_up_count) ||
8323 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8324 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308325 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8326 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8327 data->wow_rssi_breach_wake_up_count) ||
8328 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8329 data->wow_low_rssi_wake_up_count) ||
8330 nla_put_u32(skb, PARAM_GSCAN_CNT,
8331 data->wow_gscan_wake_up_count) ||
8332 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8333 data->wow_pno_complete_wake_up_count) ||
8334 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8335 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008336 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308337 goto nla_put_failure;
8338 }
8339
8340 cfg80211_vendor_cmd_reply(skb);
8341
8342 EXIT();
8343 return 0;
8344
8345nla_put_failure:
8346 kfree_skb(skb);
8347 return -EINVAL;
8348}
8349
8350/**
8351 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8352 * @wiphy: wiphy pointer
8353 * @wdev: pointer to struct wireless_dev
8354 * @data: pointer to incoming NL vendor data
8355 * @data_len: length of @data
8356 *
8357 * This function parses the incoming NL vendor command data attributes and
8358 * invokes the SME Api and blocks on a completion variable.
8359 * WMA copies required data and invokes callback
8360 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8361 *
8362 * Return: 0 on success; error number otherwise.
8363 */
8364static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8365 struct wireless_dev *wdev,
8366 const void *data,
8367 int data_len)
8368{
8369 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8370 int status, ret;
8371 struct sir_wake_lock_stats wake_lock_stats;
8372 QDF_STATUS qdf_status;
8373
8374 ENTER();
8375
8376 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008377 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308378 return -EINVAL;
8379 }
8380
8381 status = wlan_hdd_validate_context(hdd_ctx);
8382 if (0 != status)
8383 return -EINVAL;
8384
8385 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8386 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008387 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308388 return -EINVAL;
8389 }
8390
8391 ret = hdd_send_wakelock_stats(hdd_ctx,
8392 &wake_lock_stats);
8393 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008394 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308395
8396 EXIT();
8397 return ret;
8398}
8399
8400/**
8401 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8402 * @wiphy: wiphy pointer
8403 * @wdev: pointer to struct wireless_dev
8404 * @data: pointer to incoming NL vendor data
8405 * @data_len: length of @data
8406 *
8407 * This function parses the incoming NL vendor command data attributes and
8408 * invokes the SME Api and blocks on a completion variable.
8409 * WMA copies required data and invokes callback
8410 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8411 *
8412 * Return: 0 on success; error number otherwise.
8413 */
8414static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8415 struct wireless_dev *wdev,
8416 const void *data, int data_len)
8417{
8418 int ret;
8419
8420 cds_ssr_protect(__func__);
8421 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8422 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008423 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308424
8425 return ret;
8426}
8427
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308428/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308429 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8430 * @wiphy: wiphy structure pointer
8431 * @wdev: Wireless device structure pointer
8432 * @data: Pointer to the data received
8433 * @data_len: Length of @data
8434 *
8435 * This function reads wmi max bus size and fill in the skb with
8436 * NL attributes and send up the NL event.
8437 * Return: 0 on success; errno on failure
8438 */
8439static int
8440__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8441 struct wireless_dev *wdev,
8442 const void *data, int data_len)
8443{
8444 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8445 int ret_val;
8446 struct sk_buff *skb;
8447 uint32_t nl_buf_len;
8448
8449 ENTER();
8450
8451 ret_val = wlan_hdd_validate_context(hdd_ctx);
8452 if (ret_val)
8453 return ret_val;
8454
8455 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8456 hdd_err("Command not allowed in FTM mode");
8457 return -EINVAL;
8458 }
8459
8460 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8461
8462 nl_buf_len = NLMSG_HDRLEN;
8463 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8464
8465 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8466 if (!skb) {
8467 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8468 return -ENOMEM;
8469 }
8470
8471 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8472 hdd_ctx->wmi_max_len)) {
8473 hdd_err("nla put failure");
8474 goto nla_put_failure;
8475 }
8476
8477 cfg80211_vendor_cmd_reply(skb);
8478
8479 EXIT();
8480
8481 return 0;
8482
8483nla_put_failure:
8484 kfree_skb(skb);
8485 return -EINVAL;
8486}
8487
8488/**
8489 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8490 * @wiphy: wiphy structure pointer
8491 * @wdev: Wireless device structure pointer
8492 * @data: Pointer to the data received
8493 * @data_len: Length of @data
8494 *
8495 * Return: 0 on success; errno on failure
8496 */
8497static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8498 struct wireless_dev *wdev,
8499 const void *data, int data_len)
8500{
8501 int ret;
8502
8503 cds_ssr_protect(__func__);
8504 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8505 cds_ssr_unprotect(__func__);
8506
8507 return ret;
8508}
8509
8510/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308511 *__wlan_hdd_cfg80211_setband() - set band
8512 * @wiphy: Pointer to wireless phy
8513 * @wdev: Pointer to wireless device
8514 * @data: Pointer to data
8515 * @data_len: Length of @data
8516 *
8517 * Return: 0 on success, negative errno on failure
8518 */
8519static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8520 struct wireless_dev *wdev,
8521 const void *data, int data_len)
8522{
8523 struct net_device *dev = wdev->netdev;
8524 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8525 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8526 int ret;
8527 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8528 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8529
8530 ENTER();
8531
8532 ret = wlan_hdd_validate_context(hdd_ctx);
8533 if (ret)
8534 return ret;
8535
8536 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8537 hdd_err(FL("Invalid ATTR"));
8538 return -EINVAL;
8539 }
8540
8541 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8542 hdd_err(FL("attr SETBAND_VALUE failed"));
8543 return -EINVAL;
8544 }
8545
8546 ret = hdd_set_band(dev,
8547 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8548
8549 EXIT();
8550 return ret;
8551}
8552
8553/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308554 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8555 * @adapter: hdd adapter
8556 * @channel: channel number
8557 *
8558 * return: QDF status based on success or failure
8559 */
8560static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8561 int channel, int chan_bw)
8562{
8563 if (QDF_STATUS_SUCCESS !=
8564 wlan_hdd_validate_operation_channel(adapter, channel))
8565 return QDF_STATUS_E_FAILURE;
8566 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8567 channel,
8568 PHY_SINGLE_CHANNEL_CENTERED))) {
8569 hdd_notice("channel %d is in nol", channel);
8570 return -EINVAL;
8571 }
8572
8573 if ((wlansap_is_channel_leaking_in_nol(
8574 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8575 channel, chan_bw))) {
8576 hdd_notice("channel %d is leaking in nol", channel);
8577 return -EINVAL;
8578 }
8579
8580 return 0;
8581
8582}
8583
Kapil Gupta8878ad92017-02-13 11:56:04 +05308584static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8585 tsap_Config_t *sap_config,
8586 struct hdd_vendor_chan_info *channel_list)
8587{
8588 sap_config->channel = channel_list->pri_ch;
8589
8590 sap_config->ch_params.center_freq_seg0 =
8591 channel_list->vht_seg0_center_ch;
8592 sap_config->ch_params.center_freq_seg1 =
8593 channel_list->vht_seg1_center_ch;
8594
8595 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8596 sap_config->ch_params.ch_width = channel_list->chan_width;
8597 if (sap_config->channel >= 36)
8598 sap_config->ch_width_orig =
8599 hdd_ctx->config->vhtChannelWidth;
8600 else
8601 sap_config->ch_width_orig =
8602 hdd_ctx->config->nChannelBondingMode24GHz ?
8603 eHT_CHANNEL_WIDTH_40MHZ :
8604 eHT_CHANNEL_WIDTH_20MHZ;
8605
8606 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8607 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8608 sap_config->acs_cfg.vht_seg0_center_ch =
8609 channel_list->vht_seg0_center_ch;
8610 sap_config->acs_cfg.vht_seg1_center_ch =
8611 channel_list->vht_seg1_center_ch;
8612 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8613}
8614
8615static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8616 uint8_t channel_cnt,
8617 struct hdd_vendor_chan_info *channel_list)
8618{
8619 tsap_Config_t *sap_config;
8620 hdd_ap_ctx_t *hdd_ap_ctx;
8621 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8622 QDF_STATUS status = QDF_STATUS_SUCCESS;
8623
8624 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8625 sap_config = &adapter->sessionCtx.ap.sapConfig;
8626
8627 if (QDF_TIMER_STATE_RUNNING ==
8628 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8629 ap.vendor_acs_timer)) {
8630 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8631 }
8632
8633 if (channel_list && channel_list->pri_ch == 0) {
8634 /* Check mode, set default channel */
8635 channel_list->pri_ch = 6;
8636 /*
8637 * sap_select_default_oper_chan(hdd_ctx->hHal,
8638 * sap_config->acs_cfg.hw_mode);
8639 */
8640 }
8641
8642 switch (reason) {
8643 /* SAP init case */
8644 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8645 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8646 /* Update Hostapd */
8647 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8648 break;
8649
8650 /* DFS detected on current channel */
8651 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8652 wlan_sap_update_next_channel(
8653 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8654 channel_list->pri_ch,
8655 channel_list->chan_width);
8656 status = sme_update_new_channel_event(
8657 WLAN_HDD_GET_HAL_CTX(adapter),
8658 adapter->sessionId);
8659 break;
8660
8661 /* LTE coex event on current channel */
8662 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8663 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8664 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8665 hdd_ap_ctx->sapConfig.ch_width_orig =
8666 channel_list->chan_width;
8667 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8668 break;
8669
8670 default:
8671 hdd_info("invalid reason for timer invoke");
8672 }
8673 qdf_mem_free(channel_list);
8674 EXIT();
8675 return status;
8676}
8677
8678/**
8679 * Define short name for vendor channel set config
8680 */
8681#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8682#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8683#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8684#define SET_CHAN_PRIMARY_CHANNEL \
8685 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8686#define SET_CHAN_SECONDARY_CHANNEL \
8687 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8688#define SET_CHAN_SEG0_CENTER_CHANNEL \
8689 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8690#define SET_CHAN_SEG1_CENTER_CHANNEL \
8691 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8692#define SET_CHAN_CHANNEL_WIDTH \
8693 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8694#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8695
8696/**
8697 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8698 * @channel_list: pointer to hdd_vendor_chan_info
8699 * @reason: channel change reason
8700 * @channel_cnt: channel count
8701 * @data: data
8702 * @data_len: data len
8703 *
8704 * Return: 0 on success, negative errno on failure
8705 */
8706static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8707 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8708 const void *data, int data_len)
8709{
8710 int rem, i = 0;
8711 struct nlattr *tb[SET_CHAN_MAX + 1];
8712 struct nlattr *tb2[SET_CHAN_MAX + 1];
8713 struct nlattr *curr_attr;
8714 struct hdd_vendor_chan_info *channel_list;
8715
8716 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8717 hdd_err("Invalid ATTR");
8718 return -EINVAL;
8719 }
8720
8721 if (tb[SET_CHAN_REASON])
8722 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8723
8724 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8725 *channel_cnt = nla_get_u8(tb[
8726 SET_CHAN_CHANNEL_COUNT]);
8727 hdd_info("channel count %d", *channel_cnt);
8728 }
8729
8730 if (!(*channel_cnt)) {
8731 hdd_err("channel count is %d", *channel_cnt);
8732 return -EINVAL;
8733 }
8734
8735 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8736 (*channel_cnt));
8737
8738 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8739 if (nla_parse(tb2,
8740 SET_CHAN_MAX,
8741 nla_data(curr_attr), nla_len(curr_attr),
8742 NULL)) {
8743 hdd_err("nla_parse failed");
8744 return -EINVAL;
8745 }
8746 /* Parse and Fetch allowed SSID list*/
8747 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8748 channel_list[i].pri_ch =
8749 nla_get_u8(
8750 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8751 }
8752 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8753 channel_list[i].ht_sec_ch =
8754 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8755 }
8756 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8757 channel_list[i].vht_seg0_center_ch =
8758 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8759 }
8760 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8761 channel_list[i].vht_seg1_center_ch =
8762 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8763 }
8764 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8765 channel_list[i].chan_width =
8766 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8767 }
8768 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8769 i, channel_list[i].pri_ch,
8770 channel_list[i].ht_sec_ch,
8771 channel_list[i].vht_seg0_center_ch,
8772 channel_list[i].vht_seg1_center_ch,
8773 channel_list[i].chan_width);
8774 i++;
8775 if (i > *channel_cnt)
8776 break;
8777 }
8778 *chan_list_ptr = channel_list;
8779
8780 return 0;
8781}
8782
8783/**
8784 * Undef short names for vendor set channel configuration
8785 */
8786#undef SET_CHAN_REASON
8787#undef SET_CHAN_CHANNEL_COUNT
8788#undef SET_CHAN_CHAN_LIST
8789#undef SET_CHAN_PRIMARY_CHANNEL
8790#undef SET_CHAN_SECONDARY_CHANNEL
8791#undef SET_CHAN_SEG0_CENTER_CHANNEL
8792#undef SET_CHAN_SEG1_CENTER_CHANNEL
8793#undef SET_CHAN_CHANNEL_WIDTH
8794#undef SET_CHAN_MAX
8795
8796/**
8797 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8798 * @wiphy: Pointer to wireless phy
8799 * @wdev: Pointer to wireless device
8800 * @data: Pointer to data
8801 * @data_len: Length of @data
8802 *
8803 * Return: 0 on success, negative errno on failure
8804 */
8805static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8806 struct wireless_dev *wdev,
8807 const void *data, int data_len)
8808{
8809 int ret_val;
8810 QDF_STATUS qdf_status;
8811 uint8_t channel_cnt = 0, reason = -1;
8812 struct hdd_vendor_chan_info *channel_list = NULL;
8813 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8814 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8815
8816 ENTER();
8817
8818 ret_val = wlan_hdd_validate_context(hdd_ctx);
8819 if (ret_val)
8820 return ret_val;
8821
8822 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8823 hdd_err("Command not allowed in FTM mode");
8824 return -EINVAL;
8825 }
8826
8827 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8828 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8829 else {
8830 hdd_err("already timeout happened for acs");
8831 return -EINVAL;
8832 }
8833
8834 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8835 &channel_cnt, data, data_len);
8836 if (ret_val)
8837 return ret_val;
8838
8839 /* Validate channel to be set */
8840 while (channel_cnt && channel_list) {
8841 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8842 channel_list->pri_ch,
8843 channel_list->chan_width);
8844 if (qdf_status == QDF_STATUS_SUCCESS)
8845 break;
8846 channel_cnt--;
8847 channel_list++;
8848 }
8849 if ((channel_cnt <= 0) || !channel_list) {
8850 hdd_err("no available channel/chanlist %p", channel_list);
8851 return -EINVAL;
8852 }
8853
8854 qdf_status = hdd_update_acs_channel(adapter, reason,
8855 channel_cnt, channel_list);
8856 return qdf_status_to_os_return(qdf_status);
8857}
8858
8859/**
8860 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8861 * @wiphy: Pointer to wireless phy
8862 * @wdev: Pointer to wireless device
8863 * @data: Pointer to data
8864 * @data_len: Length of @data
8865 *
8866 * Return: 0 on success, negative errno on failure
8867 */
8868static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8869 struct wireless_dev *wdev,
8870 const void *data, int data_len)
8871{
8872 int ret;
8873
8874 cds_ssr_protect(__func__);
8875 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8876 data_len);
8877 cds_ssr_protect(__func__);
8878
8879 return ret;
8880}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308881
8882/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308883 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8884 * @wiphy: wiphy structure pointer
8885 * @wdev: Wireless device structure pointer
8886 * @data: Pointer to the data received
8887 * @data_len: Length of @data
8888 *
8889 * Return: 0 on success; errno on failure
8890 */
8891static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8892 struct wireless_dev *wdev,
8893 const void *data, int data_len)
8894{
8895 int ret;
8896
8897 cds_ssr_protect(__func__);
8898 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8899 cds_ssr_unprotect(__func__);
8900
8901 return ret;
8902}
8903
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008904/**
8905 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8906 * @nl80211_value: Vendor command attribute value
8907 * @wmi_value: Pointer to return converted WMI return value
8908 *
8909 * Convert NL80211 vendor command value for SAR limit set to WMI value
8910 * Return: 0 on success, -1 on invalid value
8911 */
8912static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8913 u32 *wmi_value)
8914{
8915 int ret = 0;
8916
8917 switch (nl80211_value) {
8918 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8919 *wmi_value = WMI_SAR_FEATURE_OFF;
8920 break;
8921 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8922 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8923 break;
8924 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8925 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8926 break;
8927 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8928 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8929 break;
8930 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8931 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8932 break;
8933 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8934 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8935 break;
8936 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8937 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8938 break;
8939 default:
8940 ret = -1;
8941 }
8942 return ret;
8943}
8944
8945/**
8946 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8947 * @nl80211_value: Vendor command attribute value
8948 * @wmi_value: Pointer to return converted WMI return value
8949 *
8950 * Convert NL80211 vendor command value for SAR BAND to WMI value
8951 * Return: 0 on success, -1 on invalid value
8952 */
8953static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8954{
8955 int ret = 0;
8956
8957 switch (nl80211_value) {
8958 case NL80211_BAND_2GHZ:
8959 *wmi_value = WMI_SAR_2G_ID;
8960 break;
8961 case NL80211_BAND_5GHZ:
8962 *wmi_value = WMI_SAR_5G_ID;
8963 break;
8964 default:
8965 ret = -1;
8966 }
8967 return ret;
8968}
8969
8970/**
8971 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8972 * @nl80211_value: Vendor command attribute value
8973 * @wmi_value: Pointer to return converted WMI return value
8974 *
8975 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8976 * Return: 0 on success, -1 on invalid value
8977 */
8978static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8979 u32 *wmi_value)
8980{
8981 int ret = 0;
8982
8983 switch (nl80211_value) {
8984 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8985 *wmi_value = WMI_SAR_MOD_CCK;
8986 break;
8987 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8988 *wmi_value = WMI_SAR_MOD_OFDM;
8989 break;
8990 default:
8991 ret = -1;
8992 }
8993 return ret;
8994}
8995
8996
8997/**
8998 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8999 * @wiphy: Pointer to wireless phy
9000 * @wdev: Pointer to wireless device
9001 * @data: Pointer to data
9002 * @data_len: Length of @data
9003 *
9004 * This function is used to setup Specific Absorption Rate limit specs.
9005 *
9006 * Return: 0 on success, negative errno on failure
9007 */
9008static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9009 struct wireless_dev *wdev,
9010 const void *data, int data_len)
9011{
9012 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9013 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9014 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9015 *sar_spec_list;
9016 struct sar_limit_cmd_params sar_limit_cmd = {0};
9017 int ret = -EINVAL, i = 0, rem = 0;
9018
9019 ENTER();
9020
9021 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9022 hdd_err("Command not allowed in FTM mode");
9023 return -EPERM;
9024 }
9025
9026 if (wlan_hdd_validate_context(hdd_ctx))
9027 return -EINVAL;
9028
9029 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9030 data, data_len, NULL)) {
9031 hdd_err("Invalid SAR attributes");
9032 return -EINVAL;
9033 }
9034
9035 /* Vendor command manadates all SAR Specs in single call */
9036 sar_limit_cmd.commit_limits = 1;
9037 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9038 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9039 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9040 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9041 &sar_limit_cmd.sar_enable) < 0) {
9042 hdd_err("Invalid SAR Enable attr");
9043 goto fail;
9044 }
9045 }
9046 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9047
9048 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9049 sar_limit_cmd.num_limit_rows = nla_get_u32(
9050 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9051 hdd_info("attr sar num_limit_rows %d",
9052 sar_limit_cmd.num_limit_rows);
9053 }
9054 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9055 hdd_err("SAR Spec list exceed supported size");
9056 goto fail;
9057 }
9058 if (sar_limit_cmd.num_limit_rows == 0)
9059 goto send_sar_limits;
9060 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9061 struct sar_limit_cmd_row) *
9062 sar_limit_cmd.num_limit_rows);
9063 if (!sar_limit_cmd.sar_limit_row_list) {
9064 ret = -ENOMEM;
9065 goto fail;
9066 }
9067 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9068 hdd_err("Invalid SAR SPECs list");
9069 goto fail;
9070 }
9071
9072 nla_for_each_nested(sar_spec_list,
9073 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9074 if (i == sar_limit_cmd.num_limit_rows) {
9075 hdd_warn("SAR Cmd has excess SPECs in list");
9076 break;
9077 }
9078
9079 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9080 nla_data(sar_spec_list), nla_len(sar_spec_list),
9081 NULL)) {
9082 hdd_err("nla_parse failed for SAR Spec list");
9083 goto fail;
9084 }
9085 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9086 if (sar_spec[
9087 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9088 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9089 nla_get_u32(sar_spec[
9090 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9091 } else {
9092 hdd_err("SAR Spec does not have power limit value");
9093 goto fail;
9094 }
9095
9096 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9097 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9098 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9099 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9100 < 0) {
9101 hdd_err("Invalid SAR Band attr");
9102 goto fail;
9103 }
9104 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9105 WMI_SAR_BAND_ID_VALID_MASK;
9106 }
9107 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9108 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9109 nla_get_u32(sar_spec[
9110 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9111 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9112 WMI_SAR_CHAIN_ID_VALID_MASK;
9113 }
9114 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9115 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9116 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9117 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9118 < 0) {
9119 hdd_err("Invalid SAR Modulation attr");
9120 goto fail;
9121 }
9122 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9123 WMI_SAR_MOD_ID_VALID_MASK;
9124 }
9125 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9126 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9127 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9128 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9129 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9130 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9131 i++;
9132 }
9133
9134 if (i < sar_limit_cmd.num_limit_rows) {
9135 hdd_warn("SAR Cmd has less SPECs in list");
9136 sar_limit_cmd.num_limit_rows = i;
9137 }
9138
9139send_sar_limits:
9140 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9141 QDF_STATUS_SUCCESS)
9142 ret = 0;
9143fail:
9144 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9145 return ret;
9146}
9147
9148/**
9149 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9150 * @wiphy: Pointer to wireless phy
9151 * @wdev: Pointer to wireless device
9152 * @data: Pointer to data
9153 * @data_len: Length of @data
9154 *
9155 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9156 *
9157 * Return: 0 on success, negative errno on failure
9158 */
9159static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9160 struct wireless_dev *wdev,
9161 const void *data,
9162 int data_len)
9163{
9164 int ret;
9165
9166 cds_ssr_protect(__func__);
9167 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9168 data_len);
9169 cds_ssr_unprotect(__func__);
9170
9171 return ret;
9172}
9173
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309174static const struct
9175nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9176 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9177 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9178 .len = QDF_MAC_ADDR_SIZE},
9179};
9180
9181/**
9182 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9183 * @wiphy: Pointer to wireless phy
9184 * @wdev: Pointer to wireless device
9185 * @data: Pointer to data
9186 * @data_len: Length of @data
9187 *
9188 * This function is used to enable/disable roaming using vendor commands
9189 *
9190 * Return: 0 on success, negative errno on failure
9191 */
9192static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9193 struct wireless_dev *wdev,
9194 const void *data, int data_len)
9195{
9196 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9197 struct net_device *dev = wdev->netdev;
9198 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9199 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9200 uint32_t is_fast_roam_enabled;
9201 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309202 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309203
9204 ENTER_DEV(dev);
9205
9206 ret = wlan_hdd_validate_context(hdd_ctx);
9207 if (0 != ret)
9208 return ret;
9209
9210 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9211 hdd_err("Command not allowed in FTM mode");
9212 return -EINVAL;
9213 }
9214
9215 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9216 qca_wlan_vendor_attr);
9217 if (ret) {
9218 hdd_err("Invalid ATTR");
9219 return -EINVAL;
9220 }
9221
9222 /* Parse and fetch Enable flag */
9223 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9224 hdd_err("attr enable failed");
9225 return -EINVAL;
9226 }
9227
9228 is_fast_roam_enabled = nla_get_u32(
9229 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009230 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9231 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309232
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009233 if (!adapter->fast_roaming_allowed) {
9234 hdd_err("fast roaming not allowed on %s interface",
9235 adapter->dev->name);
9236 return -EINVAL;
9237 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309238 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309239 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009240 (is_fast_roam_enabled &&
9241 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309242 if (qdf_status != QDF_STATUS_SUCCESS)
9243 hdd_err("sme_config_fast_roaming failed with status=%d",
9244 qdf_status);
9245 ret = qdf_status_to_os_return(qdf_status);
9246
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309247 EXIT();
9248 return ret;
9249}
9250
9251/**
9252 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9253 * @wiphy: Pointer to wireless phy
9254 * @wdev: Pointer to wireless device
9255 * @data: Pointer to data
9256 * @data_len: Length of @data
9257 *
9258 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9259 *
9260 * Return: 0 on success, negative errno on failure
9261 */
9262static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9263 struct wireless_dev *wdev,
9264 const void *data, int data_len)
9265{
9266 int ret;
9267
9268 cds_ssr_protect(__func__);
9269 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9270 cds_ssr_unprotect(__func__);
9271
9272 return ret;
9273}
9274
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309275static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9276 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9277 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9278 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9279 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9280};
9281
9282/**
9283 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9284 * @wiphy: Pointer to wireless phy
9285 * @wdev: Pointer to wireless device
9286 * @data: Pointer to data
9287 * @data_len: Length of @data
9288 *
9289 * Return: 0 on success, negative errno on failure
9290 */
9291static int
9292__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9293 struct wireless_dev *wdev,
9294 const void *data,
9295 int data_len)
9296{
9297 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9298 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9299 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9300 struct nlattr *apth;
9301 int rem;
9302 int ret = 1;
9303 int print_idx = -1;
9304 int module_id = -1;
9305 int bit_mask = -1;
9306 int status;
9307
9308 ENTER();
9309
9310 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9311 hdd_err("Command not allowed in FTM mode");
9312 return -EINVAL;
9313 }
9314
9315 ret = wlan_hdd_validate_context(hdd_ctx);
9316 if (ret != 0)
9317 return -EINVAL;
9318
9319 print_idx = qdf_get_pidx();
9320 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9321 hdd_err("Invalid print controle object index");
9322 return -EINVAL;
9323 }
9324
9325 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9326 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9327 hdd_err("Invalid attr");
9328 return -EINVAL;
9329 }
9330
9331 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9332 hdd_err("attr trace level param failed");
9333 return -EINVAL;
9334 }
9335
9336 nla_for_each_nested(apth,
9337 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9338 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9339 nla_data(apth), nla_len(apth), NULL)) {
9340 hdd_err("Invalid attr");
9341 return -EINVAL;
9342 }
9343
9344 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9345 hdd_err("attr Module ID failed");
9346 return -EINVAL;
9347 }
9348 module_id = nla_get_u32
9349 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9350
9351 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9352 hdd_err("attr Verbose mask failed");
9353 return -EINVAL;
9354 }
9355 bit_mask = nla_get_u32
9356 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9357
9358 status = hdd_qdf_trace_enable(module_id, bit_mask);
9359
9360 if (status != 0)
9361 hdd_err("can not set verbose mask %d for the category %d",
9362 bit_mask, module_id);
9363 }
9364
9365 EXIT();
9366 return ret;
9367}
9368
9369/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309370 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9371 * @wiphy: Pointer to wireless phy
9372 * @wdev: Pointer to wireless device
9373 * @data: Pointer to data
9374 * @data_len: Length of @data
9375 *
9376 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9377 *
9378 * Return: 0 on success, negative errno on failure
9379 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309380
9381static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9382 struct wireless_dev *wdev,
9383 const void *data,
9384 int data_len)
9385{
9386 int ret;
9387
9388 cds_ssr_protect(__func__);
9389 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9390 cds_ssr_unprotect(__func__);
9391
9392 return ret;
9393}
9394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009395const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9396 {
9397 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9398 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9399 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309400 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009401 .doit = is_driver_dfs_capable
9402 },
9403
9404#ifdef WLAN_FEATURE_NAN
9405 {
9406 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9407 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9408 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9409 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9410 .doit = wlan_hdd_cfg80211_nan_request
9411 },
9412#endif
9413
9414#ifdef WLAN_FEATURE_STATS_EXT
9415 {
9416 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9417 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9418 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9419 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9420 .doit = wlan_hdd_cfg80211_stats_ext_request
9421 },
9422#endif
9423#ifdef FEATURE_WLAN_EXTSCAN
9424 {
9425 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9426 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9427 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9428 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9429 .doit = wlan_hdd_cfg80211_extscan_start
9430 },
9431 {
9432 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9433 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9434 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9435 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9436 .doit = wlan_hdd_cfg80211_extscan_stop
9437 },
9438 {
9439 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9440 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9441 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9442 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9443 },
9444 {
9445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9448 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9449 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9450 },
9451 {
9452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9455 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9456 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9457 },
9458 {
9459 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9460 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9461 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9462 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9463 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9464 },
9465 {
9466 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9467 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9468 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9469 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9470 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9471 },
9472 {
9473 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9474 .info.subcmd =
9475 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9476 .flags =
9477 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9478 WIPHY_VENDOR_CMD_NEED_RUNNING,
9479 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9480 },
9481 {
9482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9483 .info.subcmd =
9484 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9485 .flags =
9486 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9487 WIPHY_VENDOR_CMD_NEED_RUNNING,
9488 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9489 },
9490 {
9491 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9492 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9493 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9494 WIPHY_VENDOR_CMD_NEED_NETDEV |
9495 WIPHY_VENDOR_CMD_NEED_RUNNING,
9496 .doit = wlan_hdd_cfg80211_set_epno_list
9497 },
9498#endif /* FEATURE_WLAN_EXTSCAN */
9499
9500#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9501 {
9502 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9503 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9504 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9505 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9506 .doit = wlan_hdd_cfg80211_ll_stats_clear
9507 },
9508
9509 {
9510 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9511 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9512 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9513 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9514 .doit = wlan_hdd_cfg80211_ll_stats_set
9515 },
9516
9517 {
9518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9519 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9520 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9521 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9522 .doit = wlan_hdd_cfg80211_ll_stats_get
9523 },
9524#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9525#ifdef FEATURE_WLAN_TDLS
9526 {
9527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9528 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9529 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9530 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9531 .doit = wlan_hdd_cfg80211_exttdls_enable
9532 },
9533 {
9534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9537 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9538 .doit = wlan_hdd_cfg80211_exttdls_disable
9539 },
9540 {
9541 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9542 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9543 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9544 .doit = wlan_hdd_cfg80211_exttdls_get_status
9545 },
9546#endif
9547 {
9548 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9549 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9550 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9551 .doit = wlan_hdd_cfg80211_get_supported_features
9552 },
9553 {
9554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9555 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9556 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9557 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9558 },
9559 {
9560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309563 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009564 },
9565 {
9566 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9567 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9568 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9569 WIPHY_VENDOR_CMD_NEED_NETDEV,
9570 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9571 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009572 {
9573 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9574 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9575 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9576 WIPHY_VENDOR_CMD_NEED_NETDEV,
9577 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9578 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009579 {
9580 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309581 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9582 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9583 WIPHY_VENDOR_CMD_NEED_NETDEV |
9584 WIPHY_VENDOR_CMD_NEED_RUNNING,
9585 .doit = hdd_cfg80211_get_station_cmd
9586 },
9587 {
9588 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009589 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9590 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9591 WIPHY_VENDOR_CMD_NEED_NETDEV |
9592 WIPHY_VENDOR_CMD_NEED_RUNNING,
9593 .doit = wlan_hdd_cfg80211_do_acs
9594 },
9595
9596 {
9597 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9598 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9599 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9600 WIPHY_VENDOR_CMD_NEED_NETDEV,
9601 .doit = wlan_hdd_cfg80211_get_features
9602 },
9603#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9604 {
9605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9608 WIPHY_VENDOR_CMD_NEED_NETDEV |
9609 WIPHY_VENDOR_CMD_NEED_RUNNING,
9610 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9611 },
9612#endif
9613#ifdef FEATURE_WLAN_EXTSCAN
9614 {
9615 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9616 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9617 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9618 WIPHY_VENDOR_CMD_NEED_NETDEV |
9619 WIPHY_VENDOR_CMD_NEED_RUNNING,
9620 .doit = wlan_hdd_cfg80211_set_passpoint_list
9621 },
9622 {
9623 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9624 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9625 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9626 WIPHY_VENDOR_CMD_NEED_NETDEV |
9627 WIPHY_VENDOR_CMD_NEED_RUNNING,
9628 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9629 },
9630 {
9631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9632 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9633 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9634 WIPHY_VENDOR_CMD_NEED_NETDEV |
9635 WIPHY_VENDOR_CMD_NEED_RUNNING,
9636 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9637 },
9638 {
9639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9642 WIPHY_VENDOR_CMD_NEED_NETDEV |
9643 WIPHY_VENDOR_CMD_NEED_RUNNING,
9644 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9645 },
9646#endif /* FEATURE_WLAN_EXTSCAN */
9647 {
9648 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9649 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9650 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9651 WIPHY_VENDOR_CMD_NEED_NETDEV,
9652 .doit = wlan_hdd_cfg80211_get_wifi_info
9653 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009654#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009655 {
9656 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9657 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9658 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9659 WIPHY_VENDOR_CMD_NEED_NETDEV |
9660 WIPHY_VENDOR_CMD_NEED_RUNNING,
9661 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9662 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009663#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009664 {
9665 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9666 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9667 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9668 WIPHY_VENDOR_CMD_NEED_NETDEV,
9669 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9670 },
9671 {
9672 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9673 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9674 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9675 WIPHY_VENDOR_CMD_NEED_NETDEV,
9676 .doit = wlan_hdd_cfg80211_wifi_logger_start
9677 },
9678 {
9679 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9680 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9681 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9682 WIPHY_VENDOR_CMD_NEED_NETDEV,
9683 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9684 },
9685 {
9686 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9687 .info.subcmd =
9688 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9689 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9690 WIPHY_VENDOR_CMD_NEED_NETDEV |
9691 WIPHY_VENDOR_CMD_NEED_RUNNING,
9692 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9693 },
9694 {
9695 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9696 .info.subcmd =
9697 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9698 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9699 WIPHY_VENDOR_CMD_NEED_NETDEV |
9700 WIPHY_VENDOR_CMD_NEED_RUNNING,
9701 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9702 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009703#ifdef WLAN_FEATURE_TSF
9704 {
9705 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9706 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9707 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9708 WIPHY_VENDOR_CMD_NEED_NETDEV |
9709 WIPHY_VENDOR_CMD_NEED_RUNNING,
9710 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9711 },
9712#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009713#ifdef FEATURE_WLAN_TDLS
9714 {
9715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9716 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9717 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9718 WIPHY_VENDOR_CMD_NEED_NETDEV |
9719 WIPHY_VENDOR_CMD_NEED_RUNNING,
9720 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9721 },
9722#endif
9723#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9724 {
9725 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9726 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9727 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9728 WIPHY_VENDOR_CMD_NEED_NETDEV |
9729 WIPHY_VENDOR_CMD_NEED_RUNNING,
9730 .doit = wlan_hdd_cfg80211_offloaded_packets
9731 },
9732#endif
9733 {
9734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9737 WIPHY_VENDOR_CMD_NEED_NETDEV |
9738 WIPHY_VENDOR_CMD_NEED_RUNNING,
9739 .doit = wlan_hdd_cfg80211_monitor_rssi
9740 },
9741 {
9742 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309743 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9744 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9745 WIPHY_VENDOR_CMD_NEED_NETDEV |
9746 WIPHY_VENDOR_CMD_NEED_RUNNING,
9747 .doit = wlan_hdd_cfg80211_set_ns_offload
9748 },
9749 {
9750 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009751 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9752 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9753 WIPHY_VENDOR_CMD_NEED_NETDEV |
9754 WIPHY_VENDOR_CMD_NEED_RUNNING,
9755 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9756 },
9757#ifdef WLAN_FEATURE_MEMDUMP
9758 {
9759 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9760 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9761 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9762 WIPHY_VENDOR_CMD_NEED_NETDEV |
9763 WIPHY_VENDOR_CMD_NEED_RUNNING,
9764 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9765 },
9766#endif /* WLAN_FEATURE_MEMDUMP */
9767 {
9768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9769 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9770 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9771 WIPHY_VENDOR_CMD_NEED_NETDEV |
9772 WIPHY_VENDOR_CMD_NEED_RUNNING,
9773 .doit = wlan_hdd_cfg80211_vendor_scan
9774 },
9775
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309776 /* Vendor abort scan */
9777 {
9778 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9779 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9780 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9781 WIPHY_VENDOR_CMD_NEED_NETDEV |
9782 WIPHY_VENDOR_CMD_NEED_RUNNING,
9783 .doit = wlan_hdd_vendor_abort_scan
9784 },
9785
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009786 /* OCB commands */
9787 {
9788 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9789 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9791 WIPHY_VENDOR_CMD_NEED_NETDEV |
9792 WIPHY_VENDOR_CMD_NEED_RUNNING,
9793 .doit = wlan_hdd_cfg80211_ocb_set_config
9794 },
9795 {
9796 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9797 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9798 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9799 WIPHY_VENDOR_CMD_NEED_NETDEV |
9800 WIPHY_VENDOR_CMD_NEED_RUNNING,
9801 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9802 },
9803 {
9804 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9805 .info.subcmd =
9806 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9807 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9808 WIPHY_VENDOR_CMD_NEED_NETDEV |
9809 WIPHY_VENDOR_CMD_NEED_RUNNING,
9810 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9811 },
9812 {
9813 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9814 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9815 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9816 WIPHY_VENDOR_CMD_NEED_NETDEV |
9817 WIPHY_VENDOR_CMD_NEED_RUNNING,
9818 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9819 },
9820 {
9821 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9822 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9823 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9824 WIPHY_VENDOR_CMD_NEED_NETDEV |
9825 WIPHY_VENDOR_CMD_NEED_RUNNING,
9826 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9827 },
9828 {
9829 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9830 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9831 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9832 WIPHY_VENDOR_CMD_NEED_NETDEV |
9833 WIPHY_VENDOR_CMD_NEED_RUNNING,
9834 .doit = wlan_hdd_cfg80211_dcc_get_stats
9835 },
9836 {
9837 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9838 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9839 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9840 WIPHY_VENDOR_CMD_NEED_NETDEV |
9841 WIPHY_VENDOR_CMD_NEED_RUNNING,
9842 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9843 },
9844 {
9845 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9846 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9847 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9848 WIPHY_VENDOR_CMD_NEED_NETDEV |
9849 WIPHY_VENDOR_CMD_NEED_RUNNING,
9850 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9851 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309852 {
9853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9856 WIPHY_VENDOR_CMD_NEED_NETDEV |
9857 WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_get_link_properties
9859 },
Peng Xu278d0122015-09-24 16:34:17 -07009860 {
Peng Xud2220962016-07-11 17:59:17 -07009861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9864 WIPHY_VENDOR_CMD_NEED_NETDEV |
9865 WIPHY_VENDOR_CMD_NEED_RUNNING,
9866 .doit = wlan_hdd_cfg80211_set_ota_test
9867 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009868#ifdef FEATURE_LFR_SUBNET_DETECTION
9869 {
9870 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9871 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9872 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9873 WIPHY_VENDOR_CMD_NEED_NETDEV |
9874 WIPHY_VENDOR_CMD_NEED_RUNNING,
9875 .doit = wlan_hdd_cfg80211_set_gateway_params
9876 },
9877#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009878 {
Peng Xud2220962016-07-11 17:59:17 -07009879 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009880 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9881 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9882 WIPHY_VENDOR_CMD_NEED_NETDEV |
9883 WIPHY_VENDOR_CMD_NEED_RUNNING,
9884 .doit = wlan_hdd_cfg80211_txpower_scale
9885 },
9886 {
9887 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9888 .info.subcmd =
9889 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9890 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9891 WIPHY_VENDOR_CMD_NEED_NETDEV |
9892 WIPHY_VENDOR_CMD_NEED_RUNNING,
9893 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9894 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309895 {
9896 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9897 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9898 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9899 WIPHY_VENDOR_CMD_NEED_NETDEV |
9900 WIPHY_VENDOR_CMD_NEED_RUNNING,
9901 .doit = wlan_hdd_cfg80211_bpf_offload
9902 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309903 {
9904 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309905 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9907 WIPHY_VENDOR_CMD_NEED_NETDEV |
9908 WIPHY_VENDOR_CMD_NEED_RUNNING,
9909 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9910 },
9911 {
9912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_sta_roam_policy
9918 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309919#ifdef FEATURE_WLAN_CH_AVOID
9920 {
9921 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9922 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9923 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9924 WIPHY_VENDOR_CMD_NEED_NETDEV |
9925 WIPHY_VENDOR_CMD_NEED_RUNNING,
9926 .doit = wlan_hdd_cfg80211_avoid_freq
9927 },
9928#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309929 {
9930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309931 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9933 WIPHY_VENDOR_CMD_NEED_NETDEV |
9934 WIPHY_VENDOR_CMD_NEED_RUNNING,
9935 .doit = wlan_hdd_cfg80211_sap_configuration_set
9936 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009937 {
Peng Xu4225c152016-07-14 21:18:14 -07009938 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009939 .info.subcmd =
9940 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9942 WIPHY_VENDOR_CMD_NEED_NETDEV |
9943 WIPHY_VENDOR_CMD_NEED_RUNNING,
9944 .doit = wlan_hdd_cfg80211_p2p_lo_start
9945 },
9946 {
9947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9948 .info.subcmd =
9949 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9951 WIPHY_VENDOR_CMD_NEED_NETDEV |
9952 WIPHY_VENDOR_CMD_NEED_RUNNING,
9953 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9954 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309955 {
9956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9957 .info.subcmd =
9958 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9960 WIPHY_VENDOR_CMD_NEED_NETDEV |
9961 WIPHY_VENDOR_CMD_NEED_RUNNING,
9962 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9963 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009964#ifdef WLAN_FEATURE_NAN_DATAPATH
9965 {
9966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9967 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9969 WIPHY_VENDOR_CMD_NEED_NETDEV |
9970 WIPHY_VENDOR_CMD_NEED_RUNNING,
9971 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9972 },
9973#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309974 {
9975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9976 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9977 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9978 WIPHY_VENDOR_CMD_NEED_NETDEV |
9979 WIPHY_VENDOR_CMD_NEED_RUNNING,
9980 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9981 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309982 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309983 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9984 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9985 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9986 WIPHY_VENDOR_CMD_NEED_NETDEV |
9987 WIPHY_VENDOR_CMD_NEED_RUNNING,
9988 .doit = wlan_hdd_cfg80211_get_bus_size
9989 },
9990 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309991 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9992 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
9993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9994 WIPHY_VENDOR_CMD_NEED_NETDEV |
9995 WIPHY_VENDOR_CMD_NEED_RUNNING,
9996 .doit = wlan_hdd_cfg80211_update_vendor_channel
9997 },
9998 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309999 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10000 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10001 WIPHY_VENDOR_CMD_NEED_NETDEV |
10002 WIPHY_VENDOR_CMD_NEED_RUNNING,
10003 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010004 },
10005 {
10006 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10007 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10008 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10009 WIPHY_VENDOR_CMD_NEED_NETDEV |
10010 WIPHY_VENDOR_CMD_NEED_RUNNING,
10011 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010012 },
10013#ifdef WLAN_FEATURE_DISA
10014 {
10015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10016 .info.subcmd =
10017 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10019 WIPHY_VENDOR_CMD_NEED_NETDEV |
10020 WIPHY_VENDOR_CMD_NEED_RUNNING,
10021 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10022 },
10023#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010024#ifdef FEATURE_WLAN_TDLS
10025 {
10026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10027 .info.subcmd =
10028 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10029 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10030 WIPHY_VENDOR_CMD_NEED_NETDEV |
10031 WIPHY_VENDOR_CMD_NEED_RUNNING,
10032 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010033 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010034#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010035 {
10036 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10037 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10039 WIPHY_VENDOR_CMD_NEED_RUNNING,
10040 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10041 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010042 {
10043 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10044 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10045 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10046 WIPHY_VENDOR_CMD_NEED_NETDEV |
10047 WIPHY_VENDOR_CMD_NEED_RUNNING,
10048 .doit = wlan_hdd_cfg80211_set_trace_level
10049 },
10050
Paul Zhang3a210c52016-12-08 10:18:12 +080010051#ifdef WLAN_UMAC_CONVERGENCE
10052 COMMON_VENDOR_COMMANDS
10053#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010054};
10055
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010056#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10057 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10058 defined(FEATURE_WLAN_SCAN_PNO)
10059/**
10060 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10061 * @wiphy: pointer to wiphy
10062 * @config: pointer to config
10063 *
10064 * Return: None
10065 */
10066static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10067 struct hdd_config *config)
10068{
10069 if (config->configPNOScanSupport) {
10070 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10071 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10072 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10073 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10074 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10075 if (config->max_sched_scan_plan_interval)
10076 wiphy->max_sched_scan_plan_interval =
10077 config->max_sched_scan_plan_interval;
10078 if (config->max_sched_scan_plan_iterations)
10079 wiphy->max_sched_scan_plan_iterations =
10080 config->max_sched_scan_plan_iterations;
10081 }
10082}
10083#else
10084static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10085 struct hdd_config *config)
10086{
10087}
10088#endif
10089
10090
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010091/**
10092 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10093 * @priv_size: Size of the hdd context.
10094 *
10095 * Allocate wiphy context and hdd context.
10096 *
10097 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010098 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010099hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010100{
10101 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010102 hdd_context_t *hdd_ctx;
10103
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010104 ENTER();
10105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010106 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10107
10108 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010109 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010110 return NULL;
10111 }
10112
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010113 hdd_ctx = wiphy_priv(wiphy);
10114
10115 hdd_ctx->wiphy = wiphy;
10116
10117 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118}
10119
10120/*
10121 * FUNCTION: wlan_hdd_cfg80211_update_band
10122 * This function is called from the supplicant through a
10123 * private ioctl to change the band value
10124 */
10125int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10126{
10127 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010128 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129
10130 ENTER();
10131
Dustin Browna30892e2016-10-12 17:28:36 -070010132 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010133
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010134 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136
10137 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10138 struct ieee80211_supported_band *band = wiphy->bands[i];
10139
10140 channelEnabledState =
10141 cds_get_channel_state(band->channels[j].
10142 hw_value);
10143
Dustin Browna30892e2016-10-12 17:28:36 -070010144 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010145 /* 5G only */
10146#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10147 /* Enable Social channels for P2P */
10148 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10149 (band->channels[j].center_freq)
10150 && CHANNEL_STATE_ENABLE ==
10151 channelEnabledState)
10152 band->channels[j].flags &=
10153 ~IEEE80211_CHAN_DISABLED;
10154 else
10155#endif
10156 band->channels[j].flags |=
10157 IEEE80211_CHAN_DISABLED;
10158 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010159 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010160 eCSR_BAND_24 == eBand) {
10161 /* 2G only */
10162 band->channels[j].flags |=
10163 IEEE80211_CHAN_DISABLED;
10164 continue;
10165 }
10166
Amar Singhal6842e8f2016-02-23 16:30:32 -080010167 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010168 band->channels[j].flags &=
10169 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170 }
10171 }
10172 return 0;
10173}
10174
Peng Xuacfdda12017-02-06 16:15:38 -080010175#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176/*
10177 * FUNCTION: wlan_hdd_cfg80211_init
10178 * This function is called by hdd_wlan_startup()
10179 * during initialization.
10180 * This function is used to initialize and register wiphy structure.
10181 */
10182int wlan_hdd_cfg80211_init(struct device *dev,
10183 struct wiphy *wiphy, struct hdd_config *pCfg)
10184{
10185 int i, j;
10186 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10187
10188 ENTER();
10189
10190 /* Now bind the underlying wlan device with wiphy */
10191 set_wiphy_dev(wiphy, dev);
10192
10193 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010195#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10196 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010197 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198#else
10199 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010200 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201#endif
10202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10204 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10205 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10206#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10207 | WIPHY_FLAG_4ADDR_STATION
10208#endif
10209 | WIPHY_FLAG_OFFCHAN_TX;
10210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010211#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10212 wiphy->wowlan = &wowlan_support_cfg80211_init;
10213#else
10214 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10215 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10216 wiphy->wowlan.pattern_min_len = 1;
10217 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10218#endif
10219
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010220 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221#ifdef FEATURE_WLAN_ESE
10222 || pCfg->isEseIniFeatureEnabled
10223#endif
10224 ) {
10225 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10226 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010227#ifdef FEATURE_WLAN_TDLS
10228 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10229 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10230#endif
10231
10232 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10233
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010234#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10235 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10236#endif
10237
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010238 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010239
10240#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010241 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010242#endif
10243
10244 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010245 * driver can still register regulatory callback and
10246 * it will get regulatory settings in wiphy->band[], but
10247 * driver need to determine what to do with both
10248 * regulatory settings
10249 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250
10251 wiphy->reg_notifier = hdd_reg_notifier;
10252
10253#if defined QCA_WIFI_FTM
10254}
10255#endif
10256
10257 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10258
10259 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10260
10261 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10262
Arun Khandavallifae92942016-08-01 13:31:08 +053010263 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10264 | BIT(NL80211_IFTYPE_ADHOC)
10265 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10266 | BIT(NL80211_IFTYPE_P2P_GO)
10267 | BIT(NL80211_IFTYPE_AP)
10268 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010269
Arun Khandavallifae92942016-08-01 13:31:08 +053010270 if (pCfg->advertiseConcurrentOperation) {
10271 if (pCfg->enableMCC) {
10272 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010273
Arun Khandavallifae92942016-08-01 13:31:08 +053010274 for (i = 0;
10275 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10276 i++) {
10277 if (!pCfg->allowMCCGODiffBI)
10278 wlan_hdd_iface_combination[i].
10279 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010280 }
10281 }
10282 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010283 ARRAY_SIZE(wlan_hdd_iface_combination);
10284 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285 }
10286
10287 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010288 * on ini values
10289 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290 if (!pCfg->ShortGI20MhzEnable) {
10291 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10292 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 }
10294
10295 if (!pCfg->ShortGI40MhzEnable) {
10296 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10297 }
10298
10299 if (!pCfg->nChannelBondingMode5GHz) {
10300 wlan_hdd_band_5_ghz.ht_cap.cap &=
10301 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10302 }
10303
Abhishek Singhf512bf32016-05-04 16:47:46 +053010304 /*
10305 * In case of static linked driver at the time of driver unload,
10306 * module exit doesn't happens. Module cleanup helps in cleaning
10307 * of static memory.
10308 * If driver load happens statically, at the time of driver unload,
10309 * wiphy flags don't get reset because of static memory.
10310 * It's better not to store channel in static memory.
10311 */
Dustin Browna30892e2016-10-12 17:28:36 -070010312 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10313 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010314 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010315 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010316 hdd_err("Not enough memory to allocate channels");
10317 return -ENOMEM;
10318 }
Dustin Browna30892e2016-10-12 17:28:36 -070010319 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010320 &hdd_channels_2_4_ghz[0],
10321 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010322 if ((hdd_is_5g_supported(pHddCtx)) &&
10323 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10324 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10325 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10326 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010327 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10328 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010329 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010330 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010331 hdd_err("Not enough memory to allocate channels");
10332 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010333 bands[NL80211_BAND_2GHZ]->channels);
10334 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010335 return -ENOMEM;
10336 }
Dustin Browna30892e2016-10-12 17:28:36 -070010337 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010338 &hdd_channels_5_ghz[0],
10339 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340 }
10341
Dustin Browna30892e2016-10-12 17:28:36 -070010342 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010343
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010344 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010345 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010346
10347 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10348 struct ieee80211_supported_band *band = wiphy->bands[i];
10349
Dustin Browna30892e2016-10-12 17:28:36 -070010350 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010351 eCSR_BAND_5G == pCfg->nBandCapability) {
10352 /* 5G only */
10353#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10354 /* Enable social channels for P2P */
10355 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10356 (band->channels[j].center_freq))
10357 band->channels[j].flags &=
10358 ~IEEE80211_CHAN_DISABLED;
10359 else
10360#endif
10361 band->channels[j].flags |=
10362 IEEE80211_CHAN_DISABLED;
10363 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010364 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010365 eCSR_BAND_24 == pCfg->nBandCapability) {
10366 /* 2G only */
10367 band->channels[j].flags |=
10368 IEEE80211_CHAN_DISABLED;
10369 continue;
10370 }
10371 }
10372 }
10373 /*Initialise the supported cipher suite details */
10374 wiphy->cipher_suites = hdd_cipher_suites;
10375 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10376
10377 /*signal strength in mBm (100*dBm) */
10378 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10379 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10380
Anurag Chouhan6d760662016-02-20 16:05:43 +053010381 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010382 wiphy->n_vendor_commands =
10383 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10384 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10385
10386 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10387 wiphy->n_vendor_events =
10388 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10389 }
10390
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010391 if (pCfg->enableDFSMasterCap) {
10392 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10393 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010394
10395 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10396
10397#ifdef QCA_HT_2040_COEX
10398 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10399#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010400 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010401
10402#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10403 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10404 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10405 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10406 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10407#endif
10408
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010409 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010410 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010412 EXIT();
10413 return 0;
10414}
10415
Abhishek Singhf512bf32016-05-04 16:47:46 +053010416/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010417 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10418 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010419 *
10420 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010421 * memory allocated in wlan_hdd_cfg80211_init also
10422 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010423 *
10424 * Return: void
10425 */
10426void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10427{
10428 int i;
10429
Dustin Browna30892e2016-10-12 17:28:36 -070010430 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010431 if (NULL != wiphy->bands[i] &&
10432 (NULL != wiphy->bands[i]->channels)) {
10433 qdf_mem_free(wiphy->bands[i]->channels);
10434 wiphy->bands[i]->channels = NULL;
10435 }
10436 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010437 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010438}
10439
Yingying Tang80e15f32016-09-27 18:23:01 +080010440/**
10441 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10442 * @hdd_ctx: HDD context
10443 *
10444 * this function will update capabilities for supported bands
10445 *
10446 * Return: void
10447 */
10448static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10449{
10450 uint32_t val32;
10451 uint16_t val16;
10452 tSirMacHTCapabilityInfo *ht_cap_info;
10453 QDF_STATUS status;
10454
10455 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10456 if (QDF_STATUS_SUCCESS != status) {
10457 hdd_err("could not get HT capability info");
10458 val32 = 0;
10459 }
10460 val16 = (uint16_t)val32;
10461 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10462
10463 if (ht_cap_info->txSTBC == true) {
10464 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10465 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10466 IEEE80211_HT_CAP_TX_STBC;
10467 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10468 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10469 IEEE80211_HT_CAP_TX_STBC;
10470 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010471
10472 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10473 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10474 vht_cap.vht_supported = 0;
10475 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10476 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10477 vht_cap.vht_supported = 0;
10478 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10479 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010480}
10481
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010482/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010483 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010484 * initialization. In wlan_hdd_cfg80211_init, only the
10485 * default values will be initialized. The final initialization
10486 * of all required members can be done here.
10487 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010488void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010489{
Yingying Tang80e15f32016-09-27 18:23:01 +080010490 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10491
10492 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010493}
10494
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010495/**
10496 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10497 * @cfg: hdd cfg
10498 *
10499 * this function update 11n mode in hdd cfg
10500 *
10501 * Return: void
10502 */
10503void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10504{
10505 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10506 hdd_notice("support 11ac");
10507 } else {
10508 hdd_notice("not support 11ac");
10509 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10510 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10511 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10512 cfg->sap_p2p_11ac_override = 0;
10513 }
10514 }
10515}
10516
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010517/* In this function we are registering wiphy. */
10518int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10519{
10520 ENTER();
10521 /* Register our wiphy dev with cfg80211 */
10522 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010523 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010524 return -EIO;
10525 }
10526
10527 EXIT();
10528 return 0;
10529}
10530
10531/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010532 * HDD function to update wiphy capability based on target offload status.
10533 *
10534 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10535 * capability even before downloading firmware to the target. In discrete
10536 * case, host will get know certain offload capability (say sched_scan
10537 * caps) only after downloading firmware to the target and target boots up.
10538 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10539 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010540 */
10541void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10542{
10543#ifdef FEATURE_WLAN_SCAN_PNO
10544 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10545 struct hdd_config *pCfg = pHddCtx->config;
10546
10547 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10548 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010549 * have PNO support.
10550 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010551 if (!pCfg->PnoOffload) {
10552 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10553 wiphy->max_sched_scan_ssids = 0;
10554 wiphy->max_match_sets = 0;
10555 wiphy->max_sched_scan_ie_len = 0;
10556 }
10557#endif
10558}
10559
10560/* This function registers for all frame which supplicant is interested in */
10561void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10562{
10563 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10564 /* Register for all P2P action, public action etc frames */
10565 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10566
10567 ENTER();
10568
Abhishek Singh7996eb72015-12-30 17:24:02 +053010569 /* Register frame indication call back */
10570 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10571
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010572 /* Register for p2p ack indication */
10573 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10574
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010575 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010576 * initialized. Once we will move to 2.6.37 kernel, in which we have
10577 * frame register ops, we will move this code as a part of that
10578 */
10579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010580 /* GAS Initial Request */
10581 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10582 (uint8_t *) GAS_INITIAL_REQ,
10583 GAS_INITIAL_REQ_SIZE);
10584
10585 /* GAS Initial Response */
10586 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10587 (uint8_t *) GAS_INITIAL_RSP,
10588 GAS_INITIAL_RSP_SIZE);
10589
10590 /* GAS Comeback Request */
10591 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10592 (uint8_t *) GAS_COMEBACK_REQ,
10593 GAS_COMEBACK_REQ_SIZE);
10594
10595 /* GAS Comeback Response */
10596 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10597 (uint8_t *) GAS_COMEBACK_RSP,
10598 GAS_COMEBACK_RSP_SIZE);
10599
10600 /* P2P Public Action */
10601 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10602 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10603 P2P_PUBLIC_ACTION_FRAME_SIZE);
10604
10605 /* P2P Action */
10606 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10607 (uint8_t *) P2P_ACTION_FRAME,
10608 P2P_ACTION_FRAME_SIZE);
10609
10610 /* WNM BSS Transition Request frame */
10611 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10612 (uint8_t *) WNM_BSS_ACTION_FRAME,
10613 WNM_BSS_ACTION_FRAME_SIZE);
10614
10615 /* WNM-Notification */
10616 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10617 (uint8_t *) WNM_NOTIFICATION_FRAME,
10618 WNM_NOTIFICATION_FRAME_SIZE);
10619}
10620
10621void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10622{
10623 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10624 /* Register for all P2P action, public action etc frames */
10625 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10626
10627 ENTER();
10628
10629 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010630 * initialized. Once we will move to 2.6.37 kernel, in which we have
10631 * frame register ops, we will move this code as a part of that
10632 */
10633
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010634 /* GAS Initial Request */
10635
10636 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10637 (uint8_t *) GAS_INITIAL_REQ,
10638 GAS_INITIAL_REQ_SIZE);
10639
10640 /* GAS Initial Response */
10641 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10642 (uint8_t *) GAS_INITIAL_RSP,
10643 GAS_INITIAL_RSP_SIZE);
10644
10645 /* GAS Comeback Request */
10646 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10647 (uint8_t *) GAS_COMEBACK_REQ,
10648 GAS_COMEBACK_REQ_SIZE);
10649
10650 /* GAS Comeback Response */
10651 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10652 (uint8_t *) GAS_COMEBACK_RSP,
10653 GAS_COMEBACK_RSP_SIZE);
10654
10655 /* P2P Public Action */
10656 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10657 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10658 P2P_PUBLIC_ACTION_FRAME_SIZE);
10659
10660 /* P2P Action */
10661 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10662 (uint8_t *) P2P_ACTION_FRAME,
10663 P2P_ACTION_FRAME_SIZE);
10664
10665 /* WNM-Notification */
10666 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10667 (uint8_t *) WNM_NOTIFICATION_FRAME,
10668 WNM_NOTIFICATION_FRAME_SIZE);
10669}
10670
10671#ifdef FEATURE_WLAN_WAPI
10672void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10673 const uint8_t *mac_addr, const uint8_t *key,
10674 int key_Len)
10675{
10676 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10677 tCsrRoamSetKey setKey;
10678 bool isConnected = true;
10679 int status = 0;
10680 uint32_t roamId = 0xFF;
10681 uint8_t *pKeyPtr = NULL;
10682 int n = 0;
10683
Jeff Johnson46b40792016-06-29 14:03:14 -070010684 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010685 hdd_device_mode_to_string(pAdapter->device_mode),
10686 pAdapter->device_mode);
10687
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010688 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010689 setKey.keyId = key_index; /* Store Key ID */
10690 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10691 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10692 setKey.paeRole = 0; /* the PAE role */
10693 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010694 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010695 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010696 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 }
10698 setKey.keyLength = key_Len;
10699 pKeyPtr = setKey.Key;
10700 memcpy(pKeyPtr, key, key_Len);
10701
Jeff Johnson46b40792016-06-29 14:03:14 -070010702 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010703 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010704 hdd_notice("WAPI KEY Data[%d]:%02x ",
10705 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706
10707 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10708 if (isConnected) {
10709 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10710 pAdapter->sessionId, &setKey, &roamId);
10711 }
10712 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010713 hdd_err("sme_roam_set_key returned ERROR status= %d",
10714 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010715 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10716 }
10717}
10718#endif /* FEATURE_WLAN_WAPI */
10719
10720uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10721 uint8_t eid)
10722{
10723 int left = length;
10724 uint8_t *ptr = (uint8_t *)ies_ptr;
10725 uint8_t elem_id, elem_len;
10726
10727 while (left >= 2) {
10728 elem_id = ptr[0];
10729 elem_len = ptr[1];
10730 left -= 2;
10731 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010732 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010733 eid, elem_len, left);
10734 return NULL;
10735 }
10736 if (elem_id == eid) {
10737 return ptr;
10738 }
10739
10740 left -= elem_len;
10741 ptr += (elem_len + 2);
10742 }
10743 return NULL;
10744}
10745
10746/*
10747 * FUNCTION: wlan_hdd_validate_operation_channel
10748 * called by wlan_hdd_cfg80211_start_bss() and
10749 * wlan_hdd_set_channel()
10750 * This function validates whether given channel is part of valid
10751 * channel list.
10752 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010753QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010754 int channel)
10755{
10756
10757 uint32_t num_ch = 0;
10758 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10759 u32 indx = 0;
10760 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10761 uint8_t fValidChannel = false, count = 0;
10762 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10763
10764 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10765
10766 if (hdd_pConfig_ini->sapAllowAllChannel) {
10767 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010768 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010769 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010770 fValidChannel = true;
10771 break;
10772 }
10773 }
10774 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010775 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010776 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 }
10778 } else {
10779 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10780 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010781 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010782 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010783 }
10784 for (indx = 0; indx < num_ch; indx++) {
10785 if (channel == valid_ch[indx]) {
10786 break;
10787 }
10788 }
10789
10790 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010791 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010792 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 }
10794 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010795 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010796
10797}
10798
10799#ifdef DHCP_SERVER_OFFLOAD
10800static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10801{
10802 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10803 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10804 uint8_t numEntries = 0;
10805 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10806 uint8_t num;
10807 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010808 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010809 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010810 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010811 return;
10812 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10814 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10815 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10816 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10817 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10818 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010819 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010820 goto end;
10821 }
10822 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010823 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010824 goto end;
10825 }
10826 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010827 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010828 goto end;
10829 }
10830 for (num = 0; num < numEntries; num++) {
10831 temp = srv_ip[num];
10832 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10833 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010834 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010835 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010836 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010837 goto end;
10838 }
Jeff Johnson77848112016-06-29 14:52:06 -070010839 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010841 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842 return;
10843}
10844#endif /* DHCP_SERVER_OFFLOAD */
10845
10846static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10847 struct net_device *dev,
10848 struct bss_parameters *params)
10849{
10850 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10851 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10852 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010853 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010854
10855 ENTER();
10856
Anurag Chouhan6d760662016-02-20 16:05:43 +053010857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010858 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859 return -EINVAL;
10860 }
10861
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010862 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10863 hdd_err("invalid session id: %d", pAdapter->sessionId);
10864 return -EINVAL;
10865 }
10866
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010867 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010868 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10869 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010870 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010871 hdd_device_mode_to_string(pAdapter->device_mode),
10872 pAdapter->device_mode, params->ap_isolate);
10873
10874 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10875 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010876 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010878
Krunal Sonib4326f22016-03-10 13:05:51 -080010879 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10880 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010881 return -EOPNOTSUPP;
10882 }
10883
10884 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010885 * want to update this parameter
10886 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 if (-1 != params->ap_isolate) {
10888 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10889 !!params->ap_isolate;
10890
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010891 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892 pAdapter->sessionId,
10893 pAdapter->sessionCtx.
10894 ap.
10895 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010896 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897 ret = -EINVAL;
10898 }
10899 }
10900
10901 EXIT();
10902 return ret;
10903}
10904
Krunal Soni8c37e322016-02-03 16:08:37 -080010905/**
10906 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10907 * @ndev: pointer to net device provided by supplicant
10908 * @type: type of the interface, upper layer wanted to change
10909 *
10910 * Upper layer provides the new interface mode that needs to be changed
10911 * for given net device
10912 *
10913 * Return: success or failure in terms of integer value
10914 */
10915static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 enum nl80211_iftype type)
10917{
Krunal Soni8c37e322016-02-03 16:08:37 -080010918 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10919 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10920 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010921 hdd_wext_state_t *wext;
10922 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010923 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010924
10925 ENTER();
10926
Krunal Soni8c37e322016-02-03 16:08:37 -080010927 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010928 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010929 return 0;
10930 }
10931
10932 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010933 hdd_stop_adapter(hdd_ctx, adapter, true);
10934 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010935 wdev->iftype = type;
10936 /*Check for sub-string p2p to confirm its a p2p interface */
10937 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010938 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010939 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010940 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010941 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010942 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010943 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010944 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010946 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010947 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010948 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10949 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010950 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10951 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010952 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010953 adapter->scan_info.scanAddIE.length;
10954 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010955 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010956 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10957 wext->roamProfile.phyMode =
10958 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10959 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 EXIT();
10961 return status;
10962}
10963
10964static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10965 struct net_device *dev,
10966 struct bss_parameters *params)
10967{
10968 int ret;
10969
10970 cds_ssr_protect(__func__);
10971 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10972 cds_ssr_unprotect(__func__);
10973
10974 return ret;
10975}
10976
10977/* FUNCTION: wlan_hdd_change_country_code_cd
10978 * to wait for contry code completion
10979 */
10980void *wlan_hdd_change_country_code_cb(void *pAdapter)
10981{
10982 hdd_adapter_t *call_back_pAdapter = pAdapter;
10983 complete(&call_back_pAdapter->change_country_code);
10984 return NULL;
10985}
10986
Rajeev Kumar98edb772016-01-19 12:42:19 -080010987/**
10988 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10989 * @wiphy: Pointer to the wiphy structure
10990 * @ndev: Pointer to the net device
10991 * @type: Interface type
10992 * @flags: Flags for change interface
10993 * @params: Pointer to change interface parameters
10994 *
10995 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996 */
10997static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10998 struct net_device *ndev,
10999 enum nl80211_iftype type,
11000 u32 *flags,
11001 struct vif_params *params)
11002{
11003 struct wireless_dev *wdev;
11004 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11005 hdd_context_t *pHddCtx;
11006 tCsrRoamProfile *pRoamProfile = NULL;
11007 eCsrRoamBssType LastBSSType;
11008 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011009 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011010 int status;
11011
11012 ENTER();
11013
Anurag Chouhan6d760662016-02-20 16:05:43 +053011014 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011015 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 return -EINVAL;
11017 }
11018
11019 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11020 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011021 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011022 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011023
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011024 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011025 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11026 pAdapter->sessionId, type));
11027
Jeff Johnson77848112016-06-29 14:52:06 -070011028 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011029 pAdapter->device_mode, type);
11030
Arun Khandavallifae92942016-08-01 13:31:08 +053011031 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11032 if (status) {
11033 hdd_err("Failed to start modules");
11034 return -EINVAL;
11035 }
11036
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011037 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011038 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11039 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011040 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011041 return -EINVAL;
11042 }
11043
11044 pConfig = pHddCtx->config;
11045 wdev = ndev->ieee80211_ptr;
11046
11047 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011048 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011049
11050 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
11051
Krunal Sonib4326f22016-03-10 13:05:51 -080011052 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11053 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11054 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11055 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056 hdd_wext_state_t *pWextState =
11057 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11058
11059 pRoamProfile = &pWextState->roamProfile;
11060 LastBSSType = pRoamProfile->BSSType;
11061
11062 switch (type) {
11063 case NL80211_IFTYPE_STATION:
11064 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011065 case NL80211_IFTYPE_ADHOC:
11066 if (type == NL80211_IFTYPE_ADHOC) {
11067 wlan_hdd_tdls_exit(pAdapter);
11068 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011069 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011070 }
11071 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11072 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011073 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011075 if (hdd_start_adapter(pAdapter)) {
11076 hdd_err("Failed to start adapter :%d",
11077 pAdapter->device_mode);
11078 return -EINVAL;
11079 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011080 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011081 case NL80211_IFTYPE_AP:
11082 case NL80211_IFTYPE_P2P_GO:
11083 {
Jeff Johnson77848112016-06-29 14:52:06 -070011084 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011085 (type ==
11086 NL80211_IFTYPE_AP) ? "SoftAP" :
11087 "P2pGo");
11088
11089 /* Cancel any remain on channel for GO mode */
11090 if (NL80211_IFTYPE_P2P_GO == type) {
11091 wlan_hdd_cancel_existing_remain_on_channel
11092 (pAdapter);
11093 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011094
Arun Khandavallifae92942016-08-01 13:31:08 +053011095 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 /* De-init the adapter */
11097 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11098 memset(&pAdapter->sessionCtx, 0,
11099 sizeof(pAdapter->sessionCtx));
11100 pAdapter->device_mode =
11101 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011102 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11103 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011104
11105 /*
11106 * Fw will take care incase of concurrency
11107 */
11108
Krunal Sonib4326f22016-03-10 13:05:51 -080011109 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011111 /* To meet Android requirements create
11112 * a randomized MAC address of the
11113 * form 02:1A:11:Fx:xx:xx
11114 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 get_random_bytes(&ndev->dev_addr[3], 3);
11116 ndev->dev_addr[0] = 0x02;
11117 ndev->dev_addr[1] = 0x1A;
11118 ndev->dev_addr[2] = 0x11;
11119 ndev->dev_addr[3] |= 0xF0;
11120 memcpy(pAdapter->macAddressCurrent.
11121 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011122 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011123 pr_info("wlan: Generated HotSpot BSSID "
11124 MAC_ADDRESS_STR "\n",
11125 MAC_ADDR_ARRAY(ndev->dev_addr));
11126 }
11127
11128 hdd_set_ap_ops(pAdapter->dev);
11129
Arun Khandavallifae92942016-08-01 13:31:08 +053011130 if (hdd_start_adapter(pAdapter)) {
11131 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 return -EINVAL;
11133 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011134 /* Interface type changed update in wiphy structure */
11135 if (wdev) {
11136 wdev->iftype = type;
11137 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011138 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139 return -EINVAL;
11140 }
11141 goto done;
11142 }
11143
11144 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011145 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146 type);
11147 return -EOPNOTSUPP;
11148 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011149 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11150 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011151 switch (type) {
11152 case NL80211_IFTYPE_STATION:
11153 case NL80211_IFTYPE_P2P_CLIENT:
11154 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011155 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11156 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011157 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011159 if (hdd_start_adapter(pAdapter)) {
11160 hdd_err("Failed to start adapter :%d",
11161 pAdapter->device_mode);
11162 return -EINVAL;
11163 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011164 goto done;
11165
11166 case NL80211_IFTYPE_AP:
11167 case NL80211_IFTYPE_P2P_GO:
11168 wdev->iftype = type;
11169 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011170 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011171 goto done;
11172
11173 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011174 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011175 type);
11176 return -EOPNOTSUPP;
11177 }
11178 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011179 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 pAdapter->device_mode);
11181 return -EOPNOTSUPP;
11182 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183done:
11184 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011185 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011187 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011188
11189 EXIT();
11190 return 0;
11191}
11192
Rajeev Kumar98edb772016-01-19 12:42:19 -080011193/**
11194 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11195 * @wiphy: Pointer to the wiphy structure
11196 * @ndev: Pointer to the net device
11197 * @type: Interface type
11198 * @flags: Flags for change interface
11199 * @params: Pointer to change interface parameters
11200 *
11201 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011202 */
11203static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11204 struct net_device *ndev,
11205 enum nl80211_iftype type,
11206 u32 *flags,
11207 struct vif_params *params)
11208{
11209 int ret;
11210
11211 cds_ssr_protect(__func__);
11212 ret =
11213 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11214 cds_ssr_unprotect(__func__);
11215
11216 return ret;
11217}
11218
11219#ifdef FEATURE_WLAN_TDLS
11220static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11221 int index, uint8_t match)
11222{
11223 int i;
11224 for (i = 0; i < index; i++) {
11225 if (arr[i] == match)
11226 return true;
11227 }
11228 return false;
11229}
11230#endif
11231
11232/**
11233 * __wlan_hdd_change_station() - change station
11234 * @wiphy: Pointer to the wiphy structure
11235 * @dev: Pointer to the net device.
11236 * @mac: bssid
11237 * @params: Pointer to station parameters
11238 *
11239 * Return: 0 for success, error number on failure.
11240 */
11241#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11242static int __wlan_hdd_change_station(struct wiphy *wiphy,
11243 struct net_device *dev,
11244 const uint8_t *mac,
11245 struct station_parameters *params)
11246#else
11247static int __wlan_hdd_change_station(struct wiphy *wiphy,
11248 struct net_device *dev,
11249 uint8_t *mac,
11250 struct station_parameters *params)
11251#endif
11252{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011253 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11255 hdd_context_t *pHddCtx;
11256 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011257 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258#ifdef FEATURE_WLAN_TDLS
11259 tCsrStaParams StaParams = { 0 };
11260 uint8_t isBufSta = 0;
11261 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011262 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263#endif
11264 int ret;
11265
11266 ENTER();
11267
Anurag Chouhan6d760662016-02-20 16:05:43 +053011268 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011269 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 return -EINVAL;
11271 }
11272
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011273 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 TRACE_CODE_HDD_CHANGE_STATION,
11275 pAdapter->sessionId, params->listen_interval));
11276
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011277 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11278 hdd_err("invalid session id: %d", pAdapter->sessionId);
11279 return -EINVAL;
11280 }
11281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011282 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11283 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011284 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011286
11287 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11288
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011289 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290
Krunal Sonib4326f22016-03-10 13:05:51 -080011291 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11292 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011293 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11294 status =
11295 hdd_softap_change_sta_state(pAdapter,
11296 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011297 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011299 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011300 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011301 return -EINVAL;
11302 }
11303 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011304 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11305 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011306#ifdef FEATURE_WLAN_TDLS
11307 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011308
11309 if (cds_is_sub_20_mhz_enabled()) {
11310 hdd_err("TDLS not allowed with sub 20 MHz");
11311 return -EINVAL;
11312 }
11313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011314 StaParams.capability = params->capability;
11315 StaParams.uapsd_queues = params->uapsd_queues;
11316 StaParams.max_sp = params->max_sp;
11317
11318 /* Convert (first channel , number of channels) tuple to
11319 * the total list of channels. This goes with the assumption
11320 * that if the first channel is < 14, then the next channels
11321 * are an incremental of 1 else an incremental of 4 till the number
11322 * of channels.
11323 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011324 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325 if (0 != params->supported_channels_len) {
11326 int i = 0, j = 0, k = 0, no_of_channels = 0;
11327 int num_unique_channels;
11328 int next;
11329 for (i = 0;
11330 i < params->supported_channels_len
11331 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11332 int wifi_chan_index;
11333 if (!wlan_hdd_is_duplicate_channel
11334 (StaParams.supported_channels, j,
11335 params->supported_channels[i])) {
11336 StaParams.
11337 supported_channels[j] =
11338 params->
11339 supported_channels[i];
11340 } else {
11341 continue;
11342 }
11343 wifi_chan_index =
11344 ((StaParams.supported_channels[j] <=
11345 HDD_CHANNEL_14) ? 1 : 4);
11346 no_of_channels =
11347 params->supported_channels[i + 1];
11348
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011349 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d", i, j, k, j,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011350 StaParams.
11351 supported_channels[j],
11352 wifi_chan_index,
11353 no_of_channels);
11354 for (k = 1; k <= no_of_channels &&
11355 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11356 k++) {
11357 next =
11358 StaParams.
11359 supported_channels[j] +
11360 wifi_chan_index;
11361 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11362 StaParams.
11363 supported_channels[j
11364 +
11365 1]
11366 = next;
11367 } else {
11368 continue;
11369 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011370 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011371 j + 1,
11372 StaParams.
11373 supported_channels[j +
11374 1]);
11375 j += 1;
11376 }
11377 }
11378 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011379 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011380 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011381 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 StaParams.
11383 supported_channels[i]);
11384 }
11385 if (MAX_CHANNEL < num_unique_channels)
11386 num_unique_channels = MAX_CHANNEL;
11387 StaParams.supported_channels_len =
11388 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011389 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390 StaParams.supported_channels_len);
11391 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011392 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 params->supported_oper_classes,
11394 params->supported_oper_classes_len);
11395 StaParams.supported_oper_classes_len =
11396 params->supported_oper_classes_len;
11397
11398 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011399 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011400 params->ext_capab,
11401 sizeof(StaParams.extn_capability));
11402
11403 if (NULL != params->ht_capa) {
11404 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011405 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 sizeof(tSirHTCap));
11407 }
11408
11409 StaParams.supported_rates_len =
11410 params->supported_rates_len;
11411
11412 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11413 * The supported_rates array , for all the structures propogating till Add Sta
11414 * to the firmware has to be modified , if the supplicant (ieee80211) is
11415 * modified to send more rates.
11416 */
11417
11418 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11419 */
11420 if (StaParams.supported_rates_len >
11421 SIR_MAC_MAX_SUPP_RATES)
11422 StaParams.supported_rates_len =
11423 SIR_MAC_MAX_SUPP_RATES;
11424
11425 if (0 != StaParams.supported_rates_len) {
11426 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011427 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 params->supported_rates,
11429 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011430 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011431 StaParams.supported_rates_len);
11432 for (i = 0; i < StaParams.supported_rates_len;
11433 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011434 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 StaParams.supported_rates[i]);
11436 }
11437
11438 if (NULL != params->vht_capa) {
11439 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011440 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011441 params->vht_capa,
11442 sizeof(tSirVHTCap));
11443 }
11444
11445 if (0 != params->ext_capab_len) {
11446 /*Define A Macro : TODO Sunil */
11447 if ((1 << 4) & StaParams.extn_capability[3]) {
11448 isBufSta = 1;
11449 }
11450 /* TDLS Channel Switching Support */
11451 if ((1 << 6) & StaParams.extn_capability[3]) {
11452 isOffChannelSupported = 1;
11453 }
11454 }
11455
Nitesh Shah99934ac2016-09-05 15:54:08 +053011456 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011457 (params->ht_capa || params->vht_capa ||
11458 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011459 is_qos_wmm_sta = true;
11460
11461 hdd_notice("%s: TDLS Peer is QOS capable"
11462 " is_qos_wmm_sta= %d HTcapPresent = %d",
11463 __func__, is_qos_wmm_sta,
11464 StaParams.htcap_present);
11465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011466 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011467 &StaParams,
11468 isBufSta,
11469 isOffChannelSupported,
11470 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011471 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011472 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011473 return -EINVAL;
11474 }
11475
11476 status =
11477 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11478 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011479 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011480 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011481 return -EINVAL;
11482 }
11483 }
11484#endif
11485 }
11486 EXIT();
11487 return ret;
11488}
11489
11490/**
11491 * wlan_hdd_change_station() - cfg80211 change station handler function
11492 * @wiphy: Pointer to the wiphy structure
11493 * @dev: Pointer to the net device.
11494 * @mac: bssid
11495 * @params: Pointer to station parameters
11496 *
11497 * This is the cfg80211 change station handler function which invokes
11498 * the internal function @__wlan_hdd_change_station with
11499 * SSR protection.
11500 *
11501 * Return: 0 for success, error number on failure.
11502 */
11503#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11504static int wlan_hdd_change_station(struct wiphy *wiphy,
11505 struct net_device *dev,
11506 const u8 *mac,
11507 struct station_parameters *params)
11508#else
11509static int wlan_hdd_change_station(struct wiphy *wiphy,
11510 struct net_device *dev,
11511 u8 *mac,
11512 struct station_parameters *params)
11513#endif
11514{
11515 int ret;
11516
11517 cds_ssr_protect(__func__);
11518 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11519 cds_ssr_unprotect(__func__);
11520
11521 return ret;
11522}
11523
11524/*
11525 * FUNCTION: __wlan_hdd_cfg80211_add_key
11526 * This function is used to initialize the key information
11527 */
11528static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11529 struct net_device *ndev,
11530 u8 key_index, bool pairwise,
11531 const u8 *mac_addr,
11532 struct key_params *params)
11533{
11534 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11535 tCsrRoamSetKey setKey;
11536 int status;
11537 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011539 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540 hdd_context_t *pHddCtx;
11541 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11542
11543 ENTER();
11544
Anurag Chouhan6d760662016-02-20 16:05:43 +053011545 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011546 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011547 return -EINVAL;
11548 }
11549
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011550 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11551 hdd_err("invalid session id: %d", pAdapter->sessionId);
11552 return -EINVAL;
11553 }
11554
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011555 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11557 pAdapter->sessionId, params->key_len));
11558 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11559 status = wlan_hdd_validate_context(pHddCtx);
11560
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011561 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011563
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011564 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 hdd_device_mode_to_string(pAdapter->device_mode),
11566 pAdapter->device_mode);
11567
11568 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011569 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011570
11571 return -EINVAL;
11572 }
11573
11574 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011575 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011576
11577 return -EINVAL;
11578 }
11579
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011580 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011581
11582 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011583 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584 setKey.keyId = key_index;
11585 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011586 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587
11588 switch (params->cipher) {
11589 case WLAN_CIPHER_SUITE_WEP40:
11590 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11591 break;
11592
11593 case WLAN_CIPHER_SUITE_WEP104:
11594 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11595 break;
11596
11597 case WLAN_CIPHER_SUITE_TKIP:
11598 {
11599 u8 *pKey = &setKey.Key[0];
11600 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11601
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011602 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011603
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011604 /* Supplicant sends the 32bytes key in this order
11605 *
11606 * |--------------|----------|----------|
11607 * | Tk1 |TX-MIC | RX Mic |
11608 * |--------------|----------|----------|
11609 * <---16bytes---><--8bytes--><--8bytes-->
11610 *
11611 * Sme expects the 32 bytes key to be in the below order
11612 *
11613 * |--------------|----------|----------|
11614 * | Tk1 |RX-MIC | TX Mic |
11615 * |--------------|----------|----------|
11616 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011617 */
11618 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011619 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620
11621 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011622 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623
11624 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011625 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011626
11627 break;
11628 }
11629
11630 case WLAN_CIPHER_SUITE_CCMP:
11631 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11632 break;
11633
11634#ifdef FEATURE_WLAN_WAPI
11635 case WLAN_CIPHER_SUITE_SMS4:
11636 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011637 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11639 mac_addr, params->key,
11640 params->key_len);
11641 return 0;
11642 }
11643#endif
11644
11645#ifdef FEATURE_WLAN_ESE
11646 case WLAN_CIPHER_SUITE_KRK:
11647 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11648 break;
11649#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11650 case WLAN_CIPHER_SUITE_BTK:
11651 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11652 break;
11653#endif
11654#endif
11655
11656#ifdef WLAN_FEATURE_11W
11657 case WLAN_CIPHER_SUITE_AES_CMAC:
11658 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11659 break;
11660#endif
11661
11662 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011663 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 return -EOPNOTSUPP;
11665 }
11666
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011667 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011668
11669 if (!pairwise) {
11670 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011671 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011672 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011673 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011674 } else {
11675 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011676 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011678 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011679 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011680 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011681 /* if a key is already installed, block all subsequent ones */
11682 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011683 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011684 return 0;
11685 }
11686
11687 setKey.keyDirection = eSIR_TX_RX;
11688 /*Set the group key */
11689 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11690 pAdapter->sessionId, &setKey, &roamId);
11691
11692 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011693 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011694 return -EINVAL;
11695 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011696 /* Save the keys here and call sme_roam_set_key for setting
11697 * the PTK after peer joins the IBSS network
11698 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011699 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011700 &setKey, sizeof(tCsrRoamSetKey));
11701
11702 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11703 return status;
11704 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011705 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11706 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011707 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11708 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011709 status = wlansap_set_key_sta(
11710 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011711 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011712 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 __LINE__, status);
11714 }
11715 }
11716
11717 /* Save the key in ap ctx for use on START_BASS and restart */
11718 if (pairwise ||
11719 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11720 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011721 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011722 sizeof(tCsrRoamSetKey));
11723 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011724 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011725 sizeof(tCsrRoamSetKey));
11726
Krunal Sonib4326f22016-03-10 13:05:51 -080011727 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11728 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729 hdd_wext_state_t *pWextState =
11730 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11731 hdd_station_ctx_t *pHddStaCtx =
11732 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11733
11734 if (!pairwise) {
11735 /* set group key */
11736 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011737 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011738 __func__, __LINE__);
11739 hdd_perform_roam_set_key_complete(pAdapter);
11740 }
11741 }
11742
11743 pWextState->roamProfile.Keys.KeyLength[key_index] =
11744 (u8) params->key_len;
11745
11746 pWextState->roamProfile.Keys.defaultIndex = key_index;
11747
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011748 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 KeyMaterial[key_index][0], params->key,
11750 params->key_len);
11751
11752 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11753
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011754 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11756 setKey.keyDirection);
11757
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011758 /* The supplicant may attempt to set the PTK once
11759 * pre-authentication is done. Save the key in the
11760 * UMAC and include it in the ADD BSS request
11761 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011762 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011763 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011764 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011765 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011767 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011768 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 return -EINVAL;
11770 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771
11772 /* issue set key request to SME */
11773 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11774 pAdapter->sessionId, &setKey, &roamId);
11775
11776 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011777 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011778 pHddStaCtx->roam_info.roamingState =
11779 HDD_ROAM_STATE_NONE;
11780 return -EINVAL;
11781 }
11782
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011783 /* in case of IBSS as there was no information
11784 * available about WEP keys during IBSS join, group
11785 * key intialized with NULL key, so re-initialize
11786 * group key with correct value
11787 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011788 if ((eCSR_BSS_TYPE_START_IBSS ==
11789 pWextState->roamProfile.BSSType)
11790 &&
11791 !((IW_AUTH_KEY_MGMT_802_1X ==
11792 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11793 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11794 pHddStaCtx->conn_info.authType)
11795 )
11796 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11797 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11798 )
11799 ) {
11800 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011801 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011802
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011803 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11805 setKey.keyDirection);
11806
11807 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11808 pAdapter->sessionId, &setKey,
11809 &roamId);
11810
11811 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011812 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011813 pHddStaCtx->roam_info.roamingState =
11814 HDD_ROAM_STATE_NONE;
11815 return -EINVAL;
11816 }
11817 }
11818 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011819 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011820 return 0;
11821}
11822
11823static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11824 struct net_device *ndev,
11825 u8 key_index, bool pairwise,
11826 const u8 *mac_addr,
11827 struct key_params *params)
11828{
11829 int ret;
11830 cds_ssr_protect(__func__);
11831 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11832 mac_addr, params);
11833 cds_ssr_unprotect(__func__);
11834
11835 return ret;
11836}
11837
11838/*
11839 * FUNCTION: __wlan_hdd_cfg80211_get_key
11840 * This function is used to get the key information
11841 */
11842static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11843 struct net_device *ndev,
11844 u8 key_index, bool pairwise,
11845 const u8 *mac_addr, void *cookie,
11846 void (*callback)(void *cookie,
11847 struct key_params *)
11848 )
11849{
11850 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11851 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11852 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11853 struct key_params params;
11854
11855 ENTER();
11856
Anurag Chouhan6d760662016-02-20 16:05:43 +053011857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011858 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859 return -EINVAL;
11860 }
11861
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011862 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011863 hdd_device_mode_to_string(pAdapter->device_mode),
11864 pAdapter->device_mode);
11865
11866 memset(&params, 0, sizeof(params));
11867
11868 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011869 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870 key_index);
11871 return -EINVAL;
11872 }
11873
11874 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11875 case eCSR_ENCRYPT_TYPE_NONE:
11876 params.cipher = IW_AUTH_CIPHER_NONE;
11877 break;
11878
11879 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11880 case eCSR_ENCRYPT_TYPE_WEP40:
11881 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11882 break;
11883
11884 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11885 case eCSR_ENCRYPT_TYPE_WEP104:
11886 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11887 break;
11888
11889 case eCSR_ENCRYPT_TYPE_TKIP:
11890 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11891 break;
11892
11893 case eCSR_ENCRYPT_TYPE_AES:
11894 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11895 break;
11896
11897 default:
11898 params.cipher = IW_AUTH_CIPHER_NONE;
11899 break;
11900 }
11901
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011902 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011903 TRACE_CODE_HDD_CFG80211_GET_KEY,
11904 pAdapter->sessionId, params.cipher));
11905
11906 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11907 params.seq_len = 0;
11908 params.seq = NULL;
11909 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11910 callback(cookie, &params);
11911
11912 EXIT();
11913 return 0;
11914}
11915
11916static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11917 struct net_device *ndev,
11918 u8 key_index, bool pairwise,
11919 const u8 *mac_addr, void *cookie,
11920 void (*callback)(void *cookie,
11921 struct key_params *)
11922 )
11923{
11924 int ret;
11925
11926 cds_ssr_protect(__func__);
11927 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11928 mac_addr, cookie, callback);
11929 cds_ssr_unprotect(__func__);
11930
11931 return ret;
11932}
11933
11934/**
11935 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11936 * @wiphy: wiphy interface context
11937 * @ndev: pointer to net device
11938 * @key_index: Key index used in 802.11 frames
11939 * @unicast: true if it is unicast key
11940 * @multicast: true if it is multicast key
11941 *
11942 * This function is required for cfg80211_ops API.
11943 * It is used to delete the key information
11944 * Underlying hardware implementation does not have API to delete the
11945 * encryption key. It is automatically deleted when the peer is
11946 * removed. Hence this function currently does nothing.
11947 * Future implementation may interprete delete key operation to
11948 * replacing the key with a random junk value, effectively making it
11949 * useless.
11950 *
11951 * Return: status code, always 0.
11952 */
11953
11954static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11955 struct net_device *ndev,
11956 u8 key_index,
11957 bool pairwise, const u8 *mac_addr)
11958{
11959 EXIT();
11960 return 0;
11961}
11962
11963/**
11964 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11965 * @wiphy: Pointer to wiphy structure.
11966 * @dev: Pointer to net_device structure.
11967 * @key_index: key index
11968 * @pairwise: pairwise
11969 * @mac_addr: mac address
11970 *
11971 * This is the cfg80211 delete key handler function which invokes
11972 * the internal function @__wlan_hdd_cfg80211_del_key with
11973 * SSR protection.
11974 *
11975 * Return: 0 for success, error number on failure.
11976 */
11977static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11978 struct net_device *dev,
11979 u8 key_index,
11980 bool pairwise, const u8 *mac_addr)
11981{
11982 int ret;
11983
11984 cds_ssr_protect(__func__);
11985 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11986 pairwise, mac_addr);
11987 cds_ssr_unprotect(__func__);
11988
11989 return ret;
11990}
11991
11992/*
11993 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11994 * This function is used to set the default tx key index
11995 */
11996static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11997 struct net_device *ndev,
11998 u8 key_index,
11999 bool unicast, bool multicast)
12000{
12001 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12002 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12003 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12004 hdd_context_t *pHddCtx;
12005 int status;
12006
12007 ENTER();
12008
Anurag Chouhan6d760662016-02-20 16:05:43 +053012009 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012010 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012011 return -EINVAL;
12012 }
12013
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012014 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12015 hdd_err("invalid session id: %d", pAdapter->sessionId);
12016 return -EINVAL;
12017 }
12018
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012019 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012020 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12021 pAdapter->sessionId, key_index));
12022
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012023 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012024 hdd_device_mode_to_string(pAdapter->device_mode),
12025 pAdapter->device_mode, key_index);
12026
12027 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012028 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012029 return -EINVAL;
12030 }
12031
12032 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12033 status = wlan_hdd_validate_context(pHddCtx);
12034
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012035 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012036 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012037
Krunal Sonib4326f22016-03-10 13:05:51 -080012038 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12039 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12041 pHddStaCtx->conn_info.ucEncryptionType) &&
12042 (eCSR_ENCRYPT_TYPE_AES !=
12043 pHddStaCtx->conn_info.ucEncryptionType)) {
12044 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012045 * then update the default key index
12046 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012047
12048 tCsrRoamSetKey setKey;
12049 uint32_t roamId = 0xFF;
12050 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12051
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012052 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012053
12054 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012055 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056 setKey.keyId = key_index;
12057 setKey.keyLength = Keys->KeyLength[key_index];
12058
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012059 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012060 &Keys->KeyMaterial[key_index][0],
12061 Keys->KeyLength[key_index]);
12062
12063 setKey.keyDirection = eSIR_TX_RX;
12064
Anurag Chouhanc5548422016-02-24 18:33:27 +053012065 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012066 &pHddStaCtx->conn_info.bssId);
12067
12068 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12069 pWextState->roamProfile.EncryptionType.
12070 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012071 /* In the case of dynamic wep
12072 * supplicant hardcodes DWEP type to
12073 * eCSR_ENCRYPT_TYPE_WEP104 even
12074 * though ap is configured for WEP-40
12075 * encryption. In this canse the key
12076 * length is 5 but the encryption type
12077 * is 104 hence checking the key
12078 * lenght(5) and encryption type(104)
12079 * and switching encryption type to 40
12080 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 pWextState->roamProfile.EncryptionType.
12082 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12083 pWextState->roamProfile.mcEncryptionType.
12084 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12085 }
12086
12087 setKey.encType =
12088 pWextState->roamProfile.EncryptionType.
12089 encryptionType[0];
12090
12091 /* Issue set key request */
12092 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12093 pAdapter->sessionId, &setKey,
12094 &roamId);
12095
12096 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012097 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 status);
12099 return -EINVAL;
12100 }
12101 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012102 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012103 /* In SoftAp mode setting key direction for default mode */
12104 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12105 pWextState->roamProfile.EncryptionType.encryptionType[0])
12106 && (eCSR_ENCRYPT_TYPE_AES !=
12107 pWextState->roamProfile.EncryptionType.
12108 encryptionType[0])) {
12109 /* Saving key direction for default key index to TX default */
12110 hdd_ap_ctx_t *pAPCtx =
12111 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12112 pAPCtx->wepKey[key_index].keyDirection =
12113 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012114 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012115 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012116 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 }
12118 }
12119
12120 EXIT();
12121 return status;
12122}
12123
12124static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12125 struct net_device *ndev,
12126 u8 key_index,
12127 bool unicast, bool multicast)
12128{
12129 int ret;
12130 cds_ssr_protect(__func__);
12131 ret =
12132 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12133 multicast);
12134 cds_ssr_unprotect(__func__);
12135
12136 return ret;
12137}
12138
Abhishek Singhc9941602016-08-09 16:06:22 +053012139/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012140 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12141 * interface that BSS might have been lost.
12142 * @pAdapter: adaptor
12143 * @bssid: bssid which might have been lost
12144 *
12145 * Return: bss which is unlinked from kernel cache
12146 */
12147struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12148 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012149{
12150 struct net_device *dev = pAdapter->dev;
12151 struct wireless_dev *wdev = dev->ieee80211_ptr;
12152 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012153 struct cfg80211_bss *bss = NULL;
12154
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012155 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012156 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012157 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012158 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012159 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012160 hdd_info("cfg80211_unlink_bss called for BSSID "
12161 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012162 cfg80211_unlink_bss(wiphy, bss);
12163 }
12164 return bss;
12165}
12166
Abhishek Singhc9941602016-08-09 16:06:22 +053012167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012168/**
12169 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12170 * @pAdapter: Pointer to adapter
12171 * @bss_desc: Pointer to bss descriptor
12172 *
12173 * This function is used to inform the BSS details to nl80211 interface.
12174 *
12175 * Return: struct cfg80211_bss pointer
12176 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012177struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12178 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012179{
12180 /*
12181 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12182 * already exists in bss data base of cfg80211 for that particular BSS
12183 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12184 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12185 * As of now there is no possibility to get the mgmt(probe response)
12186 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12187 * and passing to cfg80211_inform_bss_frame.
12188 */
12189 struct net_device *dev = pAdapter->dev;
12190 struct wireless_dev *wdev = dev->ieee80211_ptr;
12191 struct wiphy *wiphy = wdev->wiphy;
12192 int chan_no = bss_desc->channelId;
12193#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12194 qcom_ie_age *qie_age = NULL;
12195 int ie_length =
12196 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12197#else
12198 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12199#endif
12200 const char *ie =
12201 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12202 unsigned int freq;
12203 struct ieee80211_channel *chan;
12204 struct ieee80211_mgmt *mgmt = NULL;
12205 struct cfg80211_bss *bss_status = NULL;
12206 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12207 int rssi = 0;
12208 hdd_context_t *pHddCtx;
12209 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012210 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012211 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012212
12213 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12214 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012215 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012216 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012217
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012218 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012219 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012221 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012222 return NULL;
12223 }
12224
12225 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12226
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012227 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012228 * Instead it wants a monotonic increasing value
12229 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012230 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012231 mgmt->u.probe_resp.timestamp =
12232 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233
12234 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12235 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12236
12237#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12238 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12239 /* Assuming this is the last IE, copy at the end */
12240 ie_length -= sizeof(qcom_ie_age);
12241 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12242 qie_age->element_id = QCOM_VENDOR_IE_ID;
12243 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12244 qie_age->oui_1 = QCOM_OUI1;
12245 qie_age->oui_2 = QCOM_OUI2;
12246 qie_age->oui_3 = QCOM_OUI3;
12247 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012248 /*
12249 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12250 * all bss related timestamp is in units of ms. Due to this when scan
12251 * results are sent to lowi the scan age is high.To address this,
12252 * send age in units of 1/10 ms.
12253 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012254 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012255 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012256 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012257 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12258 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012259 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12260 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012261#endif
12262
12263 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12264 if (bss_desc->fProbeRsp) {
12265 mgmt->frame_control |=
12266 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12267 } else {
12268 mgmt->frame_control |=
12269 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12270 }
12271
12272 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012273 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274 freq =
12275 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012276 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012277 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012278 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012279 freq =
12280 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012281 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012283 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012284 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285 return NULL;
12286 }
12287
12288 chan = __ieee80211_get_channel(wiphy, freq);
12289 /* When the band is changed on the fly using the GUI, three things are done
12290 * 1. scan abort
12291 * 2. flush scan results from cache
12292 * 3. update the band with the new band user specified (refer to the
12293 * hdd_set_band_helper function) as part of the scan abort, message will be
12294 * queued to PE and we proceed with flushing and changinh the band.
12295 * PE will stop the scanning further and report back the results what ever
12296 * it had till now by calling the call back function.
12297 * if the time between update band and scandone call back is sufficient
12298 * enough the band change reflects in SME, SME validates the channels
12299 * and discards the channels correponding to previous band and calls back
12300 * with zero bss results. but if the time between band update and scan done
12301 * callback is very small then band change will not reflect in SME and SME
12302 * reports to HDD all the channels correponding to previous band.this is due
12303 * to race condition.but those channels are invalid to the new band and so
12304 * this function __ieee80211_get_channel will return NULL.Each time we
12305 * report scan result with this pointer null warning kernel trace is printed.
12306 * if the scan results contain large number of APs continuosly kernel
12307 * warning trace is printed and it will lead to apps watch dog bark.
12308 * So drop the bss and continue to next bss.
12309 */
12310 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012311 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12312 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012313 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012314 return NULL;
12315 }
12316
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012317 /* Based on .ini configuration, raw rssi can be reported for bss.
12318 * Raw rssi is typically used for estimating power.
12319 */
12320
12321 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12322 bss_desc->rssi;
12323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012325 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012326
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012327 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012328 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012329 (int)(rssi / 100),
12330 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331
12332 bss_status =
12333 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
12334 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012335 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012336 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012337 return bss_status;
12338}
12339
12340/**
12341 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12342 * @pAdapter: Pointer to adapter
12343 * @pRoamInfo: Pointer to roam info
12344 *
12345 * This function is used to update the BSS data base of CFG8011
12346 *
12347 * Return: struct cfg80211_bss pointer
12348 */
12349struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12350 tCsrRoamInfo *pRoamInfo)
12351{
12352 tCsrRoamConnectedProfile roamProfile;
12353 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12354 struct cfg80211_bss *bss = NULL;
12355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12357 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12358
12359 if (NULL != roamProfile.pBssDesc) {
12360 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12361 roamProfile.pBssDesc);
12362
12363 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012364 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012365
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012366 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012367 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012368 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012369 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012370 return bss;
12371}
12372/**
12373 * wlan_hdd_cfg80211_update_bss() - update bss
12374 * @wiphy: Pointer to wiphy
12375 * @pAdapter: Pointer to adapter
12376 * @scan_time: scan request timestamp
12377 *
12378 * Return: zero if success, non-zero otherwise
12379 */
12380int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12381 hdd_adapter_t *pAdapter,
12382 uint32_t scan_time)
12383{
12384 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12385 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012386 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 tScanResultHandle pResult;
12388 struct cfg80211_bss *bss_status = NULL;
12389 hdd_context_t *pHddCtx;
12390 int ret;
12391
12392 ENTER();
12393
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012394 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12395 hdd_err("invalid session id: %d", pAdapter->sessionId);
12396 return -EINVAL;
12397 }
12398
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012399 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12401 NO_SESSION, pAdapter->sessionId));
12402
12403 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12404 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012405 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407
12408 /* start getting scan results and populate cgf80211 BSS database */
12409 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12410
12411 /* no scan results */
12412 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012413 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012414 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012415 }
12416
12417 pScanResult = sme_scan_result_get_first(hHal, pResult);
12418
12419 while (pScanResult) {
12420 /*
12421 * - cfg80211_inform_bss() is not updating ie field of bss
12422 * entry if entry already exists in bss data base of cfg80211
12423 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12424 * to update thebss entry instead of cfg80211_inform_bss,
12425 * But this call expects mgmt packet as input. As of now
12426 * there is no possibility to get the mgmt(probe response)
12427 * frame from PE, converting bss_desc to
12428 * ieee80211_mgmt(probe response) and passing to c
12429 * fg80211_inform_bss_frame.
12430 * - Update BSS only if beacon timestamp is later than
12431 * scan request timestamp.
12432 */
12433 if ((scan_time == 0) ||
12434 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012435 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 bss_status =
12437 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12438 &pScanResult->BssDescriptor);
12439
12440 if (NULL == bss_status) {
12441 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12442 } else {
12443 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012445 bss_status);
12446 }
12447 } else {
12448 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12449 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12450 }
12451 pScanResult = sme_scan_result_get_next(hHal, pResult);
12452 }
12453
12454 sme_scan_result_purge(hHal, pResult);
12455 /*
12456 * For SAP mode, scan is invoked by hostapd during SAP start
12457 * if hostapd is restarted, we need to flush previous scan
12458 * result so that it will reflect environment change
12459 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012460 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012461#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12462 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12463#endif
12464 )
12465 sme_scan_flush_result(hHal);
12466
12467 EXIT();
12468 return 0;
12469}
12470
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471/**
12472 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12473 * @pAdapter: Pointer to adapter
12474 * @pRoamInfo: Pointer to roam info
12475 * @index: Index
12476 * @preauth: Preauth flag
12477 *
12478 * This function is used to notify the supplicant of a new PMKSA candidate.
12479 *
12480 * Return: 0 for success, non-zero for failure
12481 */
12482int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12483 tCsrRoamInfo *pRoamInfo,
12484 int index, bool preauth)
12485{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 struct net_device *dev = pAdapter->dev;
12487 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12488
12489 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012490 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012491
12492 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012493 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012494 return -EINVAL;
12495 }
12496
12497 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012498 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012499 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12500 cfg80211_pmksa_candidate_notify(dev, index,
12501 pRoamInfo->bssid.bytes,
12502 preauth, GFP_KERNEL);
12503 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012504 return 0;
12505}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506
12507#ifdef FEATURE_WLAN_LFR_METRICS
12508/**
12509 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12510 * @pAdapter: Pointer to adapter
12511 * @pRoamInfo: Pointer to roam info
12512 *
12513 * 802.11r/LFR metrics reporting function to report preauth initiation
12514 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012515 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012516 */
12517#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012518QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 tCsrRoamInfo *pRoamInfo)
12520{
12521 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12522 union iwreq_data wrqu;
12523
12524 ENTER();
12525
12526 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012527 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012528 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012529 }
12530
12531 /* create the event */
12532 memset(&wrqu, 0, sizeof(wrqu));
12533 memset(metrics_notification, 0, sizeof(metrics_notification));
12534
12535 wrqu.data.pointer = metrics_notification;
12536 wrqu.data.length = scnprintf(metrics_notification,
12537 sizeof(metrics_notification),
12538 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12539 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12540
12541 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12542 metrics_notification);
12543
12544 EXIT();
12545
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012546 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012547}
12548
12549/**
12550 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12551 * @pAdapter: Pointer to adapter
12552 * @pRoamInfo: Pointer to roam info
12553 * @preauth_status: Preauth status
12554 *
12555 * 802.11r/LFR metrics reporting function to report handover initiation
12556 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012557 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012558 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012559QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012560wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12561 tCsrRoamInfo *pRoamInfo,
12562 bool preauth_status)
12563{
12564 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12565 union iwreq_data wrqu;
12566
12567 ENTER();
12568
12569 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012570 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012571 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 }
12573
12574 /* create the event */
12575 memset(&wrqu, 0, sizeof(wrqu));
12576 memset(metrics_notification, 0, sizeof(metrics_notification));
12577
12578 scnprintf(metrics_notification, sizeof(metrics_notification),
12579 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12580 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12581
12582 if (1 == preauth_status)
12583 strlcat(metrics_notification, " true",
12584 sizeof(metrics_notification));
12585 else
12586 strlcat(metrics_notification, " false",
12587 sizeof(metrics_notification));
12588
12589 wrqu.data.pointer = metrics_notification;
12590 wrqu.data.length = strlen(metrics_notification);
12591
12592 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12593 metrics_notification);
12594
12595 EXIT();
12596
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012597 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598}
12599
12600/**
12601 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12602 * @pAdapter: Pointer to adapter
12603 * @pRoamInfo: Pointer to roam info
12604 *
12605 * 802.11r/LFR metrics reporting function to report handover initiation
12606 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012607 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012608 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012609QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610 tCsrRoamInfo *pRoamInfo)
12611{
12612 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12613 union iwreq_data wrqu;
12614
12615 ENTER();
12616
12617 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012618 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012619 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620 }
12621
12622 /* create the event */
12623 memset(&wrqu, 0, sizeof(wrqu));
12624 memset(metrics_notification, 0, sizeof(metrics_notification));
12625
12626 wrqu.data.pointer = metrics_notification;
12627 wrqu.data.length = scnprintf(metrics_notification,
12628 sizeof(metrics_notification),
12629 "QCOM: LFR_PREAUTH_HANDOVER "
12630 MAC_ADDRESS_STR,
12631 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12632
12633 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12634 metrics_notification);
12635
12636 EXIT();
12637
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012638 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012639}
12640#endif
12641
12642/**
12643 * hdd_select_cbmode() - select channel bonding mode
12644 * @pAdapter: Pointer to adapter
12645 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012646 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012647 *
12648 * Return: none
12649 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012650void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12651 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012652{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012653 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012654 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012655 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012656
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012657 /*
12658 * CDS api expects secondary channel for calculating
12659 * the channel params
12660 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012661 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012662 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12663 if (operationChannel >= 1 && operationChannel <= 5)
12664 sec_ch = operationChannel + 4;
12665 else if (operationChannel >= 6 && operationChannel <= 13)
12666 sec_ch = operationChannel - 4;
12667 }
12668
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012669 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012670 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012671
12672 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012673 eHddDot11Mode hdd_dot11_mode;
12674 uint8_t iniDot11Mode =
12675 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12676
12677 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12678 switch (iniDot11Mode) {
12679 case eHDD_DOT11_MODE_AUTO:
12680 case eHDD_DOT11_MODE_11ac:
12681 case eHDD_DOT11_MODE_11ac_ONLY:
12682 if (sme_is_feature_supported_by_fw(DOT11AC))
12683 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12684 else
12685 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12686 break;
12687 case eHDD_DOT11_MODE_11n:
12688 case eHDD_DOT11_MODE_11n_ONLY:
12689 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12690 break;
12691 default:
12692 hdd_dot11_mode = iniDot11Mode;
12693 break;
12694 }
12695 ch_info->channel_width = ch_params->ch_width;
12696 ch_info->phy_mode =
12697 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012698 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012699 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012700 hdd_info("ch_info width %d, phymode %d channel %d",
12701 ch_info->channel_width, ch_info->phy_mode,
12702 ch_info->channel);
12703 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012704}
12705
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012706/**
12707 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12708 * @adapter: STA adapter
12709 * @roam_profile: STA roam profile
12710 *
12711 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12712 *
12713 * Return: false if sta-sap conc is not allowed, else return true
12714 */
12715static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12716 tCsrRoamProfile *roam_profile)
12717{
12718 hdd_context_t *hdd_ctx;
12719 hdd_adapter_t *ap_adapter;
12720 hdd_ap_ctx_t *hdd_ap_ctx;
12721 hdd_hostapd_state_t *hostapd_state;
12722 uint8_t channel = 0;
12723 QDF_STATUS status;
12724
12725 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12726 if (!hdd_ctx) {
12727 hdd_err("HDD context is NULL");
12728 return true;
12729 }
12730
12731 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12732 /* probably no sap running, no handling required */
12733 if (ap_adapter == NULL)
12734 return true;
12735
12736 /*
12737 * sap is not in started state, so it is fine to go ahead with sta.
12738 * if sap is currently doing CAC then don't allow sta to go further.
12739 */
12740 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12741 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12742 return true;
12743
12744 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12745 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12746 return false;
12747 }
12748
12749 /*
12750 * log and return error, if we allow STA to go through, we don't
12751 * know what is going to happen better stop sta connection
12752 */
12753 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12754 if (NULL == hdd_ap_ctx) {
12755 hdd_err("AP context not found");
12756 return false;
12757 }
12758
12759 /* sap is on non-dfs channel, nothing to handle */
12760 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12761 hdd_info("sap is on non-dfs channel, sta is allowed");
12762 return true;
12763 }
12764 /*
12765 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012766 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012767 */
12768 status = cds_get_channel_from_scan_result(adapter,
12769 roam_profile, &channel);
12770
Nitesh Shah59774522016-09-16 15:14:21 +053012771 /*
12772 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12773 * channels for roaming case.
12774 */
12775 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12776 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12777 return true;
12778 }
12779
12780 /*
12781 * If channel is 0 or DFS then better to call pcl and find out the
12782 * best channel. If channel is non-dfs 5 GHz then better move SAP
12783 * to STA's channel to make scc, so we have room for 3port MCC
12784 * scenario.
12785 */
12786 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012787 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12788 true);
12789
12790 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12791 qdf_event_reset(&hostapd_state->qdf_event);
12792 status = wlansap_set_channel_change_with_csa(
12793 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12794 hdd_ap_ctx->sapConfig.ch_width_orig);
12795
12796 if (QDF_STATUS_SUCCESS != status) {
12797 hdd_err("Set channel with CSA IE failed, can't allow STA");
12798 return false;
12799 }
12800
12801 /*
12802 * wait here for SAP to finish the channel switch. When channel
12803 * switch happens, SAP sends few beacons with CSA_IE. After
12804 * successfully Transmission of those beacons, it will move its
12805 * state from started to disconnected and move to new channel.
12806 * once it moves to new channel, sap again moves its state
12807 * machine from disconnected to started and set this event.
12808 * wait for 10 secs to finish this.
12809 */
12810 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12811 if (!QDF_IS_STATUS_SUCCESS(status)) {
12812 hdd_err("wait for qdf_event failed, STA not allowed!!");
12813 return false;
12814 }
12815
12816 return true;
12817}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012818
Krunal Soni31949422016-07-29 17:17:53 -070012819/**
12820 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012821 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012822 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823 * @ssid_len: Length of ssid
12824 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012825 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012827 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012828 *
12829 * This function is used to start the association process
12830 *
12831 * Return: 0 for success, non-zero for failure
12832 */
Krunal Soni31949422016-07-29 17:17:53 -070012833static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012835 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012836 u8 operatingChannel,
12837 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012838{
12839 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012840 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012841 hdd_wext_state_t *pWextState;
12842 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012843 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012844 uint32_t roamId;
12845 tCsrRoamProfile *pRoamProfile;
12846 eCsrAuthType RSNAuthType;
12847 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012848 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012849
12850 ENTER();
12851
12852 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12853 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012854 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012855
12856 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012857 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012858 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012859
12860 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012861 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012862 status = -EINVAL;
12863 goto ret_status;
12864 }
12865
12866 if (true == cds_is_connection_in_progress()) {
12867 hdd_err("Connection refused: conn in progress");
12868 status = -EINVAL;
12869 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870 }
12871
12872 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012873 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12874 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012875
12876 if (pRoamProfile) {
12877 hdd_station_ctx_t *pHddStaCtx;
12878 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12879
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012880 /* Restart the opportunistic timer
12881 *
12882 * If hw_mode_change_in_progress is true, then wait
12883 * till firmware sends the callback for hw_mode change.
12884 *
12885 * Else set connect_in_progress as true and proceed.
12886 */
12887 cds_restart_opportunistic_timer(false);
12888 if (cds_is_hw_mode_change_in_progress()) {
12889 status = qdf_wait_for_connection_update();
12890 if (!QDF_IS_STATUS_SUCCESS(status)) {
12891 hdd_err("qdf wait for event failed!!");
12892 status = -EINVAL;
12893 goto ret_status;
12894 }
12895 }
12896 cds_set_connection_in_progress(true);
12897
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898 if (HDD_WMM_USER_MODE_NO_QOS ==
12899 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12900 /*QoS not enabled in cfg file */
12901 pRoamProfile->uapsd_mask = 0;
12902 } else {
12903 /*QoS enabled, update uapsd mask from cfg file */
12904 pRoamProfile->uapsd_mask =
12905 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12906 }
12907
12908 pRoamProfile->SSIDs.numOfSSIDs = 1;
12909 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012910 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012912 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012913 ssid, ssid_len);
12914
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012915 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012916 /* cleanup bssid hint */
12917 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12918 QDF_MAC_ADDR_SIZE);
12919 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12920 QDF_MAC_ADDR_SIZE);
12921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012922 if (bssid) {
12923 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012924 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012925 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012926 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012927 /*
12928 * Save BSSID in seperate variable as
12929 * pRoamProfile's BSSID is getting zeroed out in the
12930 * association process. In case of join failure
12931 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012932 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012933 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012934 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012935 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012936 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012937 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12938 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012939 /*
12940 * Save BSSID in a separate variable as
12941 * pRoamProfile's BSSID is getting zeroed out in the
12942 * association process. In case of join failure
12943 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012944 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012945 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012946 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012947 hdd_info("bssid_hint is given by upper layer %pM",
12948 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 }
12950
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012951 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012952 pRoamProfile->SSIDs.SSIDList->SSID.length,
12953 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12954 operatingChannel);
12955
12956 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12957 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012959 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12960 }
12961#ifdef FEATURE_WLAN_WAPI
12962 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012963 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012964 switch (pAdapter->wapi_info.wapiAuthMode) {
12965 case WAPI_AUTH_MODE_PSK:
12966 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012967 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012968 pAdapter->wapi_info.wapiAuthMode);
12969 pRoamProfile->AuthType.authType[0] =
12970 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12971 break;
12972 }
12973 case WAPI_AUTH_MODE_CERT:
12974 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012975 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012976 pAdapter->wapi_info.wapiAuthMode);
12977 pRoamProfile->AuthType.authType[0] =
12978 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12979 break;
12980 }
12981 } /* End of switch */
12982 if (pAdapter->wapi_info.wapiAuthMode ==
12983 WAPI_AUTH_MODE_PSK
12984 || pAdapter->wapi_info.wapiAuthMode ==
12985 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012986 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987 pRoamProfile->AuthType.numEntries = 1;
12988 pRoamProfile->EncryptionType.numEntries = 1;
12989 pRoamProfile->EncryptionType.encryptionType[0] =
12990 eCSR_ENCRYPT_TYPE_WPI;
12991 pRoamProfile->mcEncryptionType.numEntries = 1;
12992 pRoamProfile->mcEncryptionType.
12993 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12994 }
12995 }
Krunal Soni31949422016-07-29 17:17:53 -070012996#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997#ifdef WLAN_FEATURE_GTK_OFFLOAD
12998 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080012999 if ((QDF_STA_MODE == pAdapter->device_mode) ||
13000 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
13002 sizeof(tSirGtkOffloadParams));
13003 pHddStaCtx->gtkOffloadReqParams.ulFlags =
13004 GTK_OFFLOAD_DISABLE;
13005 }
13006#endif
13007 pRoamProfile->csrPersona = pAdapter->device_mode;
13008
13009 if (operatingChannel) {
13010 pRoamProfile->ChannelInfo.ChannelList =
13011 &operatingChannel;
13012 pRoamProfile->ChannelInfo.numOfChannels = 1;
13013 } else {
13014 pRoamProfile->ChannelInfo.ChannelList = NULL;
13015 pRoamProfile->ChannelInfo.numOfChannels = 0;
13016 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013017 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013018 && operatingChannel) {
13019 /*
13020 * Need to post the IBSS power save parameters
13021 * to WMA. WMA will configure this parameters
13022 * to firmware if power save is enabled by the
13023 * firmware.
13024 */
13025 status = hdd_set_ibss_power_save_params(pAdapter);
13026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013027 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013028 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013029 status = -EINVAL;
13030 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013031 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013032 pRoamProfile->ch_params.ch_width =
13033 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013034 /*
13035 * In IBSS mode while operating in 2.4 GHz,
13036 * the device supports only 20 MHz.
13037 */
13038 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13039 pRoamProfile->ch_params.ch_width =
13040 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013041 hdd_select_cbmode(pAdapter, operatingChannel,
13042 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013043 }
Abhishek Singh99bce862016-06-20 15:10:51 +053013044 /*
13045 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13046 * or pmf=2 is an explicit configuration in the supplicant
13047 * configuration, drop the connection request.
13048 */
13049 if (pWextState->roamProfile.MFPEnabled &&
13050 !(pWextState->roamProfile.MFPRequired ||
13051 pWextState->roamProfile.MFPCapable)) {
13052 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13053 pWextState->roamProfile.MFPEnabled,
13054 pWextState->roamProfile.MFPRequired,
13055 pWextState->roamProfile.MFPCapable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013057 status = -EINVAL;
13058 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013059 }
13060
Krunal Soni31949422016-07-29 17:17:53 -070013061 /*
13062 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013064 * enhancements, the supplicant is not issuing the scan command
13065 * now. So the unicast frames which are sent from the host are
13066 * not having the additional IEs. If it is P2P CLIENT and there
13067 * is no additional IE present in roamProfile, then use the
13068 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013069 */
13070
Krunal Sonib4326f22016-03-10 13:05:51 -080013071 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013072 (!pRoamProfile->pAddIEScan)) {
13073 pRoamProfile->pAddIEScan =
13074 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13075 pRoamProfile->nAddIEScanLength =
13076 pAdapter->scan_info.scanAddIE.length;
13077 }
13078 /*
13079 * When policy manager is enabled from ini file, we shouldn't
13080 * check for other concurrency rules.
13081 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013082 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013083 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013084 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013085 pAdapter, pRoamProfile, &roamId)) {
13086 status = 0;
13087 goto conn_failure;
13088 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013089 }
13090
Krunal Soni3091bcc2016-06-23 12:28:21 -070013091 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013092 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13093 pRoamProfile))) {
13094 hdd_err("sap-sta conc will fail, can't allow sta");
13095 hdd_conn_set_connection_state(pAdapter,
13096 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013097 status = -ENOMEM;
13098 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013099 }
13100
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013101 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 if (!sme_config) {
13103 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013104 hdd_conn_set_connection_state(pAdapter,
13105 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013106 status = -ENOMEM;
13107 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013108 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 sme_get_config_param(pHddCtx->hHal, sme_config);
13110 /* These values are not sessionized. So, any change in these SME
13111 * configs on an older or parallel interface will affect the
13112 * cb mode. So, restoring the default INI params before starting
13113 * interfaces such as sta, cli etc.,
13114 */
13115 sme_config->csrConfig.channelBondingMode5GHz =
13116 pHddCtx->config->nChannelBondingMode5GHz;
13117 sme_config->csrConfig.channelBondingMode24GHz =
13118 pHddCtx->config->nChannelBondingMode24GHz;
13119 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013120 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013121 /*
13122 * Change conn_state to connecting before sme_roam_connect(),
13123 * because sme_roam_connect() has a direct path to call
13124 * hdd_sme_roam_callback(), which will change the conn_state
13125 * If direct path, conn_state will be accordingly changed to
13126 * NotConnected or Associated by either
13127 * hdd_association_completion_handler() or
13128 * hdd_dis_connect_handler() in sme_RoamCallback()if
13129 * sme_RomConnect is to be queued,
13130 * Connecting state will remain until it is completed.
13131 *
13132 * If connection state is not changed, connection state will
13133 * remain in eConnectionState_NotConnected state.
13134 * In hdd_association_completion_handler, "hddDisconInProgress"
13135 * is set to true if conn state is
13136 * eConnectionState_NotConnected.
13137 * If "hddDisconInProgress" is set to true then cfg80211 layer
13138 * is not informed of connect result indication which
13139 * is an issue.
13140 */
13141 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013142 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013143 hdd_conn_set_connection_state(pAdapter,
13144 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013145
Komal Seelama89be8d2016-09-29 11:09:26 +053013146 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13147 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013148 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013149 pAdapter->sessionId, pRoamProfile,
13150 &roamId);
13151
Rajeev Kumard31e1542017-01-13 14:37:42 -080013152 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013153 (QDF_STA_MODE == pAdapter->device_mode ||
13154 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013155 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013156 "qdf_status %d. -> NotConnected",
13157 pAdapter->sessionId, qdf_status);
13158 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013159 /* change back to NotAssociated */
13160 hdd_conn_set_connection_state(pAdapter,
13161 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013162 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13163 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013164 }
13165
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013166 /* Reset connect_in_progress */
13167 cds_set_connection_in_progress(false);
13168
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013169 pRoamProfile->ChannelInfo.ChannelList = NULL;
13170 pRoamProfile->ChannelInfo.numOfChannels = 0;
13171
Nitesh Shah044fd672016-10-13 18:53:25 +053013172 if ((QDF_STA_MODE == pAdapter->device_mode)
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013173 && wma_is_current_hwmode_dbs() &&
13174 !wma_is_hw_dbs_2x2_capable()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013175 cds_get_channel_from_scan_result(pAdapter,
13176 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013177 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013178 if (channel)
13179 cds_checkn_update_hw_mode_single_mac_mode
13180 (channel);
13181 }
13182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013184 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013185 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013186 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013187 goto ret_status;
13188
13189conn_failure:
13190 /* Reset connect_in_progress */
13191 cds_set_connection_in_progress(false);
13192
13193ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 EXIT();
13195 return status;
13196}
13197
13198/**
13199 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13200 * @pAdapter: Pointer to adapter
13201 * @auth_type: Auth type
13202 *
13203 * This function is used to set the authentication type (OPEN/SHARED).
13204 *
13205 * Return: 0 for success, non-zero for failure
13206 */
13207static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13208 enum nl80211_auth_type auth_type)
13209{
13210 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13211 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013213 /*set authentication type */
13214 switch (auth_type) {
13215 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013216 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13218 break;
13219
13220 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013221 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013222 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13224 break;
13225
13226 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013227 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013228 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13229 break;
13230#ifdef FEATURE_WLAN_ESE
13231 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013232 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13234 break;
13235#endif
13236
13237 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013238 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013239 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13240 return -EINVAL;
13241 }
13242
13243 pWextState->roamProfile.AuthType.authType[0] =
13244 pHddStaCtx->conn_info.authType;
13245 return 0;
13246}
13247
13248/**
13249 * wlan_hdd_set_akm_suite() - set key management type
13250 * @pAdapter: Pointer to adapter
13251 * @key_mgmt: Key management type
13252 *
13253 * This function is used to set the key mgmt type(PSK/8021x).
13254 *
13255 * Return: 0 for success, non-zero for failure
13256 */
13257static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13258{
13259 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013261#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13262#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13263 /*set key mgmt type */
13264 switch (key_mgmt) {
13265 case WLAN_AKM_SUITE_PSK:
13266 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013267 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013268 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13270 break;
13271
13272 case WLAN_AKM_SUITE_8021X_SHA256:
13273 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013275 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013276 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13277 break;
13278#ifdef FEATURE_WLAN_ESE
13279#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13280#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13281 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013282 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013283 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13284 break;
13285#endif
13286#ifndef WLAN_AKM_SUITE_OSEN
13287#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13288#endif
13289 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013290 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13292 break;
13293
13294 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013295 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296 return -EINVAL;
13297
13298 }
13299 return 0;
13300}
13301
13302/**
13303 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13304 * @pAdapter: Pointer to adapter
13305 * @cipher: Cipher type
13306 * @ucast: Unicast flag
13307 *
13308 * This function is used to set the encryption type
13309 * (NONE/WEP40/WEP104/TKIP/CCMP).
13310 *
13311 * Return: 0 for success, non-zero for failure
13312 */
13313static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13314 u32 cipher, bool ucast)
13315{
13316 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13317 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13318 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013320 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013321 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013322 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13323 } else {
13324
13325 /*set encryption method */
13326 switch (cipher) {
13327 case IW_AUTH_CIPHER_NONE:
13328 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13329 break;
13330
13331 case WLAN_CIPHER_SUITE_WEP40:
13332 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13333 break;
13334
13335 case WLAN_CIPHER_SUITE_WEP104:
13336 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13337 break;
13338
13339 case WLAN_CIPHER_SUITE_TKIP:
13340 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13341 break;
13342
13343 case WLAN_CIPHER_SUITE_CCMP:
13344 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13345 break;
13346#ifdef FEATURE_WLAN_WAPI
13347 case WLAN_CIPHER_SUITE_SMS4:
13348 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13349 break;
13350#endif
13351
13352#ifdef FEATURE_WLAN_ESE
13353 case WLAN_CIPHER_SUITE_KRK:
13354 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13355 break;
13356#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13357 case WLAN_CIPHER_SUITE_BTK:
13358 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13359 break;
13360#endif
13361#endif
13362 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013363 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 return -EOPNOTSUPP;
13365 }
13366 }
13367
13368 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013369 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13371 pWextState->roamProfile.EncryptionType.numEntries = 1;
13372 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13373 encryptionType;
13374 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013375 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013376 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13377 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13378 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13379 encryptionType;
13380 }
13381
13382 return 0;
13383}
13384
13385/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013386 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13387 * @wext_state: Pointer to wext state
13388 * @gen_ie: Pointer to IE data
13389 * @len: length of IE data
13390 *
13391 * Return: 0 for success, non-zero for failure
13392 */
13393static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13394 const uint8_t *gen_ie, uint16_t len)
13395{
13396 uint16_t cur_add_ie_len =
13397 wext_state->assocAddIE.length;
13398
13399 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13400 (wext_state->assocAddIE.length + len)) {
13401 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13402 QDF_ASSERT(0);
13403 return -ENOMEM;
13404 }
13405 memcpy(wext_state->assocAddIE.addIEdata +
13406 cur_add_ie_len, gen_ie, len);
13407 wext_state->assocAddIE.length += len;
13408
13409 wext_state->roamProfile.pAddIEAssoc =
13410 wext_state->assocAddIE.addIEdata;
13411 wext_state->roamProfile.nAddIEAssocLength =
13412 wext_state->assocAddIE.length;
13413 return 0;
13414}
13415
13416/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417 * wlan_hdd_cfg80211_set_ie() - set IEs
13418 * @pAdapter: Pointer to adapter
13419 * @ie: Pointer ot ie
13420 * @ie: IE length
13421 *
13422 * Return: 0 for success, non-zero for failure
13423 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013424static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 size_t ie_len)
13426{
13427 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13428 const uint8_t *genie = ie;
13429 uint16_t remLen = ie_len;
13430#ifdef FEATURE_WLAN_WAPI
13431 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13432 u16 *tmp;
13433 uint16_t akmsuiteCount;
13434 int *akmlist;
13435#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013436 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437
13438 /* clear previous assocAddIE */
13439 pWextState->assocAddIE.length = 0;
13440 pWextState->roamProfile.bWPSAssociation = false;
13441 pWextState->roamProfile.bOSENAssociation = false;
13442
13443 while (remLen >= 2) {
13444 uint16_t eLen = 0;
13445 uint8_t elementId;
13446 elementId = *genie++;
13447 eLen = *genie++;
13448 remLen -= 2;
13449
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013450 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451
13452 switch (elementId) {
13453 case DOT11F_EID_WPA:
13454 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 -070013455 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 return -EINVAL;
13457 } else if (0 ==
13458 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13459 uint16_t curAddIELen =
13460 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013461 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013462
13463 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13464 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013465 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013466 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013467 return -ENOMEM;
13468 }
13469 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13470 memcpy(pWextState->assocAddIE.addIEdata +
13471 curAddIELen, genie - 2, eLen + 2);
13472 pWextState->assocAddIE.length += eLen + 2;
13473
13474 pWextState->roamProfile.bWPSAssociation = true;
13475 pWextState->roamProfile.pAddIEAssoc =
13476 pWextState->assocAddIE.addIEdata;
13477 pWextState->roamProfile.nAddIEAssocLength =
13478 pWextState->assocAddIE.length;
13479 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013480 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481 memset(pWextState->WPARSNIE, 0,
13482 MAX_WPA_RSN_IE_LEN);
13483 memcpy(pWextState->WPARSNIE, genie - 2,
13484 (eLen + 2));
13485 pWextState->roamProfile.pWPAReqIE =
13486 pWextState->WPARSNIE;
13487 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13488 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13489 P2P_OUI_TYPE_SIZE))) {
13490 uint16_t curAddIELen =
13491 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013492 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013493
13494 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13495 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013496 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013497 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013498 return -ENOMEM;
13499 }
13500 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13501 memcpy(pWextState->assocAddIE.addIEdata +
13502 curAddIELen, genie - 2, eLen + 2);
13503 pWextState->assocAddIE.length += eLen + 2;
13504
13505 pWextState->roamProfile.pAddIEAssoc =
13506 pWextState->assocAddIE.addIEdata;
13507 pWextState->roamProfile.nAddIEAssocLength =
13508 pWextState->assocAddIE.length;
13509 }
13510#ifdef WLAN_FEATURE_WFD
13511 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13512 WFD_OUI_TYPE_SIZE)) &&
13513 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013514 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013515 pAdapter->device_mode)) {
13516 uint16_t curAddIELen =
13517 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013518 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013519
13520 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13521 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013522 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013523 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013524 return -ENOMEM;
13525 }
13526 /* WFD IE is saved to Additional IE ; it should
13527 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013528 * WFD IE
13529 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013530 memcpy(pWextState->assocAddIE.addIEdata +
13531 curAddIELen, genie - 2, eLen + 2);
13532 pWextState->assocAddIE.length += eLen + 2;
13533
13534 pWextState->roamProfile.pAddIEAssoc =
13535 pWextState->assocAddIE.addIEdata;
13536 pWextState->roamProfile.nAddIEAssocLength =
13537 pWextState->assocAddIE.length;
13538 }
13539#endif
13540 /* Appending HS 2.0 Indication Element in Assiciation Request */
13541 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13542 HS20_OUI_TYPE_SIZE))) {
13543 uint16_t curAddIELen =
13544 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013545 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546
13547 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13548 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013549 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013550 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013551 return -ENOMEM;
13552 }
13553 memcpy(pWextState->assocAddIE.addIEdata +
13554 curAddIELen, genie - 2, eLen + 2);
13555 pWextState->assocAddIE.length += eLen + 2;
13556
13557 pWextState->roamProfile.pAddIEAssoc =
13558 pWextState->assocAddIE.addIEdata;
13559 pWextState->roamProfile.nAddIEAssocLength =
13560 pWextState->assocAddIE.length;
13561 }
13562 /* Appending OSEN Information Element in Assiciation Request */
13563 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13564 OSEN_OUI_TYPE_SIZE))) {
13565 uint16_t curAddIELen =
13566 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013567 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013568
13569 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13570 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013571 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013572 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573 return -ENOMEM;
13574 }
13575 memcpy(pWextState->assocAddIE.addIEdata +
13576 curAddIELen, genie - 2, eLen + 2);
13577 pWextState->assocAddIE.length += eLen + 2;
13578
13579 pWextState->roamProfile.bOSENAssociation = true;
13580 pWextState->roamProfile.pAddIEAssoc =
13581 pWextState->assocAddIE.addIEdata;
13582 pWextState->roamProfile.nAddIEAssocLength =
13583 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013584 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13585 MBO_OUI_TYPE_SIZE))){
13586 hdd_info("Set MBO IE(len %d)", eLen + 2);
13587 status = wlan_hdd_add_assoc_ie(pWextState,
13588 genie - 2, eLen + 2);
13589 if (status)
13590 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013591 } else {
13592 uint16_t add_ie_len =
13593 pWextState->assocAddIE.length;
13594
13595 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13596
13597 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13598 (pWextState->assocAddIE.length + eLen)) {
13599 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013600 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601 return -ENOMEM;
13602 }
13603
13604 memcpy(pWextState->assocAddIE.addIEdata +
13605 add_ie_len, genie - 2, eLen + 2);
13606 pWextState->assocAddIE.length += eLen + 2;
13607
13608 pWextState->roamProfile.pAddIEAssoc =
13609 pWextState->assocAddIE.addIEdata;
13610 pWextState->roamProfile.nAddIEAssocLength =
13611 pWextState->assocAddIE.length;
13612 }
13613 break;
13614 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013615 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013616 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13617 memcpy(pWextState->WPARSNIE, genie - 2,
13618 (eLen + 2));
13619 pWextState->roamProfile.pRSNReqIE =
13620 pWextState->WPARSNIE;
13621 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13622 break;
13623 /*
13624 * Appending Extended Capabilities with Interworking bit set
13625 * in Assoc Req.
13626 *
13627 * In assoc req this EXT Cap will only be taken into account if
13628 * interworkingService bit is set to 1. Currently
13629 * driver is only interested in interworkingService capability
13630 * from supplicant. If in future any other EXT Cap info is
13631 * required from supplicat, it needs to be handled while
13632 * sending Assoc Req in LIM.
13633 */
13634 case DOT11F_EID_EXTCAP:
13635 {
13636 uint16_t curAddIELen =
13637 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013638 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639
13640 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13641 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013642 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013643 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644 return -ENOMEM;
13645 }
13646 memcpy(pWextState->assocAddIE.addIEdata +
13647 curAddIELen, genie - 2, eLen + 2);
13648 pWextState->assocAddIE.length += eLen + 2;
13649
13650 pWextState->roamProfile.pAddIEAssoc =
13651 pWextState->assocAddIE.addIEdata;
13652 pWextState->roamProfile.nAddIEAssocLength =
13653 pWextState->assocAddIE.length;
13654 break;
13655 }
13656#ifdef FEATURE_WLAN_WAPI
13657 case WLAN_EID_WAPI:
13658 /* Setting WAPI Mode to ON=1 */
13659 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013660 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013661 tmp = (u16 *) ie;
13662 tmp = tmp + 2; /* Skip element Id and Len, Version */
13663 akmsuiteCount = WPA_GET_LE16(tmp);
13664 tmp = tmp + 1;
13665 akmlist = (int *)(tmp);
13666 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13667 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13668 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013669 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013670 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 return -EINVAL;
13672 }
13673
13674 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013675 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013676 pAdapter->wapi_info.wapiAuthMode =
13677 WAPI_AUTH_MODE_PSK;
13678 }
13679 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013680 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681 pAdapter->wapi_info.wapiAuthMode =
13682 WAPI_AUTH_MODE_CERT;
13683 }
13684 break;
13685#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013686 case DOT11F_EID_SUPPOPERATINGCLASSES:
13687 {
13688 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13689 status = wlan_hdd_add_assoc_ie(pWextState,
13690 genie - 2, eLen + 2);
13691 if (status)
13692 return status;
13693 break;
13694 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013695 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013696 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013697 /* when Unknown IE is received we break
13698 * and continue to the next IE in the buffer
13699 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 break;
13701 }
13702 genie += eLen;
13703 remLen -= eLen;
13704 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013705 return 0;
13706}
13707
13708/**
13709 * hdd_is_wpaie_present() - check for WPA ie
13710 * @ie: Pointer to ie
13711 * @ie_len: Ie length
13712 *
13713 * Parse the received IE to find the WPA IE
13714 *
13715 * Return: true if wpa ie is found else false
13716 */
13717static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13718{
13719 uint8_t eLen = 0;
13720 uint16_t remLen = ie_len;
13721 uint8_t elementId = 0;
13722
13723 while (remLen >= 2) {
13724 elementId = *ie++;
13725 eLen = *ie++;
13726 remLen -= 2;
13727 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013728 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 return false;
13730 }
13731 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13732 /* OUI - 0x00 0X50 0XF2
13733 * WPA Information Element - 0x01
13734 * WPA version - 0x01
13735 */
13736 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13737 return true;
13738 }
13739 ie += eLen;
13740 remLen -= eLen;
13741 }
13742 return false;
13743}
13744
13745/**
13746 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13747 * @pAdapter: Pointer to adapter
13748 * @req: Pointer to security parameters
13749 *
13750 * Return: 0 for success, non-zero for failure
13751 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013752static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13753 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013754{
13755 int status = 0;
13756 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13757 ENTER();
13758
13759 /*set wpa version */
13760 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13761
13762 if (req->crypto.wpa_versions) {
13763 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13764 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13765 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13766 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13767 }
13768 }
13769
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013770 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013771
13772 /*set authentication type */
13773 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13774
13775 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013776 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 return status;
13778 }
13779
13780 /*set key mgmt type */
13781 if (req->crypto.n_akm_suites) {
13782 status =
13783 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13784 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013785 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013786 return status;
13787 }
13788 }
13789
13790 /*set pairwise cipher type */
13791 if (req->crypto.n_ciphers_pairwise) {
13792 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13793 req->crypto.
13794 ciphers_pairwise[0],
13795 true);
13796 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013797 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013798 return status;
13799 }
13800 } else {
13801 /*Reset previous cipher suite to none */
13802 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13803 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013804 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013805 return status;
13806 }
13807 }
13808
13809 /*set group cipher type */
13810 status =
13811 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13812 false);
13813
13814 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013815 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013816 return status;
13817 }
13818#ifdef WLAN_FEATURE_11W
13819 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13820#endif
13821
13822 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13823 if (req->ie_len) {
13824 status =
13825 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13826 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013827 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013828 return status;
13829 }
13830 }
13831
13832 /*incase of WEP set default key information */
13833 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013834 u8 key_len = req->key_len;
13835 u8 key_idx = req->key_idx;
13836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013837 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13838 || (WLAN_CIPHER_SUITE_WEP104 ==
13839 req->crypto.ciphers_pairwise[0])
13840 ) {
13841 if (IW_AUTH_KEY_MGMT_802_1X
13842 ==
13843 (pWextState->
13844 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013845 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013847 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013848
Jeff Johnson68755312017-02-10 11:46:55 -080013849 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13850 && (CSR_MAX_NUM_KEY > key_idx)) {
13851 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13852 key_idx, key_len);
13853 qdf_mem_copy(&pWextState->roamProfile.
13854 Keys.
13855 KeyMaterial[key_idx][0],
13856 req->key, key_len);
13857 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013858 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013859 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013861 }
13862 }
13863 }
13864
13865 return status;
13866}
13867
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013868int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013869{
13870 unsigned long rc;
13871 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013872 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013873
13874 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13875
Jeff Johnson9edf9572016-10-03 15:24:49 -070013876 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013877 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13878 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13879 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 hdd_conn_set_connection_state(pAdapter,
13881 eConnectionState_Disconnecting);
13882 /* Issue disconnect to CSR */
13883 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013884
13885 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13886 pAdapter->sessionId,
13887 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13888 /*
13889 * Wait here instead of returning directly, this will block the
13890 * next connect command and allow processing of the scan for
13891 * ssid and the previous connect command in CSR. Else we might
13892 * hit some race conditions leading to SME and HDD out of sync.
13893 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013894 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013895 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13896 } else if (0 != status) {
13897 hdd_err("csrRoamDisconnect failure, returned %d",
13898 (int)status);
13899 pHddStaCtx->staDebugState = status;
13900 result = -EINVAL;
13901 goto disconnected;
13902 }
13903
13904 rc = wait_for_completion_timeout(
13905 &pAdapter->disconnect_comp_var,
13906 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013907 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013908 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13909 pAdapter->sessionId, pHddStaCtx->staDebugState);
13910 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911 }
13912 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013913 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013915 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013916 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013917 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013918 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013919 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013920 }
13921 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013922disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013923 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13924 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013925}
13926
13927/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013928 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13929 * @adapter: Pointer to the HDD adapter
13930 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013931 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013932 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013933 * This function will start reassociation if prev_bssid is set and bssid/
13934 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013935 *
Naveen Rawat07332902016-07-27 09:13:17 -070013936 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013937 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013938#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13939 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013940static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13941 struct cfg80211_connect_params *req,
13942 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013943{
Naveen Rawat07332902016-07-27 09:13:17 -070013944 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013945 const uint8_t *bssid = NULL;
13946 uint16_t channel = 0;
13947
13948 if (req->bssid)
13949 bssid = req->bssid;
13950 else if (req->bssid_hint)
13951 bssid = req->bssid_hint;
13952
13953 if (req->channel)
13954 channel = req->channel->hw_value;
13955 else if (req->channel_hint)
13956 channel = req->channel_hint->hw_value;
13957
13958 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013959 reassoc = true;
13960 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013961 channel, MAC_ADDR_ARRAY(bssid));
13962 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013963 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013964 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013965 }
Naveen Rawat07332902016-07-27 09:13:17 -070013966 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013967}
13968#else
Naveen Rawat07332902016-07-27 09:13:17 -070013969static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13970 struct cfg80211_connect_params *req,
13971 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013972{
Naveen Rawat07332902016-07-27 09:13:17 -070013973 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013974}
13975#endif
13976
13977/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013978 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13979 * @wiphy: Pointer to wiphy
13980 * @dev: Pointer to network device
13981 * @req: Pointer to cfg80211 connect request
13982 *
13983 * This function is used to start the association process
13984 *
13985 * Return: 0 for success, non-zero for failure
13986 */
13987static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13988 struct net_device *ndev,
13989 struct cfg80211_connect_params *req)
13990{
13991 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013992 u16 channel;
13993#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13994 const u8 *bssid_hint = req->bssid_hint;
13995#else
13996 const u8 *bssid_hint = NULL;
13997#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13999 hdd_context_t *pHddCtx;
14000
14001 ENTER();
14002
Anurag Chouhan6d760662016-02-20 16:05:43 +053014003 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014004 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014005 return -EINVAL;
14006 }
14007
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014008 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14009 hdd_err("invalid session id: %d", pAdapter->sessionId);
14010 return -EINVAL;
14011 }
14012
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014013 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014014 TRACE_CODE_HDD_CFG80211_CONNECT,
14015 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014016 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014017 hdd_device_mode_to_string(pAdapter->device_mode),
14018 pAdapter->device_mode);
14019
Krunal Sonib4326f22016-03-10 13:05:51 -080014020 if (pAdapter->device_mode != QDF_STA_MODE &&
14021 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014022 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014023 hdd_device_mode_to_string(pAdapter->device_mode),
14024 pAdapter->device_mode);
14025 return -EINVAL;
14026 }
14027
14028 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14029 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014030 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 return -EINVAL;
14032 }
14033
14034 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014035 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014037
Naveen Rawat07332902016-07-27 09:13:17 -070014038 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014039 return status;
14040
Agrawal Ashishf156e942016-08-04 14:54:47 +053014041 /* Try disconnecting if already in connected state */
14042 status = wlan_hdd_try_disconnect(pAdapter);
14043 if (0 > status) {
14044 hdd_err("Failed to disconnect the existing connection");
14045 return -EALREADY;
14046 }
14047
14048 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014049 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014050 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014051 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014052 pAdapter->device_mode),
14053 req->channel->hw_value, HW_MODE_20_MHZ)) {
14054 hdd_err("This concurrency combination is not allowed");
14055 return -ECONNREFUSED;
14056 }
14057 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014058 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014059 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14061 hdd_err("This concurrency combination is not allowed");
14062 return -ECONNREFUSED;
14063 }
14064 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014065
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066 /*initialise security parameters */
14067 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14068
14069 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014070 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071 return status;
14072 }
14073
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014074 if (req->channel)
14075 channel = req->channel->hw_value;
14076 else
14077 channel = 0;
14078 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14079 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014080 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014082 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014083 return status;
14084 }
14085 EXIT();
14086 return status;
14087}
14088
14089/**
14090 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14091 * @wiphy: Pointer to wiphy
14092 * @dev: Pointer to network device
14093 * @req: Pointer to cfg80211 connect request
14094 *
14095 * Return: 0 for success, non-zero for failure
14096 */
14097static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14098 struct net_device *ndev,
14099 struct cfg80211_connect_params *req)
14100{
14101 int ret;
14102 cds_ssr_protect(__func__);
14103 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14104 cds_ssr_unprotect(__func__);
14105
14106 return ret;
14107}
14108
14109/**
14110 * wlan_hdd_disconnect() - hdd disconnect api
14111 * @pAdapter: Pointer to adapter
14112 * @reason: Disconnect reason code
14113 *
14114 * This function is used to issue a disconnect request to SME
14115 *
14116 * Return: 0 for success, non-zero for failure
14117 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014118static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014119{
14120 int status, result = 0;
14121 unsigned long rc;
14122 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14123 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14124
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014125 ENTER();
14126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 status = wlan_hdd_validate_context(pHddCtx);
14128
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014129 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014131
14132 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014133 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
14135 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014136 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014137 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14138 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14139
14140 /*issue disconnect */
14141
14142 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14143 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053014144 /*
14145 * Wait here instead of returning directly, this will block the next
14146 * connect command and allow processing of the scan for ssid and
14147 * the previous connect command in CSR. Else we might hit some
14148 * race conditions leading to SME and HDD out of sync.
14149 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014150 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014151 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014152 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014153 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014154 (int)status);
14155 pHddStaCtx->staDebugState = status;
14156 result = -EINVAL;
14157 goto disconnected;
14158 }
14159 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14160 msecs_to_jiffies
14161 (WLAN_WAIT_TIME_DISCONNECT));
14162
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014163 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014164 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165 result = -ETIMEDOUT;
14166 }
14167disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014168 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14169#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14170 /* Sending disconnect event to userspace for kernel version < 3.11
14171 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14172 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014173 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014174 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14175 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014176#endif
14177
14178 return result;
14179}
14180
14181/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014182 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14183 * @reason: ieee80211 reason code.
14184 *
14185 * This utility function helps log string conversion of reason code.
14186 *
14187 * Return: string conversion of reason code, if match found;
14188 * "Unknown" otherwise.
14189 */
14190static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14191{
14192 switch (reason) {
14193 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14194 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14195 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14196 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14197 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14198 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14199 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14200 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14201 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14202 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14203 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14204 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14205 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14206 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14207 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14208 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14209 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14210 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14211 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14212 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14213 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14214 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14215 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14216 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14217 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14218 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14219 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14220 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14221 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14222 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14223 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14224 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14225 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14226 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14227 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14228 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14229 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14230 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14231 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14232 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14233 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14234 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14235 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14236 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14237 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14238 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14239 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14240 default:
14241 return "Unknown";
14242 }
14243}
14244
14245/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014246 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14247 * @wiphy: Pointer to wiphy
14248 * @dev: Pointer to network device
14249 * @reason: Disconnect reason code
14250 *
14251 * This function is used to issue a disconnect request to SME
14252 *
14253 * Return: 0 for success, non-zero for failure
14254 */
14255static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14256 struct net_device *dev, u16 reason)
14257{
14258 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14259 int status;
14260 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14261 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14262#ifdef FEATURE_WLAN_TDLS
14263 uint8_t staIdx;
14264#endif
14265
14266 ENTER();
14267
Anurag Chouhan6d760662016-02-20 16:05:43 +053014268 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014269 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014270 return -EINVAL;
14271 }
14272
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014273 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14274 hdd_err("invalid session id: %d", pAdapter->sessionId);
14275 return -EINVAL;
14276 }
14277
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014278 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14280 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014281 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014282 hdd_device_mode_to_string(pAdapter->device_mode),
14283 pAdapter->device_mode, reason);
14284
14285 status = wlan_hdd_validate_context(pHddCtx);
14286
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080014287 if (hdd_is_roaming_in_progress()) {
14288 hdd_err("Roaming In Progress. Ignore!!!");
14289 return -EAGAIN;
14290 }
14291
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014292 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014293 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014294
14295 /* Issue disconnect request to SME, if station is in connected state */
14296 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14297 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14298 eCsrRoamDisconnectReason reasonCode =
14299 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14300 hdd_scaninfo_t *pScanInfo;
14301
14302 switch (reason) {
14303 case WLAN_REASON_MIC_FAILURE:
14304 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14305 break;
14306
14307 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14308 case WLAN_REASON_DISASSOC_AP_BUSY:
14309 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14310 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14311 break;
14312
14313 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14314 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14315 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14316 break;
14317
14318 case WLAN_REASON_DEAUTH_LEAVING:
14319 reasonCode =
14320 pHddCtx->config->
14321 gEnableDeauthToDisassocMap ?
14322 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14323 eCSR_DISCONNECT_REASON_DEAUTH;
14324 break;
14325 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14326 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14327 break;
14328 default:
14329 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14330 break;
14331 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014332 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334 pScanInfo = &pAdapter->scan_info;
14335 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014336 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014338 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339 eCSR_SCAN_ABORT_DEFAULT);
14340 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014341 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342#ifdef FEATURE_WLAN_TDLS
14343 /* First clean up the tdls peers if any */
14344 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14345 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14346 pAdapter->sessionId)
14347 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14348 uint8_t *mac;
14349 mac =
14350 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014351 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14352 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014353 pHddCtx->tdlsConnInfo[staIdx].staId,
14354 pAdapter->sessionId,
14355 MAC_ADDR_ARRAY(mac));
14356 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14357 (pAdapter),
14358 pAdapter->sessionId, mac);
14359 }
14360 }
14361#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014362 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014363 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014364 hdd_info("Disconnect request from user space with reason: %s",
14365 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014366 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14367 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014368 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014369 return -EINVAL;
14370 }
14371 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014372 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014373 pHddStaCtx->conn_info.connState);
14374 }
14375
14376 return status;
14377}
14378
14379/**
14380 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14381 * @wiphy: Pointer to wiphy
14382 * @dev: Pointer to network device
14383 * @reason: Disconnect reason code
14384 *
14385 * Return: 0 for success, non-zero for failure
14386 */
14387static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14388 struct net_device *dev, u16 reason)
14389{
14390 int ret;
14391 cds_ssr_protect(__func__);
14392 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14393 cds_ssr_unprotect(__func__);
14394
14395 return ret;
14396}
14397
14398/**
14399 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14400 * @pAdapter: Pointer to adapter
14401 * @param: Pointer to IBSS parameters
14402 *
14403 * This function is used to initialize the security settings in IBSS mode
14404 *
14405 * Return: 0 for success, non-zero for failure
14406 */
14407static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14408 struct cfg80211_ibss_params
14409 *params)
14410{
14411 int status = 0;
14412 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14413 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14414 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14415
14416 ENTER();
14417
14418 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014419 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014420 pHddStaCtx->ibss_enc_key_installed = 0;
14421
14422 if (params->ie_len && (NULL != params->ie)) {
14423 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14424 params->ie_len, WLAN_EID_RSN)) {
14425 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14426 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14427 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14428 tDot11fIEWPA dot11WPAIE;
14429 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14430 u8 *ie;
14431
14432 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14433 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14434 params->ie_len,
14435 DOT11F_EID_WPA);
14436 if (NULL != ie) {
14437 pWextState->wpaVersion =
14438 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014439 /* Unpack the WPA IE
14440 * Skip past the EID byte and length byte
14441 * and four byte WiFi OUI
14442 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014443 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14444 &ie[2 + 4],
14445 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014446 /* Extract the multicast cipher, the
14447 * encType for unicast cipher for
14448 * wpa-none is none
14449 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 encryptionType =
14451 hdd_translate_wpa_to_csr_encryption_type
14452 (dot11WPAIE.multicast_cipher);
14453 }
14454 }
14455
14456 status =
14457 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14458 params->ie_len);
14459
14460 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014461 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 return status;
14463 }
14464 }
14465
14466 pWextState->roamProfile.AuthType.authType[0] =
14467 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14468
14469 if (params->privacy) {
14470 /* Security enabled IBSS, At this time there is no information
14471 * available about the security paramters, so initialise the
14472 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14473 * The correct security parameters will be updated later in
14474 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14475 * set inorder enable privacy bit in beacons
14476 */
14477
14478 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14479 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014480 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14482 pWextState->roamProfile.EncryptionType.numEntries = 1;
14483 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14484 encryptionType;
14485 return status;
14486}
14487
14488/**
14489 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14490 * @wiphy: Pointer to wiphy
14491 * @dev: Pointer to network device
14492 * @param: Pointer to IBSS join parameters
14493 *
14494 * This function is used to create/join an IBSS network
14495 *
14496 * Return: 0 for success, non-zero for failure
14497 */
14498static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14499 struct net_device *dev,
14500 struct cfg80211_ibss_params *params)
14501{
14502 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14503 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14504 tCsrRoamProfile *pRoamProfile;
14505 int status;
14506 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14507 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014508 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014509 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510
14511 ENTER();
14512
Anurag Chouhan6d760662016-02-20 16:05:43 +053014513 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014514 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 return -EINVAL;
14516 }
14517
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014518 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14519 hdd_err("invalid session id: %d", pAdapter->sessionId);
14520 return -EINVAL;
14521 }
14522
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014523 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14525 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014526 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014527 hdd_device_mode_to_string(pAdapter->device_mode),
14528 pAdapter->device_mode);
14529
14530 status = wlan_hdd_validate_context(pHddCtx);
14531
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014532 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014533 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014534
14535 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014536 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014537 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14538 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14539 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14540 int indx;
14541
14542 /* Get channel number */
14543 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 params->
14545 chandef.
14546 chan->
14547 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014548
14549 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14550 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014551 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 return -EOPNOTSUPP;
14553 }
14554
14555 for (indx = 0; indx < numChans; indx++) {
14556 if (channelNum == validChan[indx]) {
14557 break;
14558 }
14559 }
14560 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014561 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 return -EINVAL;
14563 }
14564 }
14565
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014566 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 HW_MODE_20_MHZ)) {
14568 hdd_err("This concurrency combination is not allowed");
14569 return -ECONNREFUSED;
14570 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014571
Krunal Soni3091bcc2016-06-23 12:28:21 -070014572 status = qdf_reset_connection_update();
14573 if (!QDF_IS_STATUS_SUCCESS(status))
14574 hdd_err("ERR: clear event failed");
14575
14576 status = cds_current_connections_update(pAdapter->sessionId,
14577 channelNum,
14578 SIR_UPDATE_REASON_JOIN_IBSS);
14579 if (QDF_STATUS_E_FAILURE == status) {
14580 hdd_err("ERROR: connections update failed!!");
14581 return -EINVAL;
14582 }
14583
14584 if (QDF_STATUS_SUCCESS == status) {
14585 status = qdf_wait_for_connection_update();
14586 if (!QDF_IS_STATUS_SUCCESS(status)) {
14587 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014588 return -EINVAL;
14589 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590 }
14591
14592 /*Try disconnecting if already in connected state */
14593 status = wlan_hdd_try_disconnect(pAdapter);
14594 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014595 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014596 return -EALREADY;
14597 }
14598
14599 pRoamProfile = &pWextState->roamProfile;
14600
14601 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014602 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603 return -EINVAL;
14604 }
14605
14606 /* enable selected protection checks in IBSS mode */
14607 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14608
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014609 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14611 pHddCtx->config->
14612 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014613 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014614 }
14615
14616 /* BSSID is provided by upper layers hence no need to AUTO generate */
14617 if (NULL != params->bssid) {
14618 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014619 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014620 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014621 return -EIO;
14622 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014623 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14625 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014626 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014627 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014628 return -EIO;
14629 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014630 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014631 }
14632 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14633 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14634 pRoamProfile->beaconInterval = params->beacon_interval;
14635 else {
14636 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014637 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014638 params->beacon_interval, pRoamProfile->beaconInterval);
14639 }
14640
14641 /* Set Channel */
14642 if (channelNum) {
14643 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014644 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014645 pRoamProfile->ChannelInfo.numOfChannels = 1;
14646 pHddStaCtx->conn_info.operationChannel = channelNum;
14647 pRoamProfile->ChannelInfo.ChannelList =
14648 &pHddStaCtx->conn_info.operationChannel;
14649 }
14650
14651 /* Initialize security parameters */
14652 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14653 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014654 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014655 return status;
14656 }
14657
14658 /* Issue connect start */
14659 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14660 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014661 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014662 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014663 operationChannel,
14664 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014665
14666 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014667 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014668 return status;
14669 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014670 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014671 return 0;
14672}
14673
14674/**
14675 * wlan_hdd_cfg80211_join_ibss() - join ibss
14676 * @wiphy: Pointer to wiphy
14677 * @dev: Pointer to network device
14678 * @param: Pointer to IBSS join parameters
14679 *
14680 * This function is used to create/join an IBSS network
14681 *
14682 * Return: 0 for success, non-zero for failure
14683 */
14684static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14685 struct net_device *dev,
14686 struct cfg80211_ibss_params *params)
14687{
14688 int ret = 0;
14689
14690 cds_ssr_protect(__func__);
14691 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14692 cds_ssr_unprotect(__func__);
14693
14694 return ret;
14695}
14696
14697/**
14698 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14699 * @wiphy: Pointer to wiphy
14700 * @dev: Pointer to network device
14701 *
14702 * This function is used to leave an IBSS network
14703 *
14704 * Return: 0 for success, non-zero for failure
14705 */
14706static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14707 struct net_device *dev)
14708{
14709 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14710 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14711 tCsrRoamProfile *pRoamProfile;
14712 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14713 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014714 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014715 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014716 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014717
14718 ENTER();
14719
Anurag Chouhan6d760662016-02-20 16:05:43 +053014720 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014721 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722 return -EINVAL;
14723 }
14724
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014725 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14726 hdd_err("invalid session id: %d", pAdapter->sessionId);
14727 return -EINVAL;
14728 }
14729
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014730 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14732 pAdapter->sessionId,
14733 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14734 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014735 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014737
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014738 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 hdd_device_mode_to_string(pAdapter->device_mode),
14740 pAdapter->device_mode);
14741 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014742 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014743 return -EIO;
14744 }
14745
14746 pRoamProfile = &pWextState->roamProfile;
14747
14748 /* Issue disconnect only if interface type is set to IBSS */
14749 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014750 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014751 return -EINVAL;
14752 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014753 /* Clearing add IE of beacon */
14754 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14755 sizeof(tSirMacAddr));
14756 updateIE.smeSessionId = pAdapter->sessionId;
14757 updateIE.ieBufferlength = 0;
14758 updateIE.pAdditionIEBuffer = NULL;
14759 updateIE.append = true;
14760 updateIE.notify = true;
14761 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14762 &updateIE,
14763 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014764 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014765 }
14766
14767 /* Reset WNI_CFG_PROBE_RSP Flags */
14768 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014769
14770 /* Issue Disconnect request */
14771 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14772 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14773 pAdapter->sessionId,
14774 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014775 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014776 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014777 hal_status);
14778 return -EAGAIN;
14779 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014780
14781 /* wait for mc thread to cleanup and then return to upper stack
14782 * so by the time upper layer calls the change interface, we are
14783 * all set to proceed further
14784 */
14785 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14786 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14787 if (!rc) {
14788 hdd_err("Failed to disconnect, timed out");
14789 return -ETIMEDOUT;
14790 }
14791
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014792 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 return 0;
14794}
14795
14796/**
14797 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14798 * @wiphy: Pointer to wiphy
14799 * @dev: Pointer to network device
14800 *
14801 * This function is used to leave an IBSS network
14802 *
14803 * Return: 0 for success, non-zero for failure
14804 */
14805static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14806 struct net_device *dev)
14807{
14808 int ret = 0;
14809
14810 cds_ssr_protect(__func__);
14811 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14812 cds_ssr_unprotect(__func__);
14813
14814 return ret;
14815}
14816
14817/**
14818 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14819 * @wiphy: Pointer to wiphy
14820 * @changed: Parameters changed
14821 *
14822 * This function is used to set the phy parameters. RTS Threshold/FRAG
14823 * Threshold/Retry Count etc.
14824 *
14825 * Return: 0 for success, non-zero for failure
14826 */
14827static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14828 u32 changed)
14829{
14830 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14831 tHalHandle hHal = pHddCtx->hHal;
14832 int status;
14833
14834 ENTER();
14835
Anurag Chouhan6d760662016-02-20 16:05:43 +053014836 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014837 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014838 return -EINVAL;
14839 }
14840
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014841 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014842 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14843 NO_SESSION, wiphy->rts_threshold));
14844 status = wlan_hdd_validate_context(pHddCtx);
14845
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014846 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014848
14849 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14850 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14851 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14852
14853 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14854 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014855 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856 rts_threshold);
14857 return -EINVAL;
14858 }
14859
14860 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14861 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014862 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014863 rts_threshold);
14864 return -EIO;
14865 }
14866
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014867 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014868 }
14869
14870 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14871 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14872 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14873 wiphy->frag_threshold;
14874
14875 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14876 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014877 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878 frag_threshold);
14879 return -EINVAL;
14880 }
14881
14882 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14883 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014884 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 frag_threshold);
14886 return -EIO;
14887 }
14888
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014889 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014890 }
14891
14892 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14893 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14894 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14895 wiphy->retry_short : wiphy->retry_long;
14896
14897 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14898 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014899 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014900 return -EINVAL;
14901 }
14902
14903 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14904 if (0 != sme_cfg_set_int(hHal,
14905 WNI_CFG_LONG_RETRY_LIMIT,
14906 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014907 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014908 retry_value);
14909 return -EIO;
14910 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014911 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014912 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14913 if (0 != sme_cfg_set_int(hHal,
14914 WNI_CFG_SHORT_RETRY_LIMIT,
14915 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014916 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014917 retry_value);
14918 return -EIO;
14919 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014920 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014921 }
14922 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014923 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014924 return 0;
14925}
14926
14927/**
14928 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14929 * @wiphy: Pointer to wiphy
14930 * @changed: Parameters changed
14931 *
14932 * Return: 0 for success, non-zero for failure
14933 */
14934static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14935{
14936 int ret;
14937
14938 cds_ssr_protect(__func__);
14939 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14940 cds_ssr_unprotect(__func__);
14941
14942 return ret;
14943}
14944
14945/**
14946 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14947 * key
14948 * @wiphy: Pointer to wiphy
14949 * @dev: Pointer to network device
14950 * @key_index: Key index
14951 *
14952 * Return: 0
14953 */
14954static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14955 struct net_device *netdev,
14956 u8 key_index)
14957{
14958 ENTER();
14959 return 0;
14960}
14961
14962/**
14963 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14964 * wlan_hdd_set_default_mgmt_key
14965 * @wiphy: pointer to wiphy
14966 * @netdev: pointer to net_device structure
14967 * @key_index: key index
14968 *
14969 * Return: 0 on success, error number on failure
14970 */
14971static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14972 struct net_device *netdev,
14973 u8 key_index)
14974{
14975 int ret;
14976
14977 cds_ssr_protect(__func__);
14978 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14979 cds_ssr_unprotect(__func__);
14980
14981 return ret;
14982}
14983
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014984/**
14985 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14986 * @wiphy: Pointer to wiphy
14987 * @dev: Pointer to network device
14988 * @params: Pointer to tx queue parameters
14989 *
14990 * Return: 0
14991 */
14992static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14993 struct net_device *dev,
14994 struct ieee80211_txq_params *params)
14995{
14996 ENTER();
14997 return 0;
14998}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014999
15000/**
15001 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15002 * @wiphy: pointer to wiphy
15003 * @netdev: pointer to net_device structure
15004 * @params: pointer to ieee80211_txq_params
15005 *
15006 * Return: 0 on success, error number on failure
15007 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015008static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15009 struct net_device *dev,
15010 struct ieee80211_txq_params *params)
15011{
15012 int ret;
15013
15014 cds_ssr_protect(__func__);
15015 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15016 cds_ssr_unprotect(__func__);
15017
15018 return ret;
15019}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015020
15021/**
15022 * __wlan_hdd_cfg80211_del_station() - delete station v2
15023 * @wiphy: Pointer to wiphy
15024 * @param: Pointer to delete station parameter
15025 *
15026 * Return: 0 for success, non-zero for failure
15027 */
15028static
15029int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15030 struct net_device *dev,
15031 struct tagCsrDelStaParams *pDelStaParams)
15032{
15033 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15034 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015035 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 hdd_hostapd_state_t *hapd_state;
15037 int status;
15038 uint8_t staId;
15039 uint8_t *mac;
15040
15041 ENTER();
15042
Anurag Chouhan6d760662016-02-20 16:05:43 +053015043 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015044 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015045 return -EINVAL;
15046 }
15047
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015048 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15049 hdd_err("invalid session id: %d", pAdapter->sessionId);
15050 return -EINVAL;
15051 }
15052
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015053 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015054 TRACE_CODE_HDD_CFG80211_DEL_STA,
15055 pAdapter->sessionId, pAdapter->device_mode));
15056
15057 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15058 status = wlan_hdd_validate_context(pHddCtx);
15059
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015060 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015061 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015062
15063 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15064
Krunal Sonib4326f22016-03-10 13:05:51 -080015065 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15066 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067
15068 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15069 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015070 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015071 return 0;
15072 }
15073
Anurag Chouhanc5548422016-02-24 18:33:27 +053015074 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075 uint16_t i;
15076 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15077 if ((pAdapter->aStaInfo[i].isUsed) &&
15078 (!pAdapter->aStaInfo[i].
15079 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015080 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015081 mac,
15082 pAdapter->aStaInfo[i].
15083 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015084 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15086 hdd_ipa_wlan_evt(pAdapter,
15087 pAdapter->
15088 aStaInfo[i].
15089 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015090 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015091 mac);
15092 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015093 hdd_notice("Delete STA with MAC::"
15094 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015095 MAC_ADDR_ARRAY(mac));
15096
15097 if (pHddCtx->dev_dfs_cac_status ==
15098 DFS_CAC_IN_PROGRESS)
15099 goto fn_end;
15100
Wei Song2f76f642016-11-18 16:32:53 +080015101 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015102 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015103 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015104 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015105 hdd_softap_sta_deauth(pAdapter,
15106 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015107 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015108 pAdapter->aStaInfo[i].
15109 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015110 qdf_status =
15111 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015112 &hapd_state->
15113 qdf_sta_disassoc_event,
15114 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015115 if (!QDF_IS_STATUS_SUCCESS(
15116 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015117 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015118 }
15119 }
15120 }
15121 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015122 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015123 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015124 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015126 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015127 hdd_notice("Skip DEL STA as this is not used::"
15128 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 MAC_ADDR_ARRAY(mac));
15130 return -ENOENT;
15131 }
15132
15133 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15134 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015135 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015136 }
15137
15138 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15139 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015140 hdd_notice("Skip DEL STA as deauth is in progress::"
15141 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015142 MAC_ADDR_ARRAY(mac));
15143 return -ENOENT;
15144 }
15145
15146 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15147
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015148 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015149 MAC_ADDR_ARRAY(mac));
15150
15151 /* Case: SAP in ACS selected DFS ch and client connected
15152 * Now Radar detected. Then if random channel is another
15153 * DFS ch then new CAC is initiated and no TX allowed.
15154 * So do not send any mgmt frames as it will timeout
15155 * during CAC.
15156 */
15157
15158 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15159 goto fn_end;
15160
Wei Song2f76f642016-11-18 16:32:53 +080015161 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015162 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15163 (pAdapter), pAdapter->sessionId,
15164 (uint8_t *)&pDelStaParams->peerMacAddr,
15165 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015166 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015167 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015168 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015169 pAdapter->aStaInfo[staId].isDeauthInProgress =
15170 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015171 hdd_notice("STA removal failed for ::"
15172 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015173 MAC_ADDR_ARRAY(mac));
15174 return -ENOENT;
15175 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015176 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015177 &hapd_state->
15178 qdf_sta_disassoc_event,
15179 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015180 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015181 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015182 }
15183 }
15184 }
15185
15186fn_end:
15187 EXIT();
15188 return 0;
15189}
15190
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015191#if defined(USE_CFG80211_DEL_STA_V2)
15192/**
15193 * wlan_hdd_del_station() - delete station wrapper
15194 * @adapter: pointer to the hdd adapter
15195 *
15196 * Return: None
15197 */
15198void wlan_hdd_del_station(hdd_adapter_t *adapter)
15199{
15200 struct station_del_parameters del_sta;
15201 del_sta.mac = NULL;
15202 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15203 del_sta.reason_code = eCsrForcedDeauthSta;
15204
15205 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15206 &del_sta);
15207}
15208#else
15209void wlan_hdd_del_station(hdd_adapter_t *adapter)
15210{
15211 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15212}
15213#endif
15214
15215#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015216/**
15217 * wlan_hdd_cfg80211_del_station() - delete station v2
15218 * @wiphy: Pointer to wiphy
15219 * @param: Pointer to delete station parameter
15220 *
15221 * Return: 0 for success, non-zero for failure
15222 */
15223int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15224 struct net_device *dev,
15225 struct station_del_parameters *param)
15226#else
15227/**
15228 * wlan_hdd_cfg80211_del_station() - delete station
15229 * @wiphy: Pointer to wiphy
15230 * @mac: Pointer to station mac address
15231 *
15232 * Return: 0 for success, non-zero for failure
15233 */
15234#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15235int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15236 struct net_device *dev,
15237 const uint8_t *mac)
15238#else
15239int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15240 struct net_device *dev,
15241 uint8_t *mac)
15242#endif
15243#endif
15244{
15245 int ret;
15246 struct tagCsrDelStaParams delStaParams;
15247
15248 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015249#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015250 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015251 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015252 return -EINVAL;
15253 }
15254 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15255 param->subtype, &delStaParams);
15256#else
15257 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15258 (SIR_MAC_MGMT_DEAUTH >> 4),
15259 &delStaParams);
15260#endif
15261 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15262 cds_ssr_unprotect(__func__);
15263
15264 return ret;
15265}
15266
15267/**
15268 * __wlan_hdd_cfg80211_add_station() - add station
15269 * @wiphy: Pointer to wiphy
15270 * @mac: Pointer to station mac address
15271 * @pmksa: Pointer to add station parameter
15272 *
15273 * Return: 0 for success, non-zero for failure
15274 */
15275static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15276 struct net_device *dev,
15277 const uint8_t *mac,
15278 struct station_parameters *params)
15279{
15280 int status = -EPERM;
15281#ifdef FEATURE_WLAN_TDLS
15282 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15283 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15284 u32 mask, set;
15285
15286 ENTER();
15287
Anurag Chouhan6d760662016-02-20 16:05:43 +053015288 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015289 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015290 return -EINVAL;
15291 }
15292
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015293 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15294 hdd_err("invalid session id: %d", pAdapter->sessionId);
15295 return -EINVAL;
15296 }
15297
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015298 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015299 TRACE_CODE_HDD_CFG80211_ADD_STA,
15300 pAdapter->sessionId, params->listen_interval));
15301
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015302 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015303 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304
15305 mask = params->sta_flags_mask;
15306
15307 set = params->sta_flags_set;
15308
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015309 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015310 MAC_ADDR_ARRAY(mac));
15311
15312 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15313 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15314 status =
15315 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15316 }
15317 }
15318#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015319 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015320 return status;
15321}
15322
15323/**
15324 * wlan_hdd_cfg80211_add_station() - add station
15325 * @wiphy: Pointer to wiphy
15326 * @mac: Pointer to station mac address
15327 * @pmksa: Pointer to add station parameter
15328 *
15329 * Return: 0 for success, non-zero for failure
15330 */
15331#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15332static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15333 struct net_device *dev,
15334 const uint8_t *mac,
15335 struct station_parameters *params)
15336#else
15337static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15338 struct net_device *dev, uint8_t *mac,
15339 struct station_parameters *params)
15340#endif
15341{
15342 int ret;
15343
15344 cds_ssr_protect(__func__);
15345 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15346 cds_ssr_unprotect(__func__);
15347
15348 return ret;
15349}
15350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015351/**
15352 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15353 * @wiphy: Pointer to wiphy
15354 * @dev: Pointer to network device
15355 * @pmksa: Pointer to set pmksa parameter
15356 *
15357 * Return: 0 for success, non-zero for failure
15358 */
15359static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15360 struct net_device *dev,
15361 struct cfg80211_pmksa *pmksa)
15362{
15363 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15364 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15365 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015366 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015367 int status;
15368 tPmkidCacheInfo pmk_id;
15369
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015370 ENTER();
15371
Anurag Chouhan6d760662016-02-20 16:05:43 +053015372 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015373 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374 return -EINVAL;
15375 }
15376
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015377 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15378 hdd_err("invalid session id: %d", pAdapter->sessionId);
15379 return -EINVAL;
15380 }
15381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015382 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015383 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015384 return -EINVAL;
15385 }
15386
15387 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015388 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015389 pmksa->bssid, pmksa->pmkid);
15390 return -EINVAL;
15391 }
15392
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015393 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015394 MAC_ADDR_ARRAY(pmksa->bssid));
15395
15396 status = wlan_hdd_validate_context(pHddCtx);
15397
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015398 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015399 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015400
15401 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15402
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015403 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15404 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015405
15406 /* Add to the PMKSA ID Cache in CSR */
15407 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15408 &pmk_id, 1, false);
15409
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015410 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015411 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15412 pAdapter->sessionId, result));
15413
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015414 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015415 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015416}
15417
15418/**
15419 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15420 * @wiphy: Pointer to wiphy
15421 * @dev: Pointer to network device
15422 * @pmksa: Pointer to set pmksa parameter
15423 *
15424 * Return: 0 for success, non-zero for failure
15425 */
15426static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15427 struct net_device *dev,
15428 struct cfg80211_pmksa *pmksa)
15429{
15430 int ret;
15431
15432 cds_ssr_protect(__func__);
15433 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15434 cds_ssr_unprotect(__func__);
15435
15436 return ret;
15437}
15438
15439/**
15440 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15441 * @wiphy: Pointer to wiphy
15442 * @dev: Pointer to network device
15443 * @pmksa: Pointer to pmksa parameter
15444 *
15445 * Return: 0 for success, non-zero for failure
15446 */
15447static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15448 struct net_device *dev,
15449 struct cfg80211_pmksa *pmksa)
15450{
15451 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15452 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15453 tHalHandle halHandle;
15454 int status = 0;
15455
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015456 ENTER();
15457
Anurag Chouhan6d760662016-02-20 16:05:43 +053015458 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015459 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015460 return -EINVAL;
15461 }
15462
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015463 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15464 hdd_err("invalid session id: %d", pAdapter->sessionId);
15465 return -EINVAL;
15466 }
15467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015468 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015469 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015470 return -EINVAL;
15471 }
15472
15473 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015474 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015475 return -EINVAL;
15476 }
15477
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015478 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015479 MAC_ADDR_ARRAY(pmksa->bssid));
15480
15481 status = wlan_hdd_validate_context(pHddCtx);
15482
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015483 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015484 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015485
15486 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15487
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015488 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015489 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15490 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015492 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015493 sme_roam_del_pmkid_from_cache(halHandle,
15494 pAdapter->sessionId, pmksa->bssid,
15495 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015496 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015497 MAC_ADDR_ARRAY(pmksa->bssid));
15498 status = -EINVAL;
15499 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015500 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015501 return status;
15502}
15503
15504/**
15505 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15506 * @wiphy: Pointer to wiphy
15507 * @dev: Pointer to network device
15508 * @pmksa: Pointer to pmksa parameter
15509 *
15510 * Return: 0 for success, non-zero for failure
15511 */
15512static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15513 struct net_device *dev,
15514 struct cfg80211_pmksa *pmksa)
15515{
15516 int ret;
15517
15518 cds_ssr_protect(__func__);
15519 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15520 cds_ssr_unprotect(__func__);
15521
15522 return ret;
15523
15524}
15525
15526/**
15527 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15528 * @wiphy: Pointer to wiphy
15529 * @dev: Pointer to network device
15530 *
15531 * Return: 0 for success, non-zero for failure
15532 */
15533static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15534 struct net_device *dev)
15535{
15536 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15537 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15538 tHalHandle halHandle;
15539 int status = 0;
15540
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015541 ENTER();
15542
Anurag Chouhan6d760662016-02-20 16:05:43 +053015543 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015544 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015545 return -EINVAL;
15546 }
15547
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015548 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15549 hdd_err("invalid session id: %d", pAdapter->sessionId);
15550 return -EINVAL;
15551 }
15552
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015553 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015554
15555 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15556 status = wlan_hdd_validate_context(pHddCtx);
15557
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015558 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015559 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015560
15561 /* Retrieve halHandle */
15562 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15563
15564 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015565 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015566 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15567 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015568 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015569 status = -EINVAL;
15570 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015571 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015572 return status;
15573}
15574
15575/**
15576 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15577 * @wiphy: Pointer to wiphy
15578 * @dev: Pointer to network device
15579 *
15580 * Return: 0 for success, non-zero for failure
15581 */
15582static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15583 struct net_device *dev)
15584{
15585 int ret;
15586
15587 cds_ssr_protect(__func__);
15588 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15589 cds_ssr_unprotect(__func__);
15590
15591 return ret;
15592}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015593
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015594#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595/**
15596 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15597 * @wiphy: Pointer to wiphy
15598 * @dev: Pointer to network device
15599 * @ftie: Pointer to fast transition ie parameter
15600 *
15601 * Return: 0 for success, non-zero for failure
15602 */
15603static int
15604__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15605 struct net_device *dev,
15606 struct cfg80211_update_ft_ies_params *ftie)
15607{
15608 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15610 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15611 int status;
15612
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015613 ENTER();
15614
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015615 status = wlan_hdd_validate_context(hdd_ctx);
15616 if (status)
15617 return status;
15618
Anurag Chouhan6d760662016-02-20 16:05:43 +053015619 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015620 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015621 return -EINVAL;
15622 }
15623
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015624 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15625 hdd_err("invalid session id: %d", pAdapter->sessionId);
15626 return -EINVAL;
15627 }
15628
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015629 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015630 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15631 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15632 /* Added for debug on reception of Re-assoc Req. */
15633 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015634 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015636 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015637 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015638 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015639 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015640
15641 /* Pass the received FT IEs to SME */
15642 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15643 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015644 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015645 return 0;
15646}
15647
15648/**
15649 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15650 * @wiphy: Pointer to wiphy
15651 * @dev: Pointer to network device
15652 * @ftie: Pointer to fast transition ie parameter
15653 *
15654 * Return: 0 for success, non-zero for failure
15655 */
15656static int
15657wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15658 struct net_device *dev,
15659 struct cfg80211_update_ft_ies_params *ftie)
15660{
15661 int ret;
15662
15663 cds_ssr_protect(__func__);
15664 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15665 cds_ssr_unprotect(__func__);
15666
15667 return ret;
15668}
15669#endif
15670
15671#ifdef WLAN_FEATURE_GTK_OFFLOAD
15672/**
15673 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
15674 * @callbackContext: Callback context
15675 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
15676 *
15677 * Callback rountine called upon receiving response for get offload info
15678 *
15679 * Return: none
15680 */
15681void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
15682 tpSirGtkOffloadGetInfoRspParams
15683 pGtkOffloadGetInfoRsp)
15684{
15685 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
15686 uint8_t tempReplayCounter[8];
15687 hdd_station_ctx_t *pHddStaCtx;
15688
15689 ENTER();
15690
15691 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015692 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015693 return;
15694 }
15695
15696 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015697 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015698 return;
15699 }
15700
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015701 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015702 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703 return;
15704 }
15705
15706 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15707 /* Update replay counter */
15708 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
15709 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15710
15711 {
15712 /* changing from little to big endian since supplicant
15713 * works on big endian format
15714 */
15715 int i;
15716 uint8_t *p =
15717 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15718
15719 for (i = 0; i < 8; i++) {
15720 tempReplayCounter[7 - i] = (uint8_t) p[i];
15721 }
15722 }
15723
15724 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015725 cfg80211_gtk_rekey_notify(pAdapter->dev,
15726 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015727 tempReplayCounter, GFP_KERNEL);
15728}
15729
15730/**
15731 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15732 * @wiphy: Pointer to wiphy
15733 * @dev: Pointer to network device
15734 * @data: Pointer to rekey data
15735 *
15736 * This function is used to offload GTK rekeying job to the firmware.
15737 *
15738 * Return: 0 for success, non-zero for failure
15739 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015740static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15742 struct net_device *dev,
15743 struct cfg80211_gtk_rekey_data *data)
15744{
15745 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15746 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15747 hdd_station_ctx_t *pHddStaCtx;
15748 tHalHandle hHal;
15749 int result;
15750 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015751 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752
15753 ENTER();
15754
Anurag Chouhan6d760662016-02-20 16:05:43 +053015755 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015756 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757 return -EINVAL;
15758 }
15759
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015760 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15761 hdd_err("invalid session id: %d", pAdapter->sessionId);
15762 return -EINVAL;
15763 }
15764
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015765 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015766 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15767 pAdapter->sessionId, pAdapter->device_mode));
15768
15769 result = wlan_hdd_validate_context(pHddCtx);
15770
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015771 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015772 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015773
15774 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15775 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15776 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015777 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015778 return -EAGAIN;
15779 }
15780
15781 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
15782 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
15783 NL80211_KCK_LEN);
15784 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
15785 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053015786 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015787 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015788 {
15789 /* changing from big to little endian since driver
15790 * works on little endian format
15791 */
15792 uint8_t *p =
15793 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
15794 ullKeyReplayCounter;
15795 int i;
15796
15797 for (i = 0; i < 8; i++) {
15798 p[7 - i] = data->replay_ctr[i];
15799 }
15800 }
15801
15802 if (true == pHddCtx->hdd_wlan_suspended) {
15803 /* if wlan is suspended, enable GTK offload directly from here */
15804 memcpy(&hddGtkOffloadReqParams,
15805 &pHddStaCtx->gtkOffloadReqParams,
15806 sizeof(tSirGtkOffloadParams));
15807 status =
15808 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
15809 pAdapter->sessionId);
15810
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015811 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015812 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015813 status);
15814 return -EINVAL;
15815 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015816 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015817 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015818 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015820 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821 return result;
15822}
15823
15824/**
15825 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15826 * @wiphy: Pointer to wiphy
15827 * @dev: Pointer to network device
15828 * @data: Pointer to rekey data
15829 *
15830 * This function is used to offload GTK rekeying job to the firmware.
15831 *
15832 * Return: 0 for success, non-zero for failure
15833 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015834static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015835int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15836 struct net_device *dev,
15837 struct cfg80211_gtk_rekey_data *data)
15838{
15839 int ret;
15840
15841 cds_ssr_protect(__func__);
15842 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15843 cds_ssr_unprotect(__func__);
15844
15845 return ret;
15846}
15847#endif /*WLAN_FEATURE_GTK_OFFLOAD */
15848
15849/**
15850 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15851 * @wiphy: Pointer to wiphy
15852 * @dev: Pointer to network device
15853 * @param: Pointer to access control parameter
15854 *
15855 * Return: 0 for success, non-zero for failure
15856 */
15857static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15858 struct net_device *dev,
15859 const struct cfg80211_acl_data *params)
15860{
15861 int i;
15862 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15863 hdd_hostapd_state_t *pHostapdState;
15864 tsap_Config_t *pConfig;
15865 v_CONTEXT_t p_cds_context = NULL;
15866 hdd_context_t *pHddCtx;
15867 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015868 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015869
15870 ENTER();
15871
Anurag Chouhan6d760662016-02-20 16:05:43 +053015872 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015873 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015874 return -EINVAL;
15875 }
15876
15877 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015878 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015879 return -EINVAL;
15880 }
15881
15882 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15883 status = wlan_hdd_validate_context(pHddCtx);
15884
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015885 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015886 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887
15888 p_cds_context = pHddCtx->pcds_context;
15889 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15890
15891 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015892 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015893 return -EINVAL;
15894 }
15895
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015896 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015897 params->n_acl_entries);
15898
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015899 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015900 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15901 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015902 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015903 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15904
15905 /* default value */
15906 pConfig->num_accept_mac = 0;
15907 pConfig->num_deny_mac = 0;
15908
15909 /**
15910 * access control policy
15911 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15912 * listed in hostapd.deny file.
15913 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15914 * listed in hostapd.accept file.
15915 */
15916 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15917 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15918 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15919 params->acl_policy) {
15920 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15921 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015922 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015923 params->acl_policy);
15924 return -ENOTSUPP;
15925 }
15926
15927 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15928 pConfig->num_accept_mac = params->n_acl_entries;
15929 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015930 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15931 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015932 MAC_ADDR_ARRAY(
15933 params->mac_addrs[i].addr));
15934
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015935 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015936 params->mac_addrs[i].addr,
15937 sizeof(qcmacaddr));
15938 }
15939 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15940 pConfig->num_deny_mac = params->n_acl_entries;
15941 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015942 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15943 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015944 MAC_ADDR_ARRAY(
15945 params->mac_addrs[i].addr));
15946
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015947 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015948 params->mac_addrs[i].addr,
15949 sizeof(qcmacaddr));
15950 }
15951 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015952 qdf_status = wlansap_set_mac_acl(
15953 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015954 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015955 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015956 return -EINVAL;
15957 }
15958 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015959 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015960 hdd_device_mode_to_string(pAdapter->device_mode),
15961 pAdapter->device_mode);
15962 return -EINVAL;
15963 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015964 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965 return 0;
15966}
15967
15968/**
15969 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15970 * __wlan_hdd_cfg80211_set_mac_acl
15971 * @wiphy: pointer to wiphy structure
15972 * @dev: pointer to net_device
15973 * @params: pointer to cfg80211_acl_data
15974 *
15975 * Return; 0 on success, error number otherwise
15976 */
15977static int
15978wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15979 struct net_device *dev,
15980 const struct cfg80211_acl_data *params)
15981{
15982 int ret;
15983
15984 cds_ssr_protect(__func__);
15985 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15986 cds_ssr_unprotect(__func__);
15987
15988 return ret;
15989}
15990
15991#ifdef WLAN_NL80211_TESTMODE
15992#ifdef FEATURE_WLAN_LPHB
15993/**
15994 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15995 * @pHddCtx: Pointer to hdd context
15996 * @lphbInd: Pointer to low power heart beat indication parameter
15997 *
15998 * Return: none
15999 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016000static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
16001 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016002{
16003 struct sk_buff *skb;
16004
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016005 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016007 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016008 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016009
16010 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016011 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012 return;
16013 }
16014
16015 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
16016 wiphy, sizeof(tSirLPHBInd),
16017 GFP_ATOMIC);
16018 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016019 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020 return;
16021 }
16022
16023 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016024 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016025 goto nla_put_failure;
16026 }
16027 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016028 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016029 goto nla_put_failure;
16030 }
16031 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016032 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 goto nla_put_failure;
16034 }
16035 cfg80211_testmode_event(skb, GFP_ATOMIC);
16036 return;
16037
16038nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016039 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016040 kfree_skb(skb);
16041
16042 return;
16043}
16044#endif /* FEATURE_WLAN_LPHB */
16045
16046/**
16047 * __wlan_hdd_cfg80211_testmode() - test mode
16048 * @wiphy: Pointer to wiphy
16049 * @data: Data pointer
16050 * @len: Data length
16051 *
16052 * Return: 0 for success, non-zero for failure
16053 */
16054static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16055 void *data, int len)
16056{
16057 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16058 int err;
16059 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16060
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016061 ENTER();
16062
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016063 err = wlan_hdd_validate_context(pHddCtx);
16064 if (err)
16065 return err;
16066
16067 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16068 len, wlan_hdd_tm_policy);
16069 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016070 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016071 return err;
16072 }
16073
16074 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016075 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076 return -EINVAL;
16077 }
16078
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016079 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016080 TRACE_CODE_HDD_CFG80211_TESTMODE,
16081 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016082 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16083#ifdef FEATURE_WLAN_LPHB
16084 /* Low Power Heartbeat configuration request */
16085 case WLAN_HDD_TM_CMD_WLAN_HB:
16086 {
16087 int buf_len;
16088 void *buf;
16089 tSirLPHBReq *hb_params = NULL;
16090 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016091 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092
16093 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016094 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016095 return -EINVAL;
16096 }
16097
16098 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16099 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16100
16101 hb_params_temp = (tSirLPHBReq *) buf;
16102 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16103 && (hb_params_temp->params.lphbTcpParamReq.
16104 timePeriodSec == 0))
16105 return -EINVAL;
16106
16107 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016108 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016109 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016110 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016111 return -ENOMEM;
16112 }
16113
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016114 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115 smeStatus =
16116 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16117 hb_params,
16118 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016119 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016120 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016121 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016122 }
16123 return 0;
16124 }
16125#endif /* FEATURE_WLAN_LPHB */
16126
16127#if defined(QCA_WIFI_FTM)
16128 case WLAN_HDD_TM_CMD_WLAN_FTM:
16129 {
16130 int buf_len;
16131 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016132 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016133 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016134 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016135 return -EINVAL;
16136 }
16137
16138 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16139 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16140
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016141 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016142
16143 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016145 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016146 err = -EBUSY;
16147 break;
16148 }
16149#endif
16150
16151 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016152 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016153 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16154 return -EOPNOTSUPP;
16155 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016156 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016157 return err;
16158}
16159
16160/**
16161 * wlan_hdd_cfg80211_testmode() - test mode
16162 * @wiphy: Pointer to wiphy
16163 * @dev: Pointer to network device
16164 * @data: Data pointer
16165 * @len: Data length
16166 *
16167 * Return: 0 for success, non-zero for failure
16168 */
16169static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16170#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16171 struct wireless_dev *wdev,
16172#endif
16173 void *data, int len)
16174{
16175 int ret;
16176
16177 cds_ssr_protect(__func__);
16178 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16179 cds_ssr_unprotect(__func__);
16180
16181 return ret;
16182}
16183
16184#if defined(QCA_WIFI_FTM)
16185/**
16186 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16187 * @buf: Pointer to buffer
16188 * @buf_len: Buffer length
16189 *
16190 * Return: none
16191 */
16192void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16193{
16194 struct sk_buff *skb;
16195 hdd_context_t *hdd_ctx;
16196
16197 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016198 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016199 return;
16200 }
16201
Anurag Chouhan6d760662016-02-20 16:05:43 +053016202 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016204 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016205 return;
16206 }
16207
16208 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16209 buf_len, GFP_KERNEL);
16210 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016211 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016212 return;
16213 }
16214
16215 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16216 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16217 goto nla_put_failure;
16218
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016219 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220
16221 cfg80211_testmode_event(skb, GFP_KERNEL);
16222 return;
16223
16224nla_put_failure:
16225 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016226 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227}
16228#endif
16229#endif /* CONFIG_NL80211_TESTMODE */
16230
16231#ifdef QCA_HT_2040_COEX
16232/**
16233 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16234 * @wiphy: Pointer to wiphy
16235 * @dev: Pointer to network device
16236 * @chandef: Pointer to channel definition parameter
16237 *
16238 * Return: 0 for success, non-zero for failure
16239 */
16240static int
16241__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16242 struct net_device *dev,
16243 struct cfg80211_chan_def *chandef)
16244{
16245 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16246 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016247 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016248 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016249 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250
Anurag Chouhan6d760662016-02-20 16:05:43 +053016251 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016252 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 return -EINVAL;
16254 }
16255
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016256 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16257 hdd_err("invalid session id: %d", pAdapter->sessionId);
16258 return -EINVAL;
16259 }
16260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016261 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16262 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016263 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016264 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016265
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016266 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016267 sme_get_config_param(pHddCtx->hHal, &sme_config);
16268 switch (chandef->width) {
16269 case NL80211_CHAN_WIDTH_20:
16270 if (sme_config.csrConfig.channelBondingMode24GHz !=
16271 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16272 sme_config.csrConfig.channelBondingMode24GHz =
16273 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16274 sme_update_config(pHddCtx->hHal, &sme_config);
16275 cbModeChange = true;
16276 }
16277 break;
16278
16279 case NL80211_CHAN_WIDTH_40:
16280 if (sme_config.csrConfig.channelBondingMode24GHz ==
16281 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16282 if (NL80211_CHAN_HT40MINUS ==
16283 cfg80211_get_chandef_type(chandef))
16284 sme_config.csrConfig.channelBondingMode24GHz =
16285 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16286 else
16287 sme_config.csrConfig.channelBondingMode24GHz =
16288 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16289 sme_update_config(pHddCtx->hHal, &sme_config);
16290 cbModeChange = true;
16291 }
16292 break;
16293
16294 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016295 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016296 return -EINVAL;
16297 }
16298
16299 if (!cbModeChange)
16300 return 0;
16301
Krunal Sonib4326f22016-03-10 13:05:51 -080016302 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016303 return 0;
16304
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016305 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016306 sme_config.csrConfig.channelBondingMode24GHz);
16307
16308 /* Change SAP ht2040 mode */
16309 status = hdd_set_sap_ht2040_mode(pAdapter,
16310 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016311 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016312 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016313 return -EINVAL;
16314 }
16315
16316 return 0;
16317}
16318
16319/**
16320 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16321 * @wiphy: Pointer to wiphy
16322 * @dev: Pointer to network device
16323 * @chandef: Pointer to channel definition parameter
16324 *
16325 * Return: 0 for success, non-zero for failure
16326 */
16327static int
16328wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16329 struct net_device *dev,
16330 struct cfg80211_chan_def *chandef)
16331{
16332 int ret;
16333
16334 cds_ssr_protect(__func__);
16335 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16336 cds_ssr_unprotect(__func__);
16337
16338 return ret;
16339}
16340#endif
16341
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016342#ifdef CHANNEL_SWITCH_SUPPORTED
16343/**
16344 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16345 * channel in SAP/GO
16346 * @wiphy: wiphy pointer
16347 * @dev: dev pointer.
16348 * @csa_params: Change channel params
16349 *
16350 * This function is called to switch channel in SAP/GO
16351 *
16352 * Return: 0 if success else return non zero
16353 */
16354static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16355 struct net_device *dev,
16356 struct cfg80211_csa_settings *csa_params)
16357{
16358 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16359 hdd_context_t *hdd_ctx;
16360 uint8_t channel;
16361 uint16_t freq;
16362 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016363 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016364
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016365 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016366 csa_params->chandef.chan->center_freq);
16367
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016368 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16369 hdd_err("invalid session id: %d", adapter->sessionId);
16370 return -EINVAL;
16371 }
16372
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016373 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16374 ret = wlan_hdd_validate_context(hdd_ctx);
16375
16376 if (0 != ret)
16377 return ret;
16378
Krunal Sonib4326f22016-03-10 13:05:51 -080016379 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16380 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016381 return -ENOTSUPP;
16382
16383 freq = csa_params->chandef.chan->center_freq;
16384 channel = cds_freq_to_chan(freq);
16385
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016386 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16387
16388 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016389 return ret;
16390}
16391
16392/**
16393 * wlan_hdd_cfg80211_channel_switch()- function to switch
16394 * channel in SAP/GO
16395 * @wiphy: wiphy pointer
16396 * @dev: dev pointer.
16397 * @csa_params: Change channel params
16398 *
16399 * This function is called to switch channel in SAP/GO
16400 *
16401 * Return: 0 if success else return non zero
16402 */
16403static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16404 struct net_device *dev,
16405 struct cfg80211_csa_settings *csa_params)
16406{
16407 int ret;
16408
16409 cds_ssr_protect(__func__);
16410 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16411 cds_ssr_unprotect(__func__);
16412 return ret;
16413}
16414#endif
16415
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016416/**
16417 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16418 * translation from NL to policy manager type
16419 * @type: Generic connection mode type defined in NL
16420 *
16421 *
16422 * This function provides the type translation
16423 *
16424 * Return: cds_con_mode enum
16425 */
16426enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16427 enum nl80211_iftype type)
16428{
16429 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16430 switch (type) {
16431 case NL80211_IFTYPE_STATION:
16432 mode = CDS_STA_MODE;
16433 break;
16434 case NL80211_IFTYPE_P2P_CLIENT:
16435 mode = CDS_P2P_CLIENT_MODE;
16436 break;
16437 case NL80211_IFTYPE_P2P_GO:
16438 mode = CDS_P2P_GO_MODE;
16439 break;
16440 case NL80211_IFTYPE_AP:
16441 mode = CDS_SAP_MODE;
16442 break;
16443 case NL80211_IFTYPE_ADHOC:
16444 mode = CDS_IBSS_MODE;
16445 break;
16446 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016447 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016448 type);
16449 }
16450 return mode;
16451}
16452
16453/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016454 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16455 * @wiphy: Handle to struct wiphy to get handle to module context.
16456 * @chandef: Contains information about the capture channel to be set.
16457 *
16458 * This interface is called if and only if monitor mode interface alone is
16459 * active.
16460 *
16461 * Return: 0 success or error code on failure.
16462 */
16463static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16464 struct cfg80211_chan_def *chandef)
16465{
16466 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16467 hdd_adapter_t *adapter;
16468 hdd_station_ctx_t *sta_ctx;
16469 struct hdd_mon_set_ch_info *ch_info;
16470 QDF_STATUS status;
16471 tHalHandle hal_hdl;
16472 struct qdf_mac_addr bssid;
16473 tCsrRoamProfile roam_profile;
16474 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016475 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016476 int ret;
16477 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16478
16479 ENTER();
16480
16481 ret = wlan_hdd_validate_context(hdd_ctx);
16482 if (ret)
16483 return ret;
16484
16485 hal_hdl = hdd_ctx->hHal;
16486
16487 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16488 if (!adapter)
16489 return -EIO;
16490
16491 hdd_info("%s: set monitor mode Channel %d and freq %d",
16492 adapter->dev->name, chan_num, chandef->chan->center_freq);
16493
16494 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16495 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016496 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16497 roam_profile.ChannelInfo.numOfChannels = 1;
16498 roam_profile.phyMode = ch_info->phy_mode;
16499 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016500 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016501
16502 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16503 QDF_MAC_ADDR_SIZE);
16504
16505 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016506 /*
16507 * CDS api expects secondary channel for calculating
16508 * the channel params
16509 */
16510 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16511 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16512 if (chan_num >= 1 && chan_num <= 5)
16513 sec_ch = chan_num + 4;
16514 else if (chan_num >= 6 && chan_num <= 13)
16515 sec_ch = chan_num - 4;
16516 }
16517 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016518 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16519 &roam_profile);
16520 if (status) {
16521 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16522 status);
16523 ret = qdf_status_to_os_return(status);
16524 return ret;
16525 }
16526 EXIT();
16527 return 0;
16528}
16529
16530/**
16531 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16532 * @wiphy: Handle to struct wiphy to get handle to module context.
16533 * @chandef: Contains information about the capture channel to be set.
16534 *
16535 * This interface is called if and only if monitor mode interface alone is
16536 * active.
16537 *
16538 * Return: 0 success or error code on failure.
16539 */
16540static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16541 struct cfg80211_chan_def *chandef)
16542{
16543 int ret;
16544
16545 cds_ssr_protect(__func__);
16546 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16547 cds_ssr_unprotect(__func__);
16548 return ret;
16549}
16550
16551/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016552 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16553 * @adapter: pointer to adapter
16554 *
16555 * Wrapper function to clear link layer stats.
16556 * return - void
16557 */
16558void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16559{
16560 tSirLLStatsClearReq link_layer_stats_clear_req;
16561 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16562
Mukul Sharma491021c2016-09-29 21:39:19 +053016563 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16564 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016565 link_layer_stats_clear_req.stopReq = 0;
16566 link_layer_stats_clear_req.reqId = 1;
16567 link_layer_stats_clear_req.staId = adapter->sessionId;
16568 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16569
16570 return;
16571}
16572
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016573#define CNT_DIFF(cur, prev) \
16574 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16575#define MAX_COUNT 0xffffffff
16576static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16577 struct scan_chan_info *chan,
16578 struct scan_chan_info *info, uint32_t cmd_flag)
16579{
16580 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16581 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16582 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16583
16584 mutex_lock(&hdd_ctx->chan_info_lock);
16585
16586 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16587 qdf_mem_zero(chan, sizeof(*chan));
16588
16589 chan->freq = info->freq;
16590 chan->noise_floor = info->noise_floor;
16591 chan->clock_freq = info->clock_freq;
16592 chan->cmd_flag = info->cmd_flag;
16593 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16594
16595 chan->rx_clear_count =
16596 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16597
16598 chan->tx_frame_count =
16599 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16600
16601 mutex_unlock(&hdd_ctx->chan_info_lock);
16602
16603}
16604#undef CNT_DIFF
16605#undef MAX_COUNT
16606
16607/**
16608 * wlan_hdd_chan_info_cb() - channel info callback
16609 * @chan_info: struct scan_chan_info
16610 *
16611 * Store channel info into HDD context
16612 *
16613 * Return: None.
16614 */
16615static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16616{
16617 hdd_context_t *hdd_ctx;
16618 struct scan_chan_info *chan;
16619 uint8_t idx;
16620
16621 ENTER();
16622
16623 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16624 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16625 hdd_err("hdd_ctx is invalid");
16626 return;
16627 }
16628
16629 if (!hdd_ctx->chan_info) {
16630 hdd_err("chan_info is NULL");
16631 return;
16632 }
16633
16634 chan = hdd_ctx->chan_info;
16635 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16636 if (chan[idx].freq == info->freq) {
16637 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16638 info->cmd_flag);
16639 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16640 chan[idx].cmd_flag, chan[idx].freq,
16641 chan[idx].noise_floor,
16642 chan[idx].cycle_count, chan[idx].rx_clear_count,
16643 chan[idx].clock_freq, chan[idx].cmd_flag,
16644 chan[idx].tx_frame_count, idx);
16645 if (chan[idx].freq == 0)
16646 break;
16647
16648 }
16649 }
16650
16651 EXIT();
16652}
16653
16654/**
16655 * wlan_hdd_init_chan_info() - init chan info in hdd context
16656 * @hdd_ctx: HDD context pointer
16657 *
16658 * Return: none
16659 */
16660void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16661{
16662 uint8_t num_2g, num_5g, index = 0;
16663
16664 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16665 hdd_info("SNR monitoring is disabled");
16666 return;
16667 }
16668
16669 hdd_ctx->chan_info =
16670 qdf_mem_malloc(sizeof(struct scan_chan_info)
16671 * QDF_MAX_NUM_CHAN);
16672 if (hdd_ctx->chan_info == NULL) {
16673 hdd_err("Failed to malloc for chan info");
16674 return;
16675 }
16676 mutex_init(&hdd_ctx->chan_info_lock);
16677
16678 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16679 for (; index < num_2g; index++) {
16680 hdd_ctx->chan_info[index].freq =
16681 hdd_channels_2_4_ghz[index].center_freq;
16682 }
16683
16684 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16685 for (; (index - num_2g) < num_5g; index++) {
16686 if (cds_is_dsrc_channel(
16687 hdd_channels_5_ghz[index - num_2g].center_freq))
16688 continue;
16689 hdd_ctx->chan_info[index].freq =
16690 hdd_channels_5_ghz[index - num_2g].center_freq;
16691 }
16692 sme_set_chan_info_callback(hdd_ctx->hHal,
16693 &wlan_hdd_chan_info_cb);
16694}
16695
16696/**
16697 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16698 * @hdd_ctx: hdd context pointer
16699 *
16700 * Return: none
16701 */
16702void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16703{
16704 struct scan_chan_info *chan;
16705
16706 chan = hdd_ctx->chan_info;
16707 hdd_ctx->chan_info = NULL;
16708 if (chan)
16709 qdf_mem_free(chan);
16710}
16711
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016712/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016713 * struct cfg80211_ops - cfg80211_ops
16714 *
16715 * @add_virtual_intf: Add virtual interface
16716 * @del_virtual_intf: Delete virtual interface
16717 * @change_virtual_intf: Change virtual interface
16718 * @change_station: Change station
16719 * @add_beacon: Add beacon in sap mode
16720 * @del_beacon: Delete beacon in sap mode
16721 * @set_beacon: Set beacon in sap mode
16722 * @start_ap: Start ap
16723 * @change_beacon: Change beacon
16724 * @stop_ap: Stop ap
16725 * @change_bss: Change bss
16726 * @add_key: Add key
16727 * @get_key: Get key
16728 * @del_key: Delete key
16729 * @set_default_key: Set default key
16730 * @set_channel: Set channel
16731 * @scan: Scan
16732 * @connect: Connect
16733 * @disconnect: Disconnect
16734 * @join_ibss = Join ibss
16735 * @leave_ibss = Leave ibss
16736 * @set_wiphy_params = Set wiphy params
16737 * @set_tx_power = Set tx power
16738 * @get_tx_power = get tx power
16739 * @remain_on_channel = Remain on channel
16740 * @cancel_remain_on_channel = Cancel remain on channel
16741 * @mgmt_tx = Tx management frame
16742 * @mgmt_tx_cancel_wait = Cancel management tx wait
16743 * @set_default_mgmt_key = Set default management key
16744 * @set_txq_params = Set tx queue parameters
16745 * @get_station = Get station
16746 * @set_power_mgmt = Set power management
16747 * @del_station = Delete station
16748 * @add_station = Add station
16749 * @set_pmksa = Set pmksa
16750 * @del_pmksa = Delete pmksa
16751 * @flush_pmksa = Flush pmksa
16752 * @update_ft_ies = Update FT IEs
16753 * @tdls_mgmt = Tdls management
16754 * @tdls_oper = Tdls operation
16755 * @set_rekey_data = Set rekey data
16756 * @sched_scan_start = Scheduled scan start
16757 * @sched_scan_stop = Scheduled scan stop
16758 * @resume = Resume wlan
16759 * @suspend = Suspend wlan
16760 * @set_mac_acl = Set mac acl
16761 * @testmode_cmd = Test mode command
16762 * @set_ap_chanwidth = Set AP channel bandwidth
16763 * @dump_survey = Dump survey
16764 * @key_mgmt_set_pmk = Set pmk key management
16765 */
16766static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16767 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16768 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16769 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16770 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016771 .start_ap = wlan_hdd_cfg80211_start_ap,
16772 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16773 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016774 .change_bss = wlan_hdd_cfg80211_change_bss,
16775 .add_key = wlan_hdd_cfg80211_add_key,
16776 .get_key = wlan_hdd_cfg80211_get_key,
16777 .del_key = wlan_hdd_cfg80211_del_key,
16778 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16779 .scan = wlan_hdd_cfg80211_scan,
16780 .connect = wlan_hdd_cfg80211_connect,
16781 .disconnect = wlan_hdd_cfg80211_disconnect,
16782 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16783 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16784 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16785 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16786 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16787 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16788 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16789 .mgmt_tx = wlan_hdd_mgmt_tx,
16790 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16791 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16792 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016793 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016794 .get_station = wlan_hdd_cfg80211_get_station,
16795 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16796 .del_station = wlan_hdd_cfg80211_del_station,
16797 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016798 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16799 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16800 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016801#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016802 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16803#endif
16804#ifdef FEATURE_WLAN_TDLS
16805 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16806 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16807#endif
16808#ifdef WLAN_FEATURE_GTK_OFFLOAD
16809 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16810#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16811#ifdef FEATURE_WLAN_SCAN_PNO
16812 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16813 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16814#endif /*FEATURE_WLAN_SCAN_PNO */
16815 .resume = wlan_hdd_cfg80211_resume_wlan,
16816 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16817 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16818#ifdef WLAN_NL80211_TESTMODE
16819 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16820#endif
16821#ifdef QCA_HT_2040_COEX
16822 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16823#endif
16824 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016825#ifdef CHANNEL_SWITCH_SUPPORTED
16826 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16827#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016828 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016829#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16830 defined(CFG80211_ABORT_SCAN)
16831 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16832#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016833};