blob: 4462b83b82c0453e968156f635a815c63489d194 [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>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530107#include "wlan_pmo_ucfg_api.h"
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
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004338 /*
4339 * The user space has issued a disconnect when roaming is in
4340 * progress. The disconnect should be honored gracefully.
4341 * If the roaming is complete and the roam event is sent
4342 * back to the user space, it will get confused as it is
4343 * expecting a disconnect event. So, do not send the event
4344 * and handle the disconnect later.
4345 */
4346 if (adapter->defer_disconnect) {
4347 hdd_notice("LFR3:Do not send roam auth event");
4348 return 0;
4349 }
4350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304352 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4354 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4355 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004356 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4358 GFP_KERNEL);
4359
4360 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 return -EINVAL;
4363 }
4364
4365 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4366 ETH_ALEN, bssid) ||
4367 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4368 req_rsn_len, req_rsn_ie) ||
4369 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4370 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004371 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004372 goto nla_put_failure;
4373 }
Jeff Johnson020db452016-06-29 14:37:26 -07004374 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 if (roam_info_ptr->synchAuthStatus ==
4376 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004377 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004378 if (nla_put_u8(skb,
4379 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4380 hdd_err("nla put fail");
4381 goto nla_put_failure;
4382 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004383 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4384 /* if FT or CCKM connection: dont send replay counter */
4385 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4386 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4387 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4388 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4389 nla_put(skb,
4390 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4391 SIR_REPLAY_CTR_LEN,
4392 roam_info_ptr->replay_ctr)) {
4393 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004394 hdd_err("failed to send replay counter.");
4395 goto nla_put_failure;
4396 }
4397 if (nla_put(skb,
4398 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4399 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4400 nla_put(skb,
4401 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4402 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4403 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404 goto nla_put_failure;
4405 }
4406 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004407 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4409 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004410 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004411 goto nla_put_failure;
4412 }
4413 }
4414
Jeff Johnson020db452016-06-29 14:37:26 -07004415 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004416 roam_info_ptr->subnet_change_status);
4417
4418 /*
4419 * Add subnet change status if subnet has changed
4420 * 0 = unchanged
4421 * 1 = changed
4422 * 2 = unknown
4423 */
4424 if (roam_info_ptr->subnet_change_status) {
4425 if (nla_put_u8(skb,
4426 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4427 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004428 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004429 goto nla_put_failure;
4430 }
4431 }
4432
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004433 cfg80211_vendor_event(skb, GFP_KERNEL);
4434 return 0;
4435
4436nla_put_failure:
4437 kfree_skb(skb);
4438 return -EINVAL;
4439}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004440#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004441
4442static const struct nla_policy
4443wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4444
4445 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4446 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4447 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304448 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304449 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4450 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004451 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4452 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4453 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4454 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4455 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304456 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457};
4458
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304460 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4461 *
4462 * @adapter: Pointer to HDD adapter
4463 * @ie_data: Pointer to Scan IEs buffer
4464 * @ie_len: Length of Scan IEs
4465 *
4466 * Return: 0 on success; error number otherwise
4467 */
4468static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4469 uint8_t *ie_data, uint8_t ie_len)
4470{
4471 hdd_scaninfo_t *scan_info = NULL;
4472 scan_info = &adapter->scan_info;
4473
4474 if (scan_info->default_scan_ies) {
4475 qdf_mem_free(scan_info->default_scan_ies);
4476 scan_info->default_scan_ies = NULL;
4477 }
4478
4479 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4480 if (!scan_info->default_scan_ies)
4481 return -ENOMEM;
4482
4483 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4484 scan_info->default_scan_ies_len = ie_len;
4485 return 0;
4486}
4487
4488/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4490 * vendor command
4491 *
4492 * @wiphy: wiphy device pointer
4493 * @wdev: wireless device pointer
4494 * @data: Vendor command data buffer
4495 * @data_len: Buffer length
4496 *
4497 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4498 *
4499 * Return: Error code.
4500 */
4501static int
4502__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4503 struct wireless_dev *wdev,
4504 const void *data,
4505 int data_len)
4506{
4507 struct net_device *dev = wdev->netdev;
4508 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4509 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4510 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4511 int ret_val = 0;
4512 u32 modulated_dtim;
4513 u16 stats_avg_factor;
4514 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304515 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004516 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004517 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304518 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304519 int attr_len;
4520 int access_policy = 0;
4521 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4522 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304523 uint16_t scan_ie_len = 0;
4524 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304525 struct sir_set_tx_rx_aggregation_size request;
4526 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004527 uint8_t retry, delay;
4528 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304529 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304530
Jeff Johnson1f61b612016-02-12 16:28:33 -08004531 ENTER_DEV(dev);
4532
Anurag Chouhan6d760662016-02-20 16:05:43 +05304533 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004534 hdd_err("Command not allowed in FTM mode");
4535 return -EPERM;
4536 }
4537
4538 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304539 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004541
4542 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4543 data, data_len,
4544 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004545 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 return -EINVAL;
4547 }
4548
Krunal Sonie3531942016-04-12 17:43:53 -07004549 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4550 ftm_capab = nla_get_u32(tb[
4551 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4552 hdd_ctx->config->fine_time_meas_cap =
4553 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4554 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304555 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004556 hdd_ctx->config->fine_time_meas_cap);
4557 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4558 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4559 hdd_ctx->config->fine_time_meas_cap);
4560 }
4561
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004562 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4563 modulated_dtim = nla_get_u32(
4564 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4565
4566 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4567 adapter->sessionId,
4568 modulated_dtim);
4569
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304570 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 ret_val = -EPERM;
4572 }
4573
Kapil Gupta6213c012016-09-02 19:39:09 +05304574 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4575 qpower = nla_get_u8(
4576 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4577 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4578 ret_val = -EINVAL;
4579 }
4580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4582 stats_avg_factor = nla_get_u16(
4583 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4584 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4585 adapter->sessionId,
4586 stats_avg_factor);
4587
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304588 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 ret_val = -EPERM;
4590 }
4591
4592
4593 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4594 guard_time = nla_get_u32(
4595 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4596 status = sme_configure_guard_time(hdd_ctx->hHal,
4597 adapter->sessionId,
4598 guard_time);
4599
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304600 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 ret_val = -EPERM;
4602 }
4603
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304604 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4605 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4606 attr_len = nla_len(
4607 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4608 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4609 hdd_info("Invalid value. attr_len %d",
4610 attr_len);
4611 return -EINVAL;
4612 }
4613
4614 nla_memcpy(&vendor_ie,
4615 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4616 attr_len);
4617 vendor_ie_present = true;
4618 hdd_info("Access policy vendor ie present.attr_len %d",
4619 attr_len);
4620 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4621 &vendor_ie[0], attr_len);
4622 }
4623
4624 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4625 access_policy = (int) nla_get_u32(
4626 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4627 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4628 (access_policy >
4629 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4630 hdd_info("Invalid value. access_policy %d",
4631 access_policy);
4632 return -EINVAL;
4633 }
4634 access_policy_present = true;
4635 hdd_info("Access policy present. access_policy %d",
4636 access_policy);
4637 }
4638
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004639 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4640 retry = nla_get_u8(tb[
4641 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4642 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4643 CFG_NON_AGG_RETRY_MAX : retry;
4644 param_id = WMI_PDEV_PARAM_NON_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_AGG_RETRY]) {
4650 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4651 retry = retry > CFG_AGG_RETRY_MAX ?
4652 CFG_AGG_RETRY_MAX : retry;
4653
4654 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4655 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4656 CFG_AGG_RETRY_MIN : retry;
4657 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4658 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4659 retry, PDEV_CMD);
4660 }
4661
4662 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4663 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4664 retry = retry > CFG_MGMT_RETRY_MAX ?
4665 CFG_MGMT_RETRY_MAX : retry;
4666 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4667 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4668 retry, PDEV_CMD);
4669 }
4670
4671 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4672 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4673 retry = retry > CFG_CTRL_RETRY_MAX ?
4674 CFG_CTRL_RETRY_MAX : retry;
4675 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4676 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4677 retry, PDEV_CMD);
4678 }
4679
4680 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4681 delay = nla_get_u8(tb[
4682 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4683 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4684 CFG_PROPAGATION_DELAY_MAX : delay;
4685 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4686 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4687 delay, PDEV_CMD);
4688 }
4689
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304690 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4691 tx_fail_count = nla_get_u32(
4692 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4693 if (tx_fail_count) {
4694 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4695 adapter->sessionId, tx_fail_count);
4696 if (QDF_STATUS_SUCCESS != status) {
4697 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4698 status);
4699 return -EINVAL;
4700 }
4701 }
4702 }
4703
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304704 if (vendor_ie_present && access_policy_present) {
4705 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4706 access_policy =
4707 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304708 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304709 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304710 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304711
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304712 hdd_info("calling sme_update_access_policy_vendor_ie");
4713 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4714 adapter->sessionId, &vendor_ie[0],
4715 access_policy);
4716 if (QDF_STATUS_SUCCESS != status) {
4717 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304718 return -EINVAL;
4719 }
4720 }
4721
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304722 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4723 set_value = nla_get_u8(
4724 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4725 hdd_info("set_value: %d", set_value);
4726 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4727 }
4728
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304729 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4730 scan_ie_len = nla_len(
4731 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4732 hdd_info("Received default scan IE of len %d session %d device mode %d",
4733 scan_ie_len, adapter->sessionId,
4734 adapter->device_mode);
4735 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4736 scan_ie = (uint8_t *) nla_data(tb
4737 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304738
4739 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4740 scan_ie_len))
4741 hdd_err("Failed to save default scan IEs");
4742
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304743 if (adapter->device_mode == QDF_STA_MODE) {
4744 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4745 adapter->sessionId, scan_ie,
4746 scan_ie_len);
4747 if (QDF_STATUS_SUCCESS != status)
4748 ret_val = -EPERM;
4749 }
4750 } else
4751 ret_val = -EPERM;
4752 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304753
4754 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4755 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4756 /* if one is specified, both must be specified */
4757 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4758 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4759 hdd_err("Both TX and RX MPDU Aggregation required");
4760 return -EINVAL;
4761 }
4762
4763 request.tx_aggregation_size = nla_get_u8(
4764 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4765 request.rx_aggregation_size = nla_get_u8(
4766 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4767 request.vdev_id = adapter->sessionId;
4768
4769 if (request.tx_aggregation_size >=
4770 CFG_TX_AGGREGATION_SIZE_MIN &&
4771 request.tx_aggregation_size <=
4772 CFG_TX_AGGREGATION_SIZE_MAX &&
4773 request.rx_aggregation_size >=
4774 CFG_RX_AGGREGATION_SIZE_MIN &&
4775 request.rx_aggregation_size <=
4776 CFG_RX_AGGREGATION_SIZE_MAX) {
4777 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4778 if (qdf_status != QDF_STATUS_SUCCESS) {
4779 hdd_err("failed to set aggr sizes err %d",
4780 qdf_status);
4781 ret_val = -EPERM;
4782 }
4783 } else {
4784 hdd_err("TX %d RX %d MPDU aggr size not in range",
4785 request.tx_aggregation_size,
4786 request.rx_aggregation_size);
4787 ret_val = -EINVAL;
4788 }
4789 }
4790
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304791 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4792 uint8_t ignore_assoc_disallowed;
4793
4794 ignore_assoc_disallowed
4795 = nla_get_u8(tb[
4796 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4797 hdd_info("Set ignore_assoc_disallowed value - %d",
4798 ignore_assoc_disallowed);
4799 if ((ignore_assoc_disallowed <
4800 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4801 (ignore_assoc_disallowed >
4802 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4803 return -EPERM;
4804
4805 sme_update_session_param(hdd_ctx->hHal,
4806 adapter->sessionId,
4807 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4808 ignore_assoc_disallowed);
4809 }
4810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 return ret_val;
4812}
4813
4814/**
4815 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4816 * vendor command
4817 *
4818 * @wiphy: wiphy device pointer
4819 * @wdev: wireless device pointer
4820 * @data: Vendor command data buffer
4821 * @data_len: Buffer length
4822 *
4823 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4824 *
4825 * Return: EOK or other error codes.
4826 */
4827static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4828 struct wireless_dev *wdev,
4829 const void *data,
4830 int data_len)
4831{
4832 int ret;
4833
4834 cds_ssr_protect(__func__);
4835 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4836 data, data_len);
4837 cds_ssr_unprotect(__func__);
4838
4839 return ret;
4840}
4841
4842static const struct
4843nla_policy
4844qca_wlan_vendor_wifi_logger_start_policy
4845[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4846 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4847 = {.type = NLA_U32 },
4848 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4849 = {.type = NLA_U32 },
4850 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4851 = {.type = NLA_U32 },
4852};
4853
4854/**
4855 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4856 * or disable the collection of packet statistics from the firmware
4857 * @wiphy: WIPHY structure pointer
4858 * @wdev: Wireless device structure pointer
4859 * @data: Pointer to the data received
4860 * @data_len: Length of the data received
4861 *
4862 * This function enables or disables the collection of packet statistics from
4863 * the firmware
4864 *
4865 * Return: 0 on success and errno on failure
4866 */
4867static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4868 struct wireless_dev *wdev,
4869 const void *data,
4870 int data_len)
4871{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304872 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4874 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4875 struct sir_wifi_start_log start_log;
4876
Jeff Johnson1f61b612016-02-12 16:28:33 -08004877 ENTER_DEV(wdev->netdev);
4878
Anurag Chouhan6d760662016-02-20 16:05:43 +05304879 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 hdd_err("Command not allowed in FTM mode");
4881 return -EPERM;
4882 }
4883
4884 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304885 if (status)
4886 return status;
4887
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304888 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4889 hdd_err("Driver Modules are closed, can not start logger");
4890 return -EINVAL;
4891 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892
4893 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4894 data, data_len,
4895 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004896 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004897 return -EINVAL;
4898 }
4899
4900 /* Parse and fetch ring id */
4901 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004902 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903 return -EINVAL;
4904 }
4905 start_log.ring_id = nla_get_u32(
4906 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004907 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908
4909 /* Parse and fetch verbose level */
4910 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004911 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 return -EINVAL;
4913 }
4914 start_log.verbose_level = nla_get_u32(
4915 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004916 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917
4918 /* Parse and fetch flag */
4919 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004920 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921 return -EINVAL;
4922 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304923 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304925 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304927 /* size is buff size which can be set using iwpriv command*/
4928 start_log.size = 0;
4929
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4931
4932 if (start_log.ring_id == RING_ID_WAKELOCK) {
4933 /* Start/stop wakelock events */
4934 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4935 cds_set_wakelock_logging(true);
4936 else
4937 cds_set_wakelock_logging(false);
4938 return 0;
4939 }
4940
4941 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304942 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004943 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004944 status);
4945 return -EINVAL;
4946 }
4947 return 0;
4948}
4949
4950/**
4951 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4952 * or disable the collection of packet statistics from the firmware
4953 * @wiphy: WIPHY structure pointer
4954 * @wdev: Wireless device structure pointer
4955 * @data: Pointer to the data received
4956 * @data_len: Length of the data received
4957 *
4958 * This function is used to enable or disable the collection of packet
4959 * statistics from the firmware
4960 *
4961 * Return: 0 on success and errno on failure
4962 */
4963static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4964 struct wireless_dev *wdev,
4965 const void *data,
4966 int data_len)
4967{
4968 int ret = 0;
4969
4970 cds_ssr_protect(__func__);
4971 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4972 wdev, data, data_len);
4973 cds_ssr_unprotect(__func__);
4974
4975 return ret;
4976}
4977
4978static const struct
4979nla_policy
4980qca_wlan_vendor_wifi_logger_get_ring_data_policy
4981[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4982 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4983 = {.type = NLA_U32 },
4984};
4985
4986/**
4987 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4988 * @wiphy: WIPHY structure pointer
4989 * @wdev: Wireless device structure pointer
4990 * @data: Pointer to the data received
4991 * @data_len: Length of the data received
4992 *
4993 * This function is used to flush or retrieve the per packet statistics from
4994 * the driver
4995 *
4996 * Return: 0 on success and errno on failure
4997 */
4998static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4999 struct wireless_dev *wdev,
5000 const void *data,
5001 int data_len)
5002{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305003 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005004 uint32_t ring_id;
5005 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5006 struct nlattr *tb
5007 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5008
Jeff Johnson1f61b612016-02-12 16:28:33 -08005009 ENTER_DEV(wdev->netdev);
5010
Anurag Chouhan6d760662016-02-20 16:05:43 +05305011 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012 hdd_err("Command not allowed in FTM mode");
5013 return -EPERM;
5014 }
5015
5016 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305017 if (status)
5018 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005019
5020 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5021 data, data_len,
5022 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005023 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024 return -EINVAL;
5025 }
5026
5027 /* Parse and fetch ring id */
5028 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005029 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030 return -EINVAL;
5031 }
5032
5033 ring_id = nla_get_u32(
5034 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5035
5036 if (ring_id == RING_ID_PER_PACKET_STATS) {
5037 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07005038 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305039 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5040 /*
5041 * As part of DRIVER ring ID, flush both driver and fw logs.
5042 * For other Ring ID's driver doesn't have any rings to flush
5043 */
5044 hdd_notice("Bug report triggered by framework");
5045
5046 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5047 WLAN_LOG_INDICATOR_FRAMEWORK,
5048 WLAN_LOG_REASON_CODE_UNUSED,
5049 true, false);
5050 if (QDF_STATUS_SUCCESS != status) {
5051 hdd_err("Failed to trigger bug report");
5052 return -EINVAL;
5053 }
5054 } else {
5055 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5056 WLAN_LOG_INDICATOR_FRAMEWORK,
5057 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 return 0;
5060}
5061
5062/**
5063 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5064 * @wiphy: WIPHY structure pointer
5065 * @wdev: Wireless device structure pointer
5066 * @data: Pointer to the data received
5067 * @data_len: Length of the data received
5068 *
5069 * This function is used to flush or retrieve the per packet statistics from
5070 * the driver
5071 *
5072 * Return: 0 on success and errno on failure
5073 */
5074static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5075 struct wireless_dev *wdev,
5076 const void *data,
5077 int data_len)
5078{
5079 int ret = 0;
5080
5081 cds_ssr_protect(__func__);
5082 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5083 wdev, data, data_len);
5084 cds_ssr_unprotect(__func__);
5085
5086 return ret;
5087}
5088
5089#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5090/**
5091 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5092 * @hdd_ctx: HDD context
5093 * @request_id: [input] request id
5094 * @pattern_id: [output] pattern id
5095 *
5096 * This function loops through request id to pattern id array
5097 * if the slot is available, store the request id and return pattern id
5098 * if entry exists, return the pattern id
5099 *
5100 * Return: 0 on success and errno on failure
5101 */
5102static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5103 uint32_t request_id,
5104 uint8_t *pattern_id)
5105{
5106 uint32_t i;
5107
5108 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5109 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5110 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5111 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5112 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5113 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5114 return 0;
5115 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5116 request_id) {
5117 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5118 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5119 return 0;
5120 }
5121 }
5122 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5123 return -EINVAL;
5124}
5125
5126/**
5127 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5128 * @hdd_ctx: HDD context
5129 * @request_id: [input] request id
5130 * @pattern_id: [output] pattern id
5131 *
5132 * This function loops through request id to pattern id array
5133 * reset request id to 0 (slot available again) and
5134 * return pattern id
5135 *
5136 * Return: 0 on success and errno on failure
5137 */
5138static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5139 uint32_t request_id,
5140 uint8_t *pattern_id)
5141{
5142 uint32_t i;
5143
5144 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5145 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5146 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5147 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5148 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5149 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5150 return 0;
5151 }
5152 }
5153 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5154 return -EINVAL;
5155}
5156
5157
5158/*
5159 * define short names for the global vendor params
5160 * used by __wlan_hdd_cfg80211_offloaded_packets()
5161 */
5162#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5163#define PARAM_REQUEST_ID \
5164 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5165#define PARAM_CONTROL \
5166 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5167#define PARAM_IP_PACKET \
5168 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5169#define PARAM_SRC_MAC_ADDR \
5170 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5171#define PARAM_DST_MAC_ADDR \
5172 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5173#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5174
5175/**
5176 * wlan_hdd_add_tx_ptrn() - add tx pattern
5177 * @adapter: adapter pointer
5178 * @hdd_ctx: hdd context
5179 * @tb: nl attributes
5180 *
5181 * This function reads the NL attributes and forms a AddTxPtrn message
5182 * posts it to SME.
5183 *
5184 */
5185static int
5186wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5187 struct nlattr **tb)
5188{
5189 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305190 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005191 uint32_t request_id, ret, len;
5192 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305193 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194 uint16_t eth_type = htons(ETH_P_IP);
5195
5196 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005197 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005198 return -ENOTSUPP;
5199 }
5200
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305201 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005203 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005204 return -ENOMEM;
5205 }
5206
5207 /* Parse and fetch request Id */
5208 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005209 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210 goto fail;
5211 }
5212
5213 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5214 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005215 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 return -EINVAL;
5217 }
Jeff Johnson77848112016-06-29 14:52:06 -07005218 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219
5220 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005221 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 goto fail;
5223 }
5224 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005225 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005227 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228 goto fail;
5229 }
5230
5231 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005232 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 goto fail;
5234 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005235 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305236 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005237 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005238 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239
Anurag Chouhanc5548422016-02-24 18:33:27 +05305240 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005241 &adapter->macAddressCurrent)) {
5242 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243 goto fail;
5244 }
5245
5246 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005247 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248 goto fail;
5249 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305250 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005251 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 MAC_ADDR_ARRAY(dst_addr.bytes));
5253
5254 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005255 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 goto fail;
5257 }
5258 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005259 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260
5261 if (add_req->ucPtrnSize < 0 ||
5262 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5263 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005264 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265 add_req->ucPtrnSize);
5266 goto fail;
5267 }
5268
5269 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305270 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305271 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305272 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305273 QDF_MAC_ADDR_SIZE);
5274 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305275 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005276 len += 2;
5277
5278 /*
5279 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5280 * ------------------------------------------------------------
5281 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5282 * ------------------------------------------------------------
5283 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305284 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 nla_data(tb[PARAM_IP_PACKET]),
5286 add_req->ucPtrnSize);
5287 add_req->ucPtrnSize += len;
5288
5289 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5290 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005291 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 goto fail;
5293 }
5294 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005295 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005296
5297 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305298 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005299 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 goto fail;
5301 }
5302
5303 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305304 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005305 return 0;
5306
5307fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305308 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309 return -EINVAL;
5310}
5311
5312/**
5313 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5314 * @adapter: adapter pointer
5315 * @hdd_ctx: hdd context
5316 * @tb: nl attributes
5317 *
5318 * This function reads the NL attributes and forms a DelTxPtrn message
5319 * posts it to SME.
5320 *
5321 */
5322static int
5323wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5324 struct nlattr **tb)
5325{
5326 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305327 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 uint32_t request_id, ret;
5329 uint8_t pattern_id = 0;
5330
5331 /* Parse and fetch request Id */
5332 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005333 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 return -EINVAL;
5335 }
5336 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5337 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005338 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339 return -EINVAL;
5340 }
5341
5342 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5343 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005344 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005345 return -EINVAL;
5346 }
5347
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305348 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005350 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 return -ENOMEM;
5352 }
5353
Anurag Chouhanc5548422016-02-24 18:33:27 +05305354 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005355 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005357 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358 request_id, del_req->ucPtrnId);
5359
5360 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305361 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005362 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 goto fail;
5364 }
5365
5366 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305367 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368 return 0;
5369
5370fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305371 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 return -EINVAL;
5373}
5374
5375
5376/**
5377 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5378 * @wiphy: Pointer to wireless phy
5379 * @wdev: Pointer to wireless device
5380 * @data: Pointer to data
5381 * @data_len: Data length
5382 *
5383 * Return: 0 on success, negative errno on failure
5384 */
5385static int
5386__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5387 struct wireless_dev *wdev,
5388 const void *data,
5389 int data_len)
5390{
5391 struct net_device *dev = wdev->netdev;
5392 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5393 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5394 struct nlattr *tb[PARAM_MAX + 1];
5395 uint8_t control;
5396 int ret;
5397 static const struct nla_policy policy[PARAM_MAX + 1] = {
5398 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5399 [PARAM_CONTROL] = { .type = NLA_U32 },
5400 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305401 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305403 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005404 [PARAM_PERIOD] = { .type = NLA_U32 },
5405 };
5406
Jeff Johnson1f61b612016-02-12 16:28:33 -08005407 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408
Anurag Chouhan6d760662016-02-20 16:05:43 +05305409 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410 hdd_err("Command not allowed in FTM mode");
5411 return -EPERM;
5412 }
5413
5414 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305415 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417
5418 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005419 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 return -ENOTSUPP;
5421 }
5422
5423 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005424 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 return -EINVAL;
5426 }
5427
5428 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005429 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 return -EINVAL;
5431 }
5432 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005433 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434
5435 if (control == WLAN_START_OFFLOADED_PACKETS)
5436 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005437 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005439
5440 hdd_err("Invalid control: %d", control);
5441
5442 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443}
5444
5445/*
5446 * done with short names for the global vendor params
5447 * used by __wlan_hdd_cfg80211_offloaded_packets()
5448 */
5449#undef PARAM_MAX
5450#undef PARAM_REQUEST_ID
5451#undef PARAM_CONTROL
5452#undef PARAM_IP_PACKET
5453#undef PARAM_SRC_MAC_ADDR
5454#undef PARAM_DST_MAC_ADDR
5455#undef PARAM_PERIOD
5456
5457/**
5458 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5459 * @wiphy: wiphy structure pointer
5460 * @wdev: Wireless device structure pointer
5461 * @data: Pointer to the data received
5462 * @data_len: Length of @data
5463 *
5464 * Return: 0 on success; errno on failure
5465 */
5466static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5467 struct wireless_dev *wdev,
5468 const void *data,
5469 int data_len)
5470{
5471 int ret = 0;
5472
5473 cds_ssr_protect(__func__);
5474 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5475 wdev, data, data_len);
5476 cds_ssr_unprotect(__func__);
5477
5478 return ret;
5479}
5480#endif
5481
5482/*
5483 * define short names for the global vendor params
5484 * used by __wlan_hdd_cfg80211_monitor_rssi()
5485 */
5486#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5487#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5488#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5489#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5490#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5491
5492/**
5493 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5494 * @wiphy: Pointer to wireless phy
5495 * @wdev: Pointer to wireless device
5496 * @data: Pointer to data
5497 * @data_len: Data length
5498 *
5499 * Return: 0 on success, negative errno on failure
5500 */
5501static int
5502__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5503 struct wireless_dev *wdev,
5504 const void *data,
5505 int data_len)
5506{
5507 struct net_device *dev = wdev->netdev;
5508 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5509 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5510 struct nlattr *tb[PARAM_MAX + 1];
5511 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305512 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 int ret;
5514 uint32_t control;
5515 static const struct nla_policy policy[PARAM_MAX + 1] = {
5516 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5517 [PARAM_CONTROL] = { .type = NLA_U32 },
5518 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5519 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5520 };
5521
Jeff Johnson1f61b612016-02-12 16:28:33 -08005522 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305524 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5525 hdd_err("invalid session id: %d", adapter->sessionId);
5526 return -EINVAL;
5527 }
5528
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005529 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305530 if (ret)
5531 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532
5533 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005534 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535 return -ENOTSUPP;
5536 }
5537
5538 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005539 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 return -EINVAL;
5541 }
5542
5543 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005544 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005545 return -EINVAL;
5546 }
5547
5548 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005549 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 return -EINVAL;
5551 }
5552
5553 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5554 req.session_id = adapter->sessionId;
5555 control = nla_get_u32(tb[PARAM_CONTROL]);
5556
5557 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5558 req.control = true;
5559 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005560 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561 return -EINVAL;
5562 }
5563
5564 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005565 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 return -EINVAL;
5567 }
5568
5569 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5570 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5571
5572 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005573 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 req.min_rssi, req.max_rssi);
5575 return -EINVAL;
5576 }
Jeff Johnson77848112016-06-29 14:52:06 -07005577 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 req.min_rssi, req.max_rssi);
5579
5580 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5581 req.control = false;
5582 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005583 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 return -EINVAL;
5585 }
Jeff Johnson77848112016-06-29 14:52:06 -07005586 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005587 req.request_id, req.session_id, req.control);
5588
5589 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305590 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005591 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592 return -EINVAL;
5593 }
5594
5595 return 0;
5596}
5597
5598/*
5599 * done with short names for the global vendor params
5600 * used by __wlan_hdd_cfg80211_monitor_rssi()
5601 */
5602#undef PARAM_MAX
5603#undef PARAM_CONTROL
5604#undef PARAM_REQUEST_ID
5605#undef PARAM_MAX_RSSI
5606#undef PARAM_MIN_RSSI
5607
5608/**
5609 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5610 * @wiphy: wiphy structure pointer
5611 * @wdev: Wireless device structure pointer
5612 * @data: Pointer to the data received
5613 * @data_len: Length of @data
5614 *
5615 * Return: 0 on success; errno on failure
5616 */
5617static int
5618wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5619 const void *data, int data_len)
5620{
5621 int ret;
5622
5623 cds_ssr_protect(__func__);
5624 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5625 cds_ssr_unprotect(__func__);
5626
5627 return ret;
5628}
5629
5630/**
5631 * hdd_rssi_threshold_breached() - rssi breached NL event
5632 * @hddctx: HDD context
5633 * @data: rssi breached event data
5634 *
5635 * This function reads the rssi breached event %data and fill in the skb with
5636 * NL attributes and send up the NL event.
5637 *
5638 * Return: none
5639 */
5640void hdd_rssi_threshold_breached(void *hddctx,
5641 struct rssi_breach_event *data)
5642{
5643 hdd_context_t *hdd_ctx = hddctx;
5644 struct sk_buff *skb;
5645
5646 ENTER();
5647
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305648 if (wlan_hdd_validate_context(hdd_ctx))
5649 return;
5650 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005651 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 return;
5653 }
5654
5655 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5656 NULL,
5657 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5658 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5659 GFP_KERNEL);
5660
5661 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005662 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005663 return;
5664 }
5665
Jeff Johnson77848112016-06-29 14:52:06 -07005666 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005668 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005669 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5670
5671 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5672 data->request_id) ||
5673 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5674 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5675 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5676 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005677 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 goto fail;
5679 }
5680
5681 cfg80211_vendor_event(skb, GFP_KERNEL);
5682 return;
5683
5684fail:
5685 kfree_skb(skb);
5686 return;
5687}
5688
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305689static const struct nla_policy
5690ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5691 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5692};
5693
5694/**
5695 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5696 * @wiphy: Pointer to wireless phy
5697 * @wdev: Pointer to wireless device
5698 * @data: Pointer to data
5699 * @data_len: Length of @data
5700 *
5701 * Return: 0 on success, negative errno on failure
5702 */
5703static int
5704__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5705 struct wireless_dev *wdev,
5706 const void *data, int data_len)
5707{
5708 int status;
5709 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5710 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005711 struct net_device *dev = wdev->netdev;
5712 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305713
5714 ENTER_DEV(wdev->netdev);
5715
5716 status = wlan_hdd_validate_context(pHddCtx);
5717 if (0 != status)
5718 return status;
5719 if (!pHddCtx->config->fhostNSOffload) {
5720 hdd_err("ND Offload not supported");
5721 return -EINVAL;
5722 }
5723
5724 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5725 (struct nlattr *)data,
5726 data_len, ns_offload_set_policy)) {
5727 hdd_err("nla_parse failed");
5728 return -EINVAL;
5729 }
5730
5731 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5732 hdd_err("ND Offload flag attribute not present");
5733 return -EINVAL;
5734 }
5735
5736 pHddCtx->ns_offload_enable =
5737 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5738
Dustin Brownd8279d22016-09-07 14:52:57 -07005739 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305740 if (pHddCtx->ns_offload_enable)
5741 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5742 else
5743 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005744
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305745 return 0;
5746}
5747
5748/**
5749 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5750 * @wiphy: pointer to wireless wiphy structure.
5751 * @wdev: pointer to wireless_dev structure.
5752 * @data: Pointer to the data to be passed via vendor interface
5753 * @data_len:Length of the data to be passed
5754 *
5755 * Return: Return the Success or Failure code.
5756 */
5757static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5758 struct wireless_dev *wdev,
5759 const void *data, int data_len)
5760{
5761 int ret;
5762
5763 cds_ssr_protect(__func__);
5764 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5765 cds_ssr_unprotect(__func__);
5766
5767 return ret;
5768}
5769
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005770/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5771 * @wiphy: Pointer to wireless phy
5772 * @wdev: Pointer to wireless device
5773 * @data: Pointer to data
5774 * @data_len: Data length
5775 *
5776 * This function return the preferred frequency list generated by the policy
5777 * manager.
5778 *
5779 * Return: success or failure code
5780 */
5781static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5782 struct wireless_dev
5783 *wdev, const void *data,
5784 int data_len)
5785{
5786 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5787 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305788 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305789 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305791 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005792 enum cds_con_mode intf_mode;
5793 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5794 struct sk_buff *reply_skb;
5795
Jeff Johnson1f61b612016-02-12 16:28:33 -08005796 ENTER_DEV(wdev->netdev);
5797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798 ret = wlan_hdd_validate_context(hdd_ctx);
5799 if (ret)
5800 return -EINVAL;
5801
5802 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5803 data, data_len, NULL)) {
5804 hdd_err("Invalid ATTR");
5805 return -EINVAL;
5806 }
5807
5808 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5809 hdd_err("attr interface type failed");
5810 return -EINVAL;
5811 }
5812
5813 intf_mode = nla_get_u32(tb
5814 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5815
5816 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5817 hdd_err("Invalid interface type");
5818 return -EINVAL;
5819 }
5820
5821 hdd_debug("Userspace requested pref freq list");
5822
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305823 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5824 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305825 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005826 hdd_err("Get pcl failed");
5827 return -EINVAL;
5828 }
5829
5830 /* convert channel number to frequency */
5831 for (i = 0; i < pcl_len; i++) {
5832 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5833 freq_list[i] =
5834 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005835 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836 else
5837 freq_list[i] =
5838 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005839 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840 }
5841
5842 /* send the freq_list back to supplicant */
5843 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5844 sizeof(u32) *
5845 pcl_len +
5846 NLMSG_HDRLEN);
5847
5848 if (!reply_skb) {
5849 hdd_err("Allocate reply_skb failed");
5850 return -EINVAL;
5851 }
5852
5853 if (nla_put_u32(reply_skb,
5854 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5855 intf_mode) ||
5856 nla_put(reply_skb,
5857 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5858 sizeof(uint32_t) * pcl_len,
5859 freq_list)) {
5860 hdd_err("nla put fail");
5861 kfree_skb(reply_skb);
5862 return -EINVAL;
5863 }
5864
5865 return cfg80211_vendor_cmd_reply(reply_skb);
5866}
5867
5868/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5869 * @wiphy: Pointer to wireless phy
5870 * @wdev: Pointer to wireless device
5871 * @data: Pointer to data
5872 * @data_len: Data length
5873 *
5874 * This function return the preferred frequency list generated by the policy
5875 * manager.
5876 *
5877 * Return: success or failure code
5878 */
5879static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5880 struct wireless_dev
5881 *wdev, const void *data,
5882 int data_len)
5883{
5884 int ret = 0;
5885
5886 cds_ssr_protect(__func__);
5887 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5888 data, data_len);
5889 cds_ssr_unprotect(__func__);
5890
5891 return ret;
5892}
5893
5894/**
5895 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5896 * @wiphy: Pointer to wireless phy
5897 * @wdev: Pointer to wireless device
5898 * @data: Pointer to data
5899 * @data_len: Data length
5900 *
5901 * Return: 0 on success, negative errno on failure
5902 */
5903static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5904 struct wireless_dev *wdev,
5905 const void *data,
5906 int data_len)
5907{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305908 struct net_device *ndev = wdev->netdev;
5909 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005910 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5911 int ret = 0;
5912 enum cds_con_mode intf_mode;
5913 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5914 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915
Jeff Johnson1f61b612016-02-12 16:28:33 -08005916 ENTER_DEV(ndev);
5917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005918 ret = wlan_hdd_validate_context(hdd_ctx);
5919 if (ret)
5920 return ret;
5921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5923 data, data_len, NULL)) {
5924 hdd_err("Invalid ATTR");
5925 return -EINVAL;
5926 }
5927
5928 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5929 hdd_err("attr interface type failed");
5930 return -EINVAL;
5931 }
5932
5933 intf_mode = nla_get_u32(tb
5934 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5935
5936 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5937 hdd_err("Invalid interface type");
5938 return -EINVAL;
5939 }
5940
5941 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5942 hdd_err("attr probable freq failed");
5943 return -EINVAL;
5944 }
5945
5946 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5947 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5948
5949 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005950 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005951 channel_hint, HW_MODE_20_MHZ)) {
5952 hdd_err("Set channel hint failed due to concurrency check");
5953 return -EINVAL;
5954 }
5955
Krunal Soni09e55032016-06-07 10:06:55 -07005956 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5957 hdd_warn("Remain On Channel Pending");
5958
Krunal Soni3091bcc2016-06-23 12:28:21 -07005959 ret = qdf_reset_connection_update();
5960 if (!QDF_IS_STATUS_SUCCESS(ret))
5961 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962
Krunal Soni3091bcc2016-06-23 12:28:21 -07005963 ret = cds_current_connections_update(adapter->sessionId,
5964 channel_hint,
5965 SIR_UPDATE_REASON_SET_OPER_CHAN);
5966 if (QDF_STATUS_E_FAILURE == ret) {
5967 /* return in the failure case */
5968 hdd_err("ERROR: connections update failed!!");
5969 return -EINVAL;
5970 }
5971
5972 if (QDF_STATUS_SUCCESS == ret) {
5973 /*
5974 * Success is the only case for which we expect hw mode
5975 * change to take place, hence we need to wait.
5976 * For any other return value it should be a pass
5977 * through
5978 */
5979 ret = qdf_wait_for_connection_update();
5980 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5981 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005982 return -EINVAL;
5983 }
5984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005985 }
5986
5987 return 0;
5988}
5989
5990/**
5991 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5992 * @wiphy: Pointer to wireless phy
5993 * @wdev: Pointer to wireless device
5994 * @data: Pointer to data
5995 * @data_len: Data length
5996 *
5997 * Return: 0 on success, negative errno on failure
5998 */
5999static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6000 struct wireless_dev *wdev,
6001 const void *data,
6002 int data_len)
6003{
6004 int ret = 0;
6005
6006 cds_ssr_protect(__func__);
6007 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6008 data, data_len);
6009 cds_ssr_unprotect(__func__);
6010
6011 return ret;
6012}
6013
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306014static const struct
6015nla_policy
6016qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6017 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6018};
6019
6020/**
6021 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6022 * @wiphy: WIPHY structure pointer
6023 * @wdev: Wireless device structure pointer
6024 * @data: Pointer to the data received
6025 * @data_len: Length of the data received
6026 *
6027 * This function is used to get link properties like nss, rate flags and
6028 * operating frequency for the active connection with the given peer.
6029 *
6030 * Return: 0 on success and errno on failure
6031 */
6032static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6033 struct wireless_dev *wdev,
6034 const void *data,
6035 int data_len)
6036{
6037 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6038 struct net_device *dev = wdev->netdev;
6039 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6040 hdd_station_ctx_t *hdd_sta_ctx;
6041 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306042 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306043 uint32_t sta_id;
6044 struct sk_buff *reply_skb;
6045 uint32_t rate_flags = 0;
6046 uint8_t nss;
6047 uint8_t final_rate_flags = 0;
6048 uint32_t freq;
6049
Jeff Johnson1f61b612016-02-12 16:28:33 -08006050 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306051
Anurag Chouhan6d760662016-02-20 16:05:43 +05306052 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306053 hdd_err("Command not allowed in FTM mode");
6054 return -EPERM;
6055 }
6056
6057 if (0 != wlan_hdd_validate_context(hdd_ctx))
6058 return -EINVAL;
6059
6060 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6061 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006062 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306063 return -EINVAL;
6064 }
6065
6066 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006067 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306068 adapter->device_mode);
6069 return -EINVAL;
6070 }
6071
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306072 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306073 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006074 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306075 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6076
Krunal Sonib4326f22016-03-10 13:05:51 -08006077 if (adapter->device_mode == QDF_STA_MODE ||
6078 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306079 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6080 if ((hdd_sta_ctx->conn_info.connState !=
6081 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306082 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306083 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006084 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306085 MAC_ADDR_ARRAY(peer_mac));
6086 return -EINVAL;
6087 }
6088
6089 nss = hdd_sta_ctx->conn_info.nss;
6090 freq = cds_chan_to_freq(
6091 hdd_sta_ctx->conn_info.operationChannel);
6092 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006093 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6094 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306095
6096 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6097 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306098 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306099 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306100 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306101 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306102 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306103 break;
6104 }
6105
6106 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006107 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306108 MAC_ADDR_ARRAY(peer_mac));
6109 return -EINVAL;
6110 }
6111
6112 nss = adapter->aStaInfo[sta_id].nss;
6113 freq = cds_chan_to_freq(
6114 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6115 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6116 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006117 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306118 MAC_ADDR_ARRAY(peer_mac));
6119 return -EINVAL;
6120 }
6121
6122 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6123 if (rate_flags & eHAL_TX_RATE_VHT80) {
6124 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006125#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306126 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006127#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306128 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6129 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006130#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306131 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006132#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306133 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6134 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6135 } else if (rate_flags &
6136 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6137 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006138#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306139 if (rate_flags & eHAL_TX_RATE_HT40)
6140 final_rate_flags |=
6141 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006142#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306143 }
6144
6145 if (rate_flags & eHAL_TX_RATE_SGI) {
6146 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6147 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6148 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6149 }
6150 }
6151
6152 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6153 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6154
6155 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006156 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306157 return -EINVAL;
6158 }
6159
6160 if (nla_put_u8(reply_skb,
6161 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6162 nss) ||
6163 nla_put_u8(reply_skb,
6164 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6165 final_rate_flags) ||
6166 nla_put_u32(reply_skb,
6167 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6168 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006169 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306170 kfree_skb(reply_skb);
6171 return -EINVAL;
6172 }
6173
6174 return cfg80211_vendor_cmd_reply(reply_skb);
6175}
6176
6177/**
6178 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6179 * properties.
6180 * @wiphy: WIPHY structure pointer
6181 * @wdev: Wireless device structure pointer
6182 * @data: Pointer to the data received
6183 * @data_len: Length of the data received
6184 *
6185 * This function is used to get link properties like nss, rate flags and
6186 * operating frequency for the active connection with the given peer.
6187 *
6188 * Return: 0 on success and errno on failure
6189 */
6190static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6191 struct wireless_dev *wdev,
6192 const void *data,
6193 int data_len)
6194{
6195 int ret = 0;
6196
6197 cds_ssr_protect(__func__);
6198 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6199 wdev, data, data_len);
6200 cds_ssr_unprotect(__func__);
6201
6202 return ret;
6203}
6204
Peng Xu278d0122015-09-24 16:34:17 -07006205static const struct
6206nla_policy
6207qca_wlan_vendor_ota_test_policy
6208[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6209 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6210};
6211
6212/**
6213 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6214 * @wiphy: Pointer to wireless phy
6215 * @wdev: Pointer to wireless device
6216 * @data: Pointer to data
6217 * @data_len: Data length
6218 *
6219 * Return: 0 on success, negative errno on failure
6220 */
6221static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6222 struct wireless_dev *wdev,
6223 const void *data,
6224 int data_len)
6225{
6226 struct net_device *dev = wdev->netdev;
6227 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6228 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6229 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6230 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6231 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306232 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006233 uint32_t current_roam_state;
6234
Jeff Johnson1f61b612016-02-12 16:28:33 -08006235 ENTER_DEV(dev);
6236
Anurag Chouhan6d760662016-02-20 16:05:43 +05306237 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006238 hdd_err("Command not allowed in FTM mode");
6239 return -EPERM;
6240 }
6241
6242 if (0 != wlan_hdd_validate_context(hdd_ctx))
6243 return -EINVAL;
6244
6245 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6246 data, data_len,
6247 qca_wlan_vendor_ota_test_policy)) {
6248 hdd_err("invalid attr");
6249 return -EINVAL;
6250 }
6251
6252 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6253 hdd_err("attr ota test failed");
6254 return -EINVAL;
6255 }
6256
6257 ota_enable = nla_get_u8(
6258 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6259
6260 hdd_info(" OTA test enable = %d", ota_enable);
6261 if (ota_enable != 1) {
6262 hdd_err("Invalid value, only enable test mode is supported!");
6263 return -EINVAL;
6264 }
6265
6266 current_roam_state =
6267 sme_get_current_roam_state(hal, adapter->sessionId);
6268 status = sme_stop_roaming(hal, adapter->sessionId,
6269 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306270 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006271 hdd_err("Enable/Disable roaming failed");
6272 return -EINVAL;
6273 }
6274
6275 status = sme_ps_enable_disable(hal, adapter->sessionId,
6276 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306277 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006278 hdd_err("Enable/Disable power save failed");
6279 /* restore previous roaming setting */
6280 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6281 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6282 status = sme_start_roaming(hal, adapter->sessionId,
6283 eCsrHddIssued);
6284 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6285 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6286 status = sme_stop_roaming(hal, adapter->sessionId,
6287 eCsrHddIssued);
6288
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306289 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006290 hdd_err("Restoring roaming state failed");
6291
6292 return -EINVAL;
6293 }
6294
6295
6296 return 0;
6297}
6298
6299/**
6300 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6301 * @wiphy: Pointer to wireless phy
6302 * @wdev: Pointer to wireless device
6303 * @data: Pointer to data
6304 * @data_len: Data length
6305 *
6306 * Return: 0 on success, negative errno on failure
6307 */
6308static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6309 struct wireless_dev *wdev,
6310 const void *data,
6311 int data_len)
6312{
6313 int ret = 0;
6314
6315 cds_ssr_protect(__func__);
6316 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6317 cds_ssr_unprotect(__func__);
6318
6319 return ret;
6320}
6321
Peng Xu4d67c8f2015-10-16 16:02:26 -07006322/**
6323 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6324 * @wiphy: Pointer to wireless phy
6325 * @wdev: Pointer to wireless device
6326 * @data: Pointer to data
6327 * @data_len: Data length
6328 *
6329 * Return: 0 on success, negative errno on failure
6330 */
6331static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6332 struct wireless_dev *wdev,
6333 const void *data,
6334 int data_len)
6335{
6336 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6337 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006338 hdd_adapter_t *adapter;
6339 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006340 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6341 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006342 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006343
Jeff Johnson1f61b612016-02-12 16:28:33 -08006344 ENTER_DEV(dev);
6345
Peng Xu4d67c8f2015-10-16 16:02:26 -07006346 ret = wlan_hdd_validate_context(hdd_ctx);
6347 if (ret)
6348 return ret;
6349
6350 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6351
6352 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6353 data, data_len, NULL)) {
6354 hdd_err("Invalid ATTR");
6355 return -EINVAL;
6356 }
6357
6358 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6359 hdd_err("attr tx power scale failed");
6360 return -EINVAL;
6361 }
6362
6363 scale_value = nla_get_u8(tb
6364 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6365
6366 if (scale_value > MAX_TXPOWER_SCALE) {
6367 hdd_err("Invalid tx power scale level");
6368 return -EINVAL;
6369 }
6370
Peng Xu62c8c432016-05-09 15:23:02 -07006371 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006372
Peng Xu62c8c432016-05-09 15:23:02 -07006373 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006374 hdd_err("Set tx power scale failed");
6375 return -EINVAL;
6376 }
6377
6378 return 0;
6379}
6380
6381/**
6382 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6383 * @wiphy: Pointer to wireless phy
6384 * @wdev: Pointer to wireless device
6385 * @data: Pointer to data
6386 * @data_len: Data length
6387 *
6388 * Return: 0 on success, negative errno on failure
6389 */
6390static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6391 struct wireless_dev *wdev,
6392 const void *data,
6393 int data_len)
6394{
Peng Xu62c8c432016-05-09 15:23:02 -07006395 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006396
6397 cds_ssr_protect(__func__);
6398 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6399 data, data_len);
6400 cds_ssr_unprotect(__func__);
6401
6402 return ret;
6403}
6404
6405/**
6406 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6407 * @wiphy: Pointer to wireless phy
6408 * @wdev: Pointer to wireless device
6409 * @data: Pointer to data
6410 * @data_len: Data length
6411 *
6412 * Return: 0 on success, negative errno on failure
6413 */
6414static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6415 struct wireless_dev *wdev,
6416 const void *data,
6417 int data_len)
6418{
6419 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6420 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006421 hdd_adapter_t *adapter;
6422 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006423 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6424 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006425 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006426
Jeff Johnson1f61b612016-02-12 16:28:33 -08006427 ENTER_DEV(dev);
6428
Peng Xu4d67c8f2015-10-16 16:02:26 -07006429 ret = wlan_hdd_validate_context(hdd_ctx);
6430 if (ret)
6431 return ret;
6432
6433 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6434
6435 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6436 data, data_len, NULL)) {
6437 hdd_err("Invalid ATTR");
6438 return -EINVAL;
6439 }
6440
6441 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6442 hdd_err("attr tx power decrease db value failed");
6443 return -EINVAL;
6444 }
6445
6446 scale_value = nla_get_u8(tb
6447 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6448
Peng Xu62c8c432016-05-09 15:23:02 -07006449 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6450 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006451
Peng Xu62c8c432016-05-09 15:23:02 -07006452 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006453 hdd_err("Set tx power decrease db failed");
6454 return -EINVAL;
6455 }
6456
6457 return 0;
6458}
6459
6460/**
6461 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6462 * @wiphy: Pointer to wireless phy
6463 * @wdev: Pointer to wireless device
6464 * @data: Pointer to data
6465 * @data_len: Data length
6466 *
6467 * Return: 0 on success, negative errno on failure
6468 */
6469static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6470 struct wireless_dev *wdev,
6471 const void *data,
6472 int data_len)
6473{
Peng Xu62c8c432016-05-09 15:23:02 -07006474 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006475
6476 cds_ssr_protect(__func__);
6477 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6478 data, data_len);
6479 cds_ssr_unprotect(__func__);
6480
6481 return ret;
6482}
Peng Xu8fdaa492016-06-22 10:20:47 -07006483
6484/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306485 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6486 * @wiphy: Pointer to wireless phy
6487 * @wdev: Pointer to wireless device
6488 * @data: Pointer to data
6489 * @data_len: Data length
6490 *
6491 * Processes the conditional channel switch request and invokes the helper
6492 * APIs to process the channel switch request.
6493 *
6494 * Return: 0 on success, negative errno on failure
6495 */
6496static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6497 struct wireless_dev *wdev,
6498 const void *data,
6499 int data_len)
6500{
6501 int ret;
6502 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6503 struct net_device *dev = wdev->netdev;
6504 hdd_adapter_t *adapter;
6505 struct nlattr
6506 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6507 uint32_t freq_len, i;
6508 uint32_t *freq;
6509 uint8_t chans[QDF_MAX_NUM_CHAN];
6510
6511 ENTER_DEV(dev);
6512
6513 ret = wlan_hdd_validate_context(hdd_ctx);
6514 if (ret)
6515 return ret;
6516
6517 if (!hdd_ctx->config->enableDFSMasterCap) {
6518 hdd_err("DFS master capability is not present in the driver");
6519 return -EINVAL;
6520 }
6521
6522 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6523 hdd_err("Command not allowed in FTM mode");
6524 return -EPERM;
6525 }
6526
6527 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6528 if (adapter->device_mode != QDF_SAP_MODE) {
6529 hdd_err("Invalid device mode %d", adapter->device_mode);
6530 return -EINVAL;
6531 }
6532
6533 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6534 data, data_len, NULL)) {
6535 hdd_err("Invalid ATTR");
6536 return -EINVAL;
6537 }
6538
6539 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6540 hdd_err("Frequency list is missing");
6541 return -EINVAL;
6542 }
6543
6544 freq_len = nla_len(
6545 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6546 sizeof(uint32_t);
6547
6548 if (freq_len > QDF_MAX_NUM_CHAN) {
6549 hdd_err("insufficient space to hold channels");
6550 return -ENOMEM;
6551 }
6552
6553 hdd_debug("freq_len=%d", freq_len);
6554
6555 freq = nla_data(
6556 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6557
6558
6559 for (i = 0; i < freq_len; i++) {
6560 if (freq[i] == 0)
6561 chans[i] = 0;
6562 else
6563 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6564
6565 hdd_debug("freq[%d]=%d", i, freq[i]);
6566 }
6567
6568 /*
6569 * The input frequency list from user space is designed to be a
6570 * priority based frequency list. This is only to accommodate any
6571 * future request. But, current requirement is only to perform CAC
6572 * on a single channel. So, the first entry from the list is picked.
6573 *
6574 * If channel is zero, any channel in the available outdoor regulatory
6575 * domain will be selected.
6576 */
6577 ret = wlan_hdd_request_pre_cac(chans[0]);
6578 if (ret) {
6579 hdd_err("pre cac request failed with reason:%d", ret);
6580 return ret;
6581 }
6582
6583 return 0;
6584}
6585
6586/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006587 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6588 * @wiphy: Pointer to wireless phy
6589 * @wdev: Pointer to wireless device
6590 * @data: Pointer to data
6591 * @data_len: Data length
6592 *
6593 * This function is to process the p2p listen offload start vendor
6594 * command. It parses the input parameters and invoke WMA API to
6595 * send the command to firmware.
6596 *
6597 * Return: 0 on success, negative errno on failure
6598 */
6599static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6600 struct wireless_dev *wdev,
6601 const void *data,
6602 int data_len)
6603{
6604 int ret;
6605 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6606 struct net_device *dev = wdev->netdev;
6607 hdd_adapter_t *adapter;
6608 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6609 struct sir_p2p_lo_start params;
6610 QDF_STATUS status;
6611
6612 ENTER_DEV(dev);
6613
6614 ret = wlan_hdd_validate_context(hdd_ctx);
6615 if (ret)
6616 return ret;
6617
6618 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6619 hdd_err("Command not allowed in FTM mode");
6620 return -EPERM;
6621 }
6622
6623 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6624 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6625 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6626 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6627 hdd_err("Invalid device mode %d", adapter->device_mode);
6628 return -EINVAL;
6629 }
6630
6631 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6632 data, data_len, NULL)) {
6633 hdd_err("Invalid ATTR");
6634 return -EINVAL;
6635 }
6636
6637 memset(&params, 0, sizeof(params));
6638
6639 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6640 params.ctl_flags = 1; /* set to default value */
6641 else
6642 params.ctl_flags = nla_get_u32(tb
6643 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6644
6645 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6646 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6647 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6648 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6649 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6650 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6651 hdd_err("Attribute parsing failed");
6652 return -EINVAL;
6653 }
6654
6655 params.vdev_id = adapter->sessionId;
6656 params.freq = nla_get_u32(tb
6657 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6658 if ((params.freq != 2412) && (params.freq != 2437) &&
6659 (params.freq != 2462)) {
6660 hdd_err("Invalid listening channel: %d", params.freq);
6661 return -EINVAL;
6662 }
6663
6664 params.period = nla_get_u32(tb
6665 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6666 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6667 hdd_err("Invalid period: %d", params.period);
6668 return -EINVAL;
6669 }
6670
6671 params.interval = nla_get_u32(tb
6672 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6673 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6674 hdd_err("Invalid interval: %d", params.interval);
6675 return -EINVAL;
6676 }
6677
6678 params.count = nla_get_u32(tb
6679 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006680 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006681 hdd_err("Invalid count: %d", params.count);
6682 return -EINVAL;
6683 }
6684
6685 params.device_types = nla_data(tb
6686 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6687 if (params.device_types == NULL) {
6688 hdd_err("Invalid device types");
6689 return -EINVAL;
6690 }
6691
6692 params.dev_types_len = nla_len(tb
6693 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6694 if (params.dev_types_len < 8) {
6695 hdd_err("Invalid device type length: %d", params.dev_types_len);
6696 return -EINVAL;
6697 }
6698
6699 params.probe_resp_tmplt = nla_data(tb
6700 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6701 if (params.probe_resp_tmplt == NULL) {
6702 hdd_err("Invalid probe response template");
6703 return -EINVAL;
6704 }
6705
6706 params.probe_resp_len = nla_len(tb
6707 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6708 if (params.probe_resp_len == 0) {
6709 hdd_err("Invalid probe resp template length: %d",
6710 params.probe_resp_len);
6711 return -EINVAL;
6712 }
6713
6714 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6715 params.freq, params.period, params.interval, params.count);
6716
6717 status = wma_p2p_lo_start(&params);
6718
6719 if (!QDF_IS_STATUS_SUCCESS(status)) {
6720 hdd_err("P2P LO start failed");
6721 return -EINVAL;
6722 }
6723
6724 return 0;
6725}
6726
6727
6728/**
6729 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6730 * @wiphy: Pointer to wireless phy
6731 * @wdev: Pointer to wireless device
6732 * @data: Pointer to data
6733 * @data_len: Data length
6734 *
6735 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6736 * to process p2p listen offload start vendor command.
6737 *
6738 * Return: 0 on success, negative errno on failure
6739 */
6740static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6741 struct wireless_dev *wdev,
6742 const void *data,
6743 int data_len)
6744{
6745 int ret = 0;
6746
6747 cds_ssr_protect(__func__);
6748 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6749 data, data_len);
6750 cds_ssr_unprotect(__func__);
6751
6752 return ret;
6753}
6754
6755/**
6756 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6757 * @wiphy: Pointer to wireless phy
6758 * @wdev: Pointer to wireless device
6759 * @data: Pointer to data
6760 * @data_len: Data length
6761 *
6762 * This function is to process the p2p listen offload stop vendor
6763 * command. It invokes WMA API to send command to firmware.
6764 *
6765 * Return: 0 on success, negative errno on failure
6766 */
6767static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6768 struct wireless_dev *wdev,
6769 const void *data,
6770 int data_len)
6771{
6772 QDF_STATUS status;
6773 hdd_adapter_t *adapter;
6774 struct net_device *dev = wdev->netdev;
6775
6776 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6777 hdd_err("Command not allowed in FTM mode");
6778 return -EPERM;
6779 }
6780
6781 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6782 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6783 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6784 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6785 hdd_err("Invalid device mode");
6786 return -EINVAL;
6787 }
6788
6789 status = wma_p2p_lo_stop(adapter->sessionId);
6790
6791 if (!QDF_IS_STATUS_SUCCESS(status)) {
6792 hdd_err("P2P LO stop failed");
6793 return -EINVAL;
6794 }
6795
6796 return 0;
6797}
6798
6799/**
6800 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6801 * @wiphy: Pointer to wireless phy
6802 * @wdev: Pointer to wireless device
6803 * @data: Pointer to data
6804 * @data_len: Data length
6805 *
6806 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6807 * to process p2p listen offload stop vendor command.
6808 *
6809 * Return: 0 on success, negative errno on failure
6810 */
6811static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6812 struct wireless_dev *wdev,
6813 const void *data,
6814 int data_len)
6815{
6816 int ret = 0;
6817
6818 cds_ssr_protect(__func__);
6819 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6820 data, data_len);
6821 cds_ssr_unprotect(__func__);
6822
6823 return ret;
6824}
6825
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306826/**
6827 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6828 * @wiphy: Pointer to wireless phy
6829 * @wdev: Pointer to wireless device
6830 * @data: Pointer to data
6831 * @data_len: Data length
6832 *
6833 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6834 * to process the conditional channel switch request.
6835 *
6836 * Return: 0 on success, negative errno on failure
6837 */
6838static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6839 struct wireless_dev *wdev,
6840 const void *data,
6841 int data_len)
6842{
6843 int ret;
6844
6845 cds_ssr_protect(__func__);
6846 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6847 data, data_len);
6848 cds_ssr_unprotect(__func__);
6849
6850 return ret;
6851}
6852
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306853/*
6854 * define short names for the global vendor params
6855 * used by __wlan_hdd_cfg80211_bpf_offload()
6856 */
6857#define BPF_INVALID \
6858 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6859#define BPF_SET_RESET \
6860 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6861#define BPF_VERSION \
6862 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6863#define BPF_FILTER_ID \
6864 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6865#define BPF_PACKET_SIZE \
6866 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6867#define BPF_CURRENT_OFFSET \
6868 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6869#define BPF_PROGRAM \
6870 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6871#define BPF_MAX \
6872 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006873
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306874static const struct nla_policy
6875wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6876 [BPF_SET_RESET] = {.type = NLA_U32},
6877 [BPF_VERSION] = {.type = NLA_U32},
6878 [BPF_FILTER_ID] = {.type = NLA_U32},
6879 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6880 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6881 [BPF_PROGRAM] = {.type = NLA_U8},
6882};
6883
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006884struct bpf_offload_priv {
6885 struct sir_bpf_get_offload bpf_get_offload;
6886};
6887
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306888/**
6889 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006890 * @context: opaque context originally passed to SME. HDD always passes
6891 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306892 * @bpf_get_offload: struct for get offload
6893 *
6894 * This function receives the response/data from the lower layer and
6895 * checks to see if the thread is still waiting then post the results to
6896 * upper layer, if the request has timed out then ignore.
6897 *
6898 * Return: None
6899 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006900static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006901 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306902{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006903 struct hdd_request *request;
6904 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306905
6906 ENTER();
6907
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006908 request = hdd_request_get(context);
6909 if (!request) {
6910 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306911 return;
6912 }
6913
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006914 priv = hdd_request_priv(request);
6915 priv->bpf_get_offload = *data;
6916 hdd_request_complete(request);
6917 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306918}
6919
6920/**
6921 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6922 * @hdd_context: hdd_context
6923 * @bpf_get_offload: struct for get offload
6924 *
6925 * Return: 0 on success, error number otherwise.
6926 */
6927static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6928 struct sir_bpf_get_offload *bpf_get_offload)
6929{
6930 struct sk_buff *skb;
6931 uint32_t nl_buf_len;
6932
6933 ENTER();
6934
6935 nl_buf_len = NLMSG_HDRLEN;
6936 nl_buf_len +=
6937 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6938 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6939
6940 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6941 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006942 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306943 return -ENOMEM;
6944 }
6945
Jeff Johnson77848112016-06-29 14:52:06 -07006946 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306947 bpf_get_offload->bpf_version,
6948 bpf_get_offload->max_bytes_for_bpf_inst);
6949
6950 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6951 bpf_get_offload->max_bytes_for_bpf_inst) ||
6952 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006953 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306954 goto nla_put_failure;
6955 }
6956
6957 cfg80211_vendor_cmd_reply(skb);
6958 EXIT();
6959 return 0;
6960
6961nla_put_failure:
6962 kfree_skb(skb);
6963 return -EINVAL;
6964}
6965
6966/**
6967 * hdd_get_bpf_offload - Get BPF offload Capabilities
6968 * @hdd_ctx: Hdd context
6969 *
6970 * Return: 0 on success, errno on failure
6971 */
6972static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6973{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306974 QDF_STATUS status;
6975 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006976 void *cookie;
6977 struct hdd_request *request;
6978 struct bpf_offload_priv *priv;
6979 static const struct hdd_request_params params = {
6980 .priv_size = sizeof(*priv),
6981 .timeout_ms = WLAN_WAIT_TIME_BPF,
6982 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983
6984 ENTER();
6985
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006986 request = hdd_request_alloc(&params);
6987 if (!request) {
6988 hdd_err("Unable to allocate request");
6989 return -EINVAL;
6990 }
6991 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306992
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006993 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6994 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006995 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306996 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006997 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006998 ret = qdf_status_to_os_return(status);
6999 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007001 ret = hdd_request_wait_for_response(request);
7002 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007003 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007004 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307005 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007006 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307007 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007008 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307009 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007010 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307011
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007012cleanup:
7013 /*
7014 * either we never sent a request to SME, we sent a request to
7015 * SME and timed out, or we sent a request to SME, received a
7016 * response from SME, and posted the response to userspace.
7017 * regardless we are done with the request.
7018 */
7019 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307020 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007021
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307022 return ret;
7023}
7024
7025/**
7026 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7027 * @hdd_ctx: Hdd context
7028 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307029 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307030 *
7031 * Return: 0 on success; errno on failure
7032 */
7033static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7034 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307035 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307036{
7037 struct sir_bpf_set_offload *bpf_set_offload;
7038 QDF_STATUS status;
7039 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307040 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307041
7042 ENTER();
7043
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307044 if (adapter->device_mode == QDF_STA_MODE ||
7045 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7046 if (!hdd_conn_is_connected(
7047 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7048 hdd_err("Not in Connected state!");
7049 return -ENOTSUPP;
7050 }
7051 }
7052
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307053 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7054 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007055 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307056 return -ENOMEM;
7057 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307058
7059 /* Parse and fetch bpf packet size */
7060 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007061 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307062 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307063 goto fail;
7064 }
7065 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7066
7067 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007068 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307069 goto post_sme;
7070 }
7071
7072 /* Parse and fetch bpf program */
7073 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007074 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307075 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076 goto fail;
7077 }
7078
7079 prog_len = nla_len(tb[BPF_PROGRAM]);
7080 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307081
7082 if (bpf_set_offload->program == NULL) {
7083 hdd_err("qdf_mem_malloc failed for bpf offload program");
7084 ret = -ENOMEM;
7085 goto fail;
7086 }
7087
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307088 bpf_set_offload->current_length = prog_len;
7089 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307090 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307091
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307092 hdd_info("BPF set instructions");
7093 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7094 bpf_set_offload->program, prog_len);
7095
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307096 /* Parse and fetch filter Id */
7097 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007098 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307099 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307100 goto fail;
7101 }
7102 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7103
7104 /* Parse and fetch current offset */
7105 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007106 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307107 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108 goto fail;
7109 }
7110 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7111
7112post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007113 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 +05307114 bpf_set_offload->session_id,
7115 bpf_set_offload->version,
7116 bpf_set_offload->filter_id,
7117 bpf_set_offload->total_length,
7118 bpf_set_offload->current_length,
7119 bpf_set_offload->current_offset);
7120
7121 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7122 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007123 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307124 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307125 goto fail;
7126 }
7127 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307128
7129fail:
7130 if (bpf_set_offload->current_length)
7131 qdf_mem_free(bpf_set_offload->program);
7132 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307133 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307134}
7135
7136/**
7137 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7138 * @wiphy: wiphy structure pointer
7139 * @wdev: Wireless device structure pointer
7140 * @data: Pointer to the data received
7141 * @data_len: Length of @data
7142 *
7143 * Return: 0 on success; errno on failure
7144 */
7145static int
7146__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7147 struct wireless_dev *wdev,
7148 const void *data, int data_len)
7149{
7150 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7151 struct net_device *dev = wdev->netdev;
7152 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7153 struct nlattr *tb[BPF_MAX + 1];
7154 int ret_val, packet_filter_subcmd;
7155
7156 ENTER();
7157
7158 ret_val = wlan_hdd_validate_context(hdd_ctx);
7159 if (ret_val)
7160 return ret_val;
7161
7162 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007163 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307164 return -EINVAL;
7165 }
7166
7167 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007168 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307169 return -ENOTSUPP;
7170 }
7171
7172 if (nla_parse(tb, BPF_MAX, data, data_len,
7173 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007174 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307175 return -EINVAL;
7176 }
7177
7178 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007179 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307180 return -EINVAL;
7181 }
7182
7183 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7184
7185 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7186 return hdd_get_bpf_offload(hdd_ctx);
7187 else
7188 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307189 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307190}
7191
7192/**
7193 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7194 * @wiphy: wiphy structure pointer
7195 * @wdev: Wireless device structure pointer
7196 * @data: Pointer to the data received
7197 * @data_len: Length of @data
7198 *
7199 * Return: 0 on success; errno on failure
7200 */
7201
7202static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7203 struct wireless_dev *wdev,
7204 const void *data, int data_len)
7205{
7206 int ret;
7207
7208 cds_ssr_protect(__func__);
7209 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7210 cds_ssr_unprotect(__func__);
7211
7212 return ret;
7213}
7214
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307215/**
7216 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7217 * @pre_cac_adapter: AP adapter used for pre cac
7218 * @status: Status (true or false)
7219 * @handle: Global handle
7220 *
7221 * Sets the status of pre cac i.e., whether the pre cac is active or not
7222 *
7223 * Return: Zero on success, non-zero on failure
7224 */
7225static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7226 bool status, tHalHandle handle)
7227{
7228 QDF_STATUS ret;
7229
7230 ret = wlan_sap_set_pre_cac_status(
7231 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7232 if (QDF_IS_STATUS_ERROR(ret))
7233 return -EINVAL;
7234
7235 return 0;
7236}
7237
7238/**
7239 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7240 * @ap_adapter: AP adapter
7241 * @chan_before_pre_cac: Channel
7242 *
7243 * Saves the channel which the AP was beaconing on before moving to the pre
7244 * cac channel. If radar is detected on the pre cac channel, this saved
7245 * channel will be used for AP operations.
7246 *
7247 * Return: Zero on success, non-zero on failure
7248 */
7249static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7250 uint8_t chan_before_pre_cac)
7251{
7252 QDF_STATUS ret;
7253
7254 ret = wlan_sap_set_chan_before_pre_cac(
7255 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7256 if (QDF_IS_STATUS_ERROR(ret))
7257 return -EINVAL;
7258
7259 return 0;
7260}
7261
7262/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307263 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7264 * are in nol list from provided channel list
7265 * @adapter: AP adapter
7266 * @channel_count: channel count
7267 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307268 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307269 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307270 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307271static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7272 uint32_t *channel_count,
7273 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307274{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307275 uint8_t i, j;
7276 uint32_t nol_len = 0;
7277 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7278 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7279 uint32_t chan_count;
7280 bool found;
7281 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307282
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307283 if (!hdd_ctx) {
7284 hdd_err("hdd ctx not found");
7285 *channel_count = 0;
7286 return;
7287 }
7288
7289 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7290 hdd_err("invalid channel count %d", *channel_count);
7291 return;
7292 }
7293
7294 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7295 if (nol_len == 0)
7296 return;
7297
7298 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7299 chan_count = *channel_count;
7300 qdf_mem_zero(channel_list, chan_count);
7301 *channel_count = 0;
7302
7303 for (i = 0 ; i < chan_count; i++) {
7304 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7305 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7306 continue;
7307 found = false;
7308 for (j = 0; j < nol_len; j++) {
7309 if (tmp_chan_list[i] == nol[j]) {
7310 found = true;
7311 hdd_notice("skipped channel %d due to nol",
7312 nol[j]);
7313 break;
7314 }
7315 }
7316 if (!found) {
7317 channel_list[*channel_count] = tmp_chan_list[i];
7318 *channel_count = *channel_count + 1;
7319 }
7320 }
7321}
7322
7323int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7324 uint32_t *channel_count,
7325 uint8_t *channel_list)
7326{
7327 tsap_Config_t *sap_config;
7328
7329 sap_config = &adapter->sessionCtx.ap.sapConfig;
7330
7331 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7332 sap_config->acs_cfg.ch_list_count);
7333 *channel_count = sap_config->acs_cfg.ch_list_count;
7334 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7335
7336 if (*channel_count == 0) {
7337 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307338 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307339 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307340
7341 return 0;
7342}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307343
7344/**
7345 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7346 * @hdd_ctx: HDD context
7347 * @ap_adapter: AP adapter
7348 * @channel: Channel requested by userspace
7349 * @pre_cac_chan: Pointer to the pre CAC channel
7350 *
7351 * Validates the channel provided by userspace. If user provided channel 0,
7352 * a valid outdoor channel must be selected from the regulatory channel.
7353 *
7354 * Return: Zero on success and non zero value on error
7355 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007356static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7357 hdd_adapter_t *ap_adapter,
7358 uint8_t channel,
7359 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307360{
7361 uint32_t i, j;
7362 QDF_STATUS status;
7363 int ret;
7364 uint8_t nol[QDF_MAX_NUM_CHAN];
7365 uint32_t nol_len = 0, weight_len = 0;
7366 bool found;
7367 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7368 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7369 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7370
7371 if (0 == channel) {
7372 /* Channel is not obtained from PCL because PCL may not have
7373 * the entire channel list. For example: if SAP is up on
7374 * channel 6 and PCL is queried for the next SAP interface,
7375 * if SCC is preferred, the PCL will contain only the channel
7376 * 6. But, we are in need of a DFS channel. So, going with the
7377 * first channel from the valid channel list.
7378 */
7379 status = cds_get_valid_chans(channel_list, &len);
7380 if (QDF_IS_STATUS_ERROR(status)) {
7381 hdd_err("Failed to get channel list");
7382 return -EINVAL;
7383 }
7384 cds_update_with_safe_channel_list(channel_list, &len,
7385 pcl_weights, weight_len);
7386 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7387 for (i = 0; i < len; i++) {
7388 found = false;
7389 for (j = 0; j < nol_len; j++) {
7390 if (channel_list[i] == nol[j]) {
7391 found = true;
7392 break;
7393 }
7394 }
7395 if (found)
7396 continue;
7397 if (CDS_IS_DFS_CH(channel_list[i])) {
7398 *pre_cac_chan = channel_list[i];
7399 break;
7400 }
7401 }
7402 if (*pre_cac_chan == 0) {
7403 hdd_err("unable to find outdoor channel");
7404 return -EINVAL;
7405 }
7406 } else {
7407 /* Only when driver selects a channel, check is done for
7408 * unnsafe and NOL channels. When user provides a fixed channel
7409 * the user is expected to take care of this.
7410 */
7411 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7412 !CDS_IS_DFS_CH(channel)) {
7413 hdd_err("Invalid channel for pre cac:%d", channel);
7414 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307415 }
Jeff Johnson68755312017-02-10 11:46:55 -08007416
7417 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307418 }
7419 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7420 return 0;
7421}
7422
7423/**
7424 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7425 * @channel: Channel option provided by userspace
7426 *
7427 * Sets the driver to the required hardware mode and start an adapater for
7428 * pre CAC which will mimic an AP.
7429 *
7430 * Return: Zero on success, non-zero value on error
7431 */
7432int wlan_hdd_request_pre_cac(uint8_t channel)
7433{
Krunal Sonib37bb352016-12-20 14:12:21 -08007434 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307435 hdd_context_t *hdd_ctx;
7436 int ret;
7437 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7438 hdd_ap_ctx_t *hdd_ap_ctx;
7439 QDF_STATUS status;
7440 struct wiphy *wiphy;
7441 struct net_device *dev;
7442 struct cfg80211_chan_def chandef;
7443 enum nl80211_channel_type channel_type;
7444 uint32_t freq;
7445 struct ieee80211_channel *chan;
7446 tHalHandle handle;
7447 bool val;
7448
7449 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7450 if (0 != wlan_hdd_validate_context(hdd_ctx))
7451 return -EINVAL;
7452
7453 if (cds_get_connection_count() > 1) {
7454 hdd_err("pre cac not allowed in concurrency");
7455 return -EINVAL;
7456 }
7457
7458 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7459 if (!ap_adapter) {
7460 hdd_err("unable to get SAP adapter");
7461 return -EINVAL;
7462 }
7463
7464 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7465 if (!handle) {
7466 hdd_err("Invalid handle");
7467 return -EINVAL;
7468 }
7469
7470 val = wlan_sap_is_pre_cac_active(handle);
7471 if (val) {
7472 hdd_err("pre cac is already in progress");
7473 return -EINVAL;
7474 }
7475
7476 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7477 if (!hdd_ap_ctx) {
7478 hdd_err("SAP context is NULL");
7479 return -EINVAL;
7480 }
7481
7482 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7483 hdd_err("SAP is already on DFS channel:%d",
7484 hdd_ap_ctx->operatingChannel);
7485 return -EINVAL;
7486 }
7487
7488 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7489 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7490 hdd_ap_ctx->operatingChannel);
7491 return -EINVAL;
7492 }
7493
Krunal Sonib37bb352016-12-20 14:12:21 -08007494 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7495 if (!mac_addr) {
7496 hdd_err("can't add virtual intf: Not getting valid mac addr");
7497 return -EINVAL;
7498 }
7499
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307500 hdd_info("channel:%d", channel);
7501
7502 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7503 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007504 if (ret != 0) {
7505 hdd_err("can't validate pre-cac channel");
7506 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307507 }
7508
7509 hdd_debug("starting pre cac SAP adapter");
7510
7511 /* Starting a SAP adapter:
7512 * Instead of opening an adapter, we could just do a SME open session
7513 * for AP type. But, start BSS would still need an adapter.
7514 * So, this option is not taken.
7515 *
7516 * hdd open adapter is going to register this precac interface with
7517 * user space. This interface though exposed to user space will be in
7518 * DOWN state. Consideration was done to avoid this registration to the
7519 * user space. But, as part of SAP operations multiple events are sent
7520 * to user space. Some of these events received from unregistered
7521 * interface was causing crashes. So, retaining the registration.
7522 *
7523 * So, this interface would remain registered and will remain in DOWN
7524 * state for the CAC duration. We will add notes in the feature
7525 * announcement to not use this temporary interface for any activity
7526 * from user space.
7527 */
7528 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007529 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307530 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307531 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007532 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307533 }
7534
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307535 /*
7536 * This interface is internally created by the driver. So, no interface
7537 * up comes for this interface from user space and hence starting
7538 * the adapter internally.
7539 */
7540 if (hdd_start_adapter(pre_cac_adapter)) {
7541 hdd_err("error starting the pre cac adapter");
7542 goto close_pre_cac_adapter;
7543 }
7544
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307545 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7546
7547 wiphy = hdd_ctx->wiphy;
7548 dev = pre_cac_adapter->dev;
7549
7550 /* Since this is only a dummy interface lets us use the IEs from the
7551 * other active SAP interface. In regular scenarios, these IEs would
7552 * come from the user space entity
7553 */
7554 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7555 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7556 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7557 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307558 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307559 }
7560 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7561 ap_adapter->sessionCtx.ap.beacon,
7562 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7563 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7564 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7565 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7566 ap_adapter->sessionCtx.ap.sapConfig.authType;
7567
7568 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7569 * to operate on the same bandwidth as that of the 2.4GHz operations.
7570 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7571 */
7572 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7573 case CH_WIDTH_20MHZ:
7574 channel_type = NL80211_CHAN_HT20;
7575 break;
7576 case CH_WIDTH_40MHZ:
7577 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7578 ap_adapter->sessionCtx.ap.sapConfig.channel)
7579 channel_type = NL80211_CHAN_HT40PLUS;
7580 else
7581 channel_type = NL80211_CHAN_HT40MINUS;
7582 break;
7583 default:
7584 channel_type = NL80211_CHAN_NO_HT;
7585 break;
7586 }
7587
7588 freq = cds_chan_to_freq(pre_cac_chan);
7589 chan = __ieee80211_get_channel(wiphy, freq);
7590 if (!chan) {
7591 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307592 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307593 }
7594
7595 cfg80211_chandef_create(&chandef, chan, channel_type);
7596
7597 hdd_debug("orig width:%d channel_type:%d freq:%d",
7598 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7599 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007600 /*
7601 * Doing update after opening and starting pre-cac adapter will make
7602 * sure that driver won't do hardware mode change if there are any
7603 * initial hick-ups or issues in pre-cac adapter's configuration.
7604 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7605 * connection update should result in DBS mode
7606 */
7607 status = cds_update_and_wait_for_connection_update(
7608 ap_adapter->sessionId,
7609 pre_cac_chan,
7610 SIR_UPDATE_REASON_PRE_CAC);
7611 if (QDF_IS_STATUS_ERROR(status)) {
7612 hdd_err("error in moving to DBS mode");
7613 goto stop_close_pre_cac_adapter;
7614 }
7615
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307616
7617 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7618 if (0 != ret) {
7619 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307620 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307621 }
7622
7623 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7624 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007625 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307626 if (QDF_IS_STATUS_ERROR(status)) {
7627 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307628 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307629 }
7630
7631 /*
7632 * The pre cac status is set here. But, it would not be reset explicitly
7633 * anywhere, since after the pre cac success/failure, the pre cac
7634 * adapter itself would be removed.
7635 */
7636 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7637 if (0 != ret) {
7638 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307639 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307640 }
7641
7642 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7643 hdd_ap_ctx->operatingChannel);
7644 if (0 != ret) {
7645 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307646 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307647 }
7648
7649 ap_adapter->pre_cac_chan = pre_cac_chan;
7650
7651 return 0;
7652
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307653stop_close_pre_cac_adapter:
7654 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307655 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7656 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307657close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307658 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007659release_intf_addr_and_return_failure:
7660 /*
7661 * Release the interface address as the adapter
7662 * failed to start, if you don't release then next
7663 * adapter which is trying to come wouldn't get valid
7664 * mac address. Remember we have limited pool of mac addresses
7665 */
7666 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307667 return -EINVAL;
7668}
7669
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307670static const struct nla_policy
7671wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7672 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7673};
7674
Agrawal Ashish65634612016-08-18 13:24:32 +05307675static const struct nla_policy
7676wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7677 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7678 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7679};
7680
7681/**
7682 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7683 * @wiphy: Pointer to wireless phy
7684 * @wdev: Pointer to wireless device
7685 * @data: Pointer to data
7686 * @data_len: Length of @data
7687 *
7688 * This function parses the incoming NL vendor command data attributes and
7689 * updates the SAP context about channel_hint and DFS mode.
7690 * If channel_hint is set, SAP will choose that channel
7691 * as operating channel.
7692 *
7693 * If DFS mode is enabled, driver will include DFS channels
7694 * in ACS else driver will skip DFS channels.
7695 *
7696 * Return: 0 on success, negative errno on failure
7697 */
7698static int
7699__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7700 struct wireless_dev *wdev,
7701 const void *data, int data_len)
7702{
7703 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7704 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7705 int ret;
7706 struct acs_dfs_policy *acs_policy;
7707 int mode = DFS_MODE_NONE;
7708 int channel_hint = 0;
7709
7710 ENTER_DEV(wdev->netdev);
7711
7712 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7713 hdd_err("Command not allowed in FTM mode");
7714 return -EINVAL;
7715 }
7716
7717 ret = wlan_hdd_validate_context(hdd_ctx);
7718 if (0 != ret)
7719 return ret;
7720
7721 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7722 data, data_len,
7723 wlan_hdd_set_acs_dfs_config_policy)) {
7724 hdd_err("invalid attr");
7725 return -EINVAL;
7726 }
7727
7728 acs_policy = &hdd_ctx->acs_policy;
7729 /*
7730 * SCM sends this attribute to restrict SAP from choosing
7731 * DFS channels from ACS.
7732 */
7733 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7734 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7735
7736 if (!IS_DFS_MODE_VALID(mode)) {
7737 hdd_err("attr acs dfs mode is not valid");
7738 return -EINVAL;
7739 }
7740 acs_policy->acs_dfs_mode = mode;
7741
7742 /*
7743 * SCM sends this attribute to provide an active channel,
7744 * to skip redundant ACS between drivers, and save driver start up time
7745 */
7746 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7747 channel_hint = nla_get_u8(
7748 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7749
7750 if (!IS_CHANNEL_VALID(channel_hint)) {
7751 hdd_err("acs channel is not valid");
7752 return -EINVAL;
7753 }
7754 acs_policy->acs_channel = channel_hint;
7755
7756 return 0;
7757}
7758
7759/**
7760 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7761 * @wiphy: wiphy structure pointer
7762 * @wdev: Wireless device structure pointer
7763 * @data: Pointer to the data received
7764 * @data_len: Length of @data
7765 *
7766 * This function parses the incoming NL vendor command data attributes and
7767 * updates the SAP context about channel_hint and DFS mode.
7768 *
7769 * Return: 0 on success; errno on failure
7770 */
7771static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7772 struct wireless_dev *wdev,
7773 const void *data, int data_len)
7774{
7775 int ret;
7776
7777 cds_ssr_protect(__func__);
7778 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7779 cds_ssr_unprotect(__func__);
7780
7781 return ret;
7782}
7783
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307784/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307785 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7786 * @mode : cfg80211 dfs mode
7787 *
7788 * Return: return csr sta roam dfs mode else return NONE
7789 */
7790static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7791 enum dfs_mode mode)
7792{
7793 switch (mode) {
7794 case DFS_MODE_ENABLE:
7795 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7796 break;
7797 case DFS_MODE_DISABLE:
7798 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7799 break;
7800 case DFS_MODE_DEPRIORITIZE:
7801 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7802 break;
7803 default:
7804 hdd_err("STA Roam policy dfs mode is NONE");
7805 return CSR_STA_ROAM_POLICY_NONE;
7806 }
7807}
7808
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307809/*
7810 * hdd_get_sap_operating_band: Get current operating channel
7811 * for sap.
7812 * @hdd_ctx: hdd context
7813 *
7814 * Return : Corresponding band for SAP operating channel
7815 */
7816uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7817{
7818 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7819 QDF_STATUS status;
7820 hdd_adapter_t *adapter;
7821 uint8_t operating_channel = 0;
7822 uint8_t sap_operating_band = 0;
7823 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7824 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7825 adapter = adapter_node->pAdapter;
7826
7827 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7828 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7829 &next);
7830 adapter_node = next;
7831 continue;
7832 }
7833 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7834 if (IS_24G_CH(operating_channel))
7835 sap_operating_band = eCSR_BAND_24;
7836 else if (IS_5G_CH(operating_channel))
7837 sap_operating_band = eCSR_BAND_5G;
7838 else
7839 sap_operating_band = eCSR_BAND_ALL;
7840 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7841 &next);
bings373b99b2017-01-23 10:35:08 +08007842 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307843 }
7844 return sap_operating_band;
7845}
7846
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307847static const struct nla_policy
7848wlan_hdd_set_sta_roam_config_policy[
7849QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7850 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7851 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7852};
7853
7854/**
7855 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7856 * for station connection or roaming.
7857 * @wiphy: Pointer to wireless phy
7858 * @wdev: Pointer to wireless device
7859 * @data: Pointer to data
7860 * @data_len: Length of @data
7861 *
7862 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7863 * channels needs to be skipped in scanning or not.
7864 * If dfs_mode is disabled, driver will not scan DFS channels.
7865 * If skip_unsafe_channels is set, driver will skip unsafe channels
7866 * in Scanning.
7867 *
7868 * Return: 0 on success, negative errno on failure
7869 */
7870static int
7871__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7872 struct wireless_dev *wdev,
7873 const void *data, int data_len)
7874{
7875 struct net_device *dev = wdev->netdev;
7876 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7877 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7878 struct nlattr *tb[
7879 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7880 int ret;
7881 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7882 enum dfs_mode mode = DFS_MODE_NONE;
7883 bool skip_unsafe_channels = false;
7884 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307885 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307886
7887 ENTER_DEV(dev);
7888
7889 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7890 hdd_err("Command not allowed in FTM mode");
7891 return -EINVAL;
7892 }
7893
7894 ret = wlan_hdd_validate_context(hdd_ctx);
7895 if (0 != ret)
7896 return ret;
7897 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7898 data, data_len,
7899 wlan_hdd_set_sta_roam_config_policy)) {
7900 hdd_err("invalid attr");
7901 return -EINVAL;
7902 }
7903 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7904 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7905 if (!IS_DFS_MODE_VALID(mode)) {
7906 hdd_err("attr sta roam dfs mode policy is not valid");
7907 return -EINVAL;
7908 }
7909
7910 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7911
7912 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7913 skip_unsafe_channels = nla_get_u8(
7914 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307915 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307916 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307917 skip_unsafe_channels, adapter->sessionId,
7918 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307919
7920 if (!QDF_IS_STATUS_SUCCESS(status)) {
7921 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7922 return -EINVAL;
7923 }
7924 return 0;
7925}
7926
7927/**
7928 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7929 * connection and roaming for station.
7930 * @wiphy: wiphy structure pointer
7931 * @wdev: Wireless device structure pointer
7932 * @data: Pointer to the data received
7933 * @data_len: Length of @data
7934 *
7935 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7936 * channels needs to be skipped in scanning or not.
7937 * If dfs_mode is disabled, driver will not scan DFS channels.
7938 * If skip_unsafe_channels is set, driver will skip unsafe channels
7939 * in Scanning.
7940 * Return: 0 on success; errno on failure
7941 */
7942static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7943 struct wireless_dev *wdev,
7944 const void *data, int data_len)
7945{
7946 int ret;
7947
7948 cds_ssr_protect(__func__);
7949 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7950 cds_ssr_unprotect(__func__);
7951
7952 return ret;
7953}
7954
Agrawal Ashish467dde42016-09-08 18:44:22 +05307955#ifdef FEATURE_WLAN_CH_AVOID
7956/**
7957 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7958 * is on unsafe channel.
7959 * @wiphy: wiphy structure pointer
7960 * @wdev: Wireless device structure pointer
7961 * @data: Pointer to the data received
7962 * @data_len: Length of @data
7963 *
7964 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7965 * on any of unsafe channels.
7966 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7967 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7968 *
7969 * Return: 0 on success; errno on failure
7970 */
7971static int
7972__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7973 struct wireless_dev *wdev,
7974 const void *data, int data_len)
7975{
7976 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7977 int ret;
7978 uint16_t unsafe_channel_count;
7979 int unsafe_channel_index;
7980 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7981
7982 ENTER_DEV(wdev->netdev);
7983
7984 if (!qdf_ctx) {
7985 cds_err("qdf_ctx is NULL");
7986 return -EINVAL;
7987 }
7988
7989 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7990 hdd_err("Command not allowed in FTM mode");
7991 return -EINVAL;
7992 }
7993
7994 ret = wlan_hdd_validate_context(hdd_ctx);
7995 if (0 != ret)
7996 return ret;
7997 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7998 &(hdd_ctx->unsafe_channel_count),
7999 sizeof(hdd_ctx->unsafe_channel_list));
8000
8001 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8002 (uint16_t)NUM_CHANNELS);
8003 for (unsafe_channel_index = 0;
8004 unsafe_channel_index < unsafe_channel_count;
8005 unsafe_channel_index++) {
8006 hdd_info("Channel %d is not safe",
8007 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8008 }
8009 hdd_unsafe_channel_restart_sap(hdd_ctx);
8010 return 0;
8011}
8012
8013/**
8014 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8015 * is on unsafe channel.
8016 * @wiphy: wiphy structure pointer
8017 * @wdev: Wireless device structure pointer
8018 * @data: Pointer to the data received
8019 * @data_len: Length of @data
8020 *
8021 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8022 * on any of unsafe channels.
8023 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8024 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8025 *
8026 * Return: 0 on success; errno on failure
8027 */
8028static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8029 struct wireless_dev *wdev,
8030 const void *data, int data_len)
8031{
8032 int ret;
8033
8034 cds_ssr_protect(__func__);
8035 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8036 cds_ssr_unprotect(__func__);
8037
8038 return ret;
8039}
8040
8041#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308042/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308043 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8044 * SAP is on unsafe channel.
8045 * @wiphy: wiphy structure pointer
8046 * @wdev: Wireless device structure pointer
8047 * @data: Pointer to the data received
8048 * @data_len: Length of @data
8049 *
8050 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8051 * driver.
8052 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8053 * will initiate restart of sap.
8054 *
8055 * Return: 0 on success; errno on failure
8056 */
8057static int
8058__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8059 struct wireless_dev *wdev,
8060 const void *data, int data_len)
8061{
8062 struct net_device *ndev = wdev->netdev;
8063 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8064 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8065 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8066 uint8_t config_channel = 0;
8067 hdd_ap_ctx_t *ap_ctx;
8068 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308069 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308070
8071 ENTER();
8072
8073 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008074 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308075 return -EINVAL;
8076 }
8077
8078 ret = wlan_hdd_validate_context(hdd_ctx);
8079 if (0 != ret)
8080 return -EINVAL;
8081
8082 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8083 data, data_len,
8084 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008085 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308086 return -EINVAL;
8087 }
8088
8089 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8090 if (!test_bit(SOFTAP_BSS_STARTED,
8091 &hostapd_adapter->event_flags)) {
8092 hdd_err("SAP is not started yet. Restart sap will be invalid");
8093 return -EINVAL;
8094 }
8095
8096 config_channel =
8097 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8098
8099 if (!((IS_24G_CH(config_channel)) ||
8100 (IS_5G_CH(config_channel)))) {
8101 hdd_err("Channel %d is not valid to restart SAP",
8102 config_channel);
8103 return -ENOTSUPP;
8104 }
8105
8106 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8107 ap_ctx->sapConfig.channel = config_channel;
8108 ap_ctx->sapConfig.ch_params.ch_width =
8109 ap_ctx->sapConfig.ch_width_orig;
8110
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008111 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308112 ap_ctx->sapConfig.sec_ch,
8113 &ap_ctx->sapConfig.ch_params);
8114
8115 cds_restart_sap(hostapd_adapter);
8116 }
8117
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308118 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8119 uint32_t freq_len, i;
8120 uint32_t *freq;
8121 uint8_t chans[QDF_MAX_NUM_CHAN];
8122
8123 hdd_debug("setting mandatory freq/chan list");
8124
8125 freq_len = nla_len(
8126 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8127 sizeof(uint32_t);
8128
8129 if (freq_len > QDF_MAX_NUM_CHAN) {
8130 hdd_err("insufficient space to hold channels");
8131 return -ENOMEM;
8132 }
8133
8134 freq = nla_data(
8135 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8136
8137 hdd_debug("freq_len=%d", freq_len);
8138
8139 for (i = 0; i < freq_len; i++) {
8140 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8141 hdd_debug("freq[%d]=%d", i, freq[i]);
8142 }
8143
8144 status = cds_set_sap_mandatory_channels(chans, freq_len);
8145 if (QDF_IS_STATUS_ERROR(status))
8146 return -EINVAL;
8147 }
8148
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308149 return 0;
8150}
8151
8152/**
8153 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8154 * @wiphy: wiphy structure pointer
8155 * @wdev: Wireless device structure pointer
8156 * @data: Pointer to the data received
8157 * @data_len: Length of @data
8158 *
8159 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8160 * driver.
8161 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8162 * will initiate restart of sap.
8163 *
8164 * Return: 0 on success; errno on failure
8165 */
8166static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8167 struct wireless_dev *wdev,
8168 const void *data, int data_len)
8169{
8170 int ret;
8171
8172 cds_ssr_protect(__func__);
8173 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8174 wdev, data, data_len);
8175 cds_ssr_unprotect(__func__);
8176
8177 return ret;
8178}
8179
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308180#undef BPF_INVALID
8181#undef BPF_SET_RESET
8182#undef BPF_VERSION
8183#undef BPF_ID
8184#undef BPF_PACKET_SIZE
8185#undef BPF_CURRENT_OFFSET
8186#undef BPF_PROGRAM
8187#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308188
8189/**
8190 * define short names for the global vendor params
8191 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8192 */
8193#define PARAM_TOTAL_CMD_EVENT_WAKE \
8194 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8195#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8196 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8197#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8198 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8199#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8200 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8201#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8202 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8203#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8204 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8205#define PARAM_TOTAL_RX_DATA_WAKE \
8206 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8207#define PARAM_RX_UNICAST_CNT \
8208 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8209#define PARAM_RX_MULTICAST_CNT \
8210 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8211#define PARAM_RX_BROADCAST_CNT \
8212 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8213#define PARAM_ICMP_PKT \
8214 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8215#define PARAM_ICMP6_PKT \
8216 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8217#define PARAM_ICMP6_RA \
8218 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8219#define PARAM_ICMP6_NA \
8220 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8221#define PARAM_ICMP6_NS \
8222 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8223#define PARAM_ICMP4_RX_MULTICAST_CNT \
8224 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8225#define PARAM_ICMP6_RX_MULTICAST_CNT \
8226 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8227#define PARAM_OTHER_RX_MULTICAST_CNT \
8228 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308229#define PARAM_RSSI_BREACH_CNT \
8230 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8231#define PARAM_LOW_RSSI_CNT \
8232 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8233#define PARAM_GSCAN_CNT \
8234 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8235#define PARAM_PNO_COMPLETE_CNT \
8236 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8237#define PARAM_PNO_MATCH_CNT \
8238 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8239
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308240
8241
8242/**
8243 * hdd_send_wakelock_stats() - API to send wakelock stats
8244 * @ctx: context to be passed to callback
8245 * @data: data passed to callback
8246 *
8247 * This function is used to send wake lock stats to HAL layer
8248 *
8249 * Return: 0 on success, error number otherwise.
8250 */
8251static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8252 const struct sir_wake_lock_stats *data)
8253{
8254 struct sk_buff *skb;
8255 uint32_t nl_buf_len;
8256 uint32_t total_rx_data_wake, rx_multicast_cnt;
8257 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308258 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308259
8260 ENTER();
8261
8262 nl_buf_len = NLMSG_HDRLEN;
8263 nl_buf_len +=
8264 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8265 (NLMSG_HDRLEN + sizeof(uint32_t));
8266
8267 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8268
8269 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008270 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308271 return -ENOMEM;
8272 }
8273
Jeff Johnson64943bd2016-08-23 13:14:06 -07008274 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308275 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008276 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308277 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008278 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308279 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008280 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308281 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008282 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308283 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008284 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308285 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008286 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008288 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8289 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308290 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308291 hdd_info("wow_rssi_breach_wake_up_count %d",
8292 data->wow_rssi_breach_wake_up_count);
8293 hdd_info("wow_low_rssi_wake_up_count %d",
8294 data->wow_low_rssi_wake_up_count);
8295 hdd_info("wow_gscan_wake_up_count %d",
8296 data->wow_gscan_wake_up_count);
8297 hdd_info("wow_pno_complete_wake_up_count %d",
8298 data->wow_pno_complete_wake_up_count);
8299 hdd_info("wow_pno_match_wake_up_count %d",
8300 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308301
8302 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308303 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308304
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308305 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308306 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308307
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308308 rx_multicast_cnt =
8309 data->wow_ipv4_mcast_wake_up_count +
8310 ipv6_rx_multicast_addr_cnt;
8311
8312 total_rx_data_wake =
8313 data->wow_ucast_wake_up_count +
8314 data->wow_bcast_wake_up_count +
8315 rx_multicast_cnt;
8316
8317 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8318 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8319 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8320 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8321 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8322 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8323 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8324 total_rx_data_wake) ||
8325 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8326 data->wow_ucast_wake_up_count) ||
8327 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8328 rx_multicast_cnt) ||
8329 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8330 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308331 nla_put_u32(skb, PARAM_ICMP_PKT,
8332 data->wow_icmpv4_count) ||
8333 nla_put_u32(skb, PARAM_ICMP6_PKT,
8334 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308335 nla_put_u32(skb, PARAM_ICMP6_RA,
8336 data->wow_ipv6_mcast_ra_stats) ||
8337 nla_put_u32(skb, PARAM_ICMP6_NA,
8338 data->wow_ipv6_mcast_na_stats) ||
8339 nla_put_u32(skb, PARAM_ICMP6_NS,
8340 data->wow_ipv6_mcast_ns_stats) ||
8341 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8342 data->wow_ipv4_mcast_wake_up_count) ||
8343 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8344 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308345 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8346 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8347 data->wow_rssi_breach_wake_up_count) ||
8348 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8349 data->wow_low_rssi_wake_up_count) ||
8350 nla_put_u32(skb, PARAM_GSCAN_CNT,
8351 data->wow_gscan_wake_up_count) ||
8352 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8353 data->wow_pno_complete_wake_up_count) ||
8354 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8355 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008356 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308357 goto nla_put_failure;
8358 }
8359
8360 cfg80211_vendor_cmd_reply(skb);
8361
8362 EXIT();
8363 return 0;
8364
8365nla_put_failure:
8366 kfree_skb(skb);
8367 return -EINVAL;
8368}
8369
8370/**
8371 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8372 * @wiphy: wiphy pointer
8373 * @wdev: pointer to struct wireless_dev
8374 * @data: pointer to incoming NL vendor data
8375 * @data_len: length of @data
8376 *
8377 * This function parses the incoming NL vendor command data attributes and
8378 * invokes the SME Api and blocks on a completion variable.
8379 * WMA copies required data and invokes callback
8380 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8381 *
8382 * Return: 0 on success; error number otherwise.
8383 */
8384static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8385 struct wireless_dev *wdev,
8386 const void *data,
8387 int data_len)
8388{
8389 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8390 int status, ret;
8391 struct sir_wake_lock_stats wake_lock_stats;
8392 QDF_STATUS qdf_status;
8393
8394 ENTER();
8395
8396 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008397 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308398 return -EINVAL;
8399 }
8400
8401 status = wlan_hdd_validate_context(hdd_ctx);
8402 if (0 != status)
8403 return -EINVAL;
8404
8405 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8406 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008407 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308408 return -EINVAL;
8409 }
8410
8411 ret = hdd_send_wakelock_stats(hdd_ctx,
8412 &wake_lock_stats);
8413 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008414 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308415
8416 EXIT();
8417 return ret;
8418}
8419
8420/**
8421 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8422 * @wiphy: wiphy pointer
8423 * @wdev: pointer to struct wireless_dev
8424 * @data: pointer to incoming NL vendor data
8425 * @data_len: length of @data
8426 *
8427 * This function parses the incoming NL vendor command data attributes and
8428 * invokes the SME Api and blocks on a completion variable.
8429 * WMA copies required data and invokes callback
8430 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8431 *
8432 * Return: 0 on success; error number otherwise.
8433 */
8434static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8435 struct wireless_dev *wdev,
8436 const void *data, int data_len)
8437{
8438 int ret;
8439
8440 cds_ssr_protect(__func__);
8441 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8442 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008443 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308444
8445 return ret;
8446}
8447
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308448/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308449 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8450 * @wiphy: wiphy structure pointer
8451 * @wdev: Wireless device structure pointer
8452 * @data: Pointer to the data received
8453 * @data_len: Length of @data
8454 *
8455 * This function reads wmi max bus size and fill in the skb with
8456 * NL attributes and send up the NL event.
8457 * Return: 0 on success; errno on failure
8458 */
8459static int
8460__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8461 struct wireless_dev *wdev,
8462 const void *data, int data_len)
8463{
8464 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8465 int ret_val;
8466 struct sk_buff *skb;
8467 uint32_t nl_buf_len;
8468
8469 ENTER();
8470
8471 ret_val = wlan_hdd_validate_context(hdd_ctx);
8472 if (ret_val)
8473 return ret_val;
8474
8475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8476 hdd_err("Command not allowed in FTM mode");
8477 return -EINVAL;
8478 }
8479
8480 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8481
8482 nl_buf_len = NLMSG_HDRLEN;
8483 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8484
8485 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8486 if (!skb) {
8487 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8488 return -ENOMEM;
8489 }
8490
8491 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8492 hdd_ctx->wmi_max_len)) {
8493 hdd_err("nla put failure");
8494 goto nla_put_failure;
8495 }
8496
8497 cfg80211_vendor_cmd_reply(skb);
8498
8499 EXIT();
8500
8501 return 0;
8502
8503nla_put_failure:
8504 kfree_skb(skb);
8505 return -EINVAL;
8506}
8507
8508/**
8509 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8510 * @wiphy: wiphy structure pointer
8511 * @wdev: Wireless device structure pointer
8512 * @data: Pointer to the data received
8513 * @data_len: Length of @data
8514 *
8515 * Return: 0 on success; errno on failure
8516 */
8517static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8518 struct wireless_dev *wdev,
8519 const void *data, int data_len)
8520{
8521 int ret;
8522
8523 cds_ssr_protect(__func__);
8524 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8525 cds_ssr_unprotect(__func__);
8526
8527 return ret;
8528}
8529
8530/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308531 *__wlan_hdd_cfg80211_setband() - set band
8532 * @wiphy: Pointer to wireless phy
8533 * @wdev: Pointer to wireless device
8534 * @data: Pointer to data
8535 * @data_len: Length of @data
8536 *
8537 * Return: 0 on success, negative errno on failure
8538 */
8539static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8540 struct wireless_dev *wdev,
8541 const void *data, int data_len)
8542{
8543 struct net_device *dev = wdev->netdev;
8544 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8545 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8546 int ret;
8547 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8548 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8549
8550 ENTER();
8551
8552 ret = wlan_hdd_validate_context(hdd_ctx);
8553 if (ret)
8554 return ret;
8555
8556 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8557 hdd_err(FL("Invalid ATTR"));
8558 return -EINVAL;
8559 }
8560
8561 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8562 hdd_err(FL("attr SETBAND_VALUE failed"));
8563 return -EINVAL;
8564 }
8565
8566 ret = hdd_set_band(dev,
8567 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8568
8569 EXIT();
8570 return ret;
8571}
8572
8573/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308574 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8575 * @adapter: hdd adapter
8576 * @channel: channel number
8577 *
8578 * return: QDF status based on success or failure
8579 */
8580static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8581 int channel, int chan_bw)
8582{
8583 if (QDF_STATUS_SUCCESS !=
8584 wlan_hdd_validate_operation_channel(adapter, channel))
8585 return QDF_STATUS_E_FAILURE;
8586 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8587 channel,
8588 PHY_SINGLE_CHANNEL_CENTERED))) {
8589 hdd_notice("channel %d is in nol", channel);
8590 return -EINVAL;
8591 }
8592
8593 if ((wlansap_is_channel_leaking_in_nol(
8594 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8595 channel, chan_bw))) {
8596 hdd_notice("channel %d is leaking in nol", channel);
8597 return -EINVAL;
8598 }
8599
8600 return 0;
8601
8602}
8603
Kapil Gupta8878ad92017-02-13 11:56:04 +05308604static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8605 tsap_Config_t *sap_config,
8606 struct hdd_vendor_chan_info *channel_list)
8607{
8608 sap_config->channel = channel_list->pri_ch;
8609
8610 sap_config->ch_params.center_freq_seg0 =
8611 channel_list->vht_seg0_center_ch;
8612 sap_config->ch_params.center_freq_seg1 =
8613 channel_list->vht_seg1_center_ch;
8614
8615 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8616 sap_config->ch_params.ch_width = channel_list->chan_width;
8617 if (sap_config->channel >= 36)
8618 sap_config->ch_width_orig =
8619 hdd_ctx->config->vhtChannelWidth;
8620 else
8621 sap_config->ch_width_orig =
8622 hdd_ctx->config->nChannelBondingMode24GHz ?
8623 eHT_CHANNEL_WIDTH_40MHZ :
8624 eHT_CHANNEL_WIDTH_20MHZ;
8625
8626 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8627 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8628 sap_config->acs_cfg.vht_seg0_center_ch =
8629 channel_list->vht_seg0_center_ch;
8630 sap_config->acs_cfg.vht_seg1_center_ch =
8631 channel_list->vht_seg1_center_ch;
8632 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8633}
8634
8635static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8636 uint8_t channel_cnt,
8637 struct hdd_vendor_chan_info *channel_list)
8638{
8639 tsap_Config_t *sap_config;
8640 hdd_ap_ctx_t *hdd_ap_ctx;
8641 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8642 QDF_STATUS status = QDF_STATUS_SUCCESS;
8643
8644 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8645 sap_config = &adapter->sessionCtx.ap.sapConfig;
8646
8647 if (QDF_TIMER_STATE_RUNNING ==
8648 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8649 ap.vendor_acs_timer)) {
8650 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8651 }
8652
8653 if (channel_list && channel_list->pri_ch == 0) {
8654 /* Check mode, set default channel */
8655 channel_list->pri_ch = 6;
8656 /*
8657 * sap_select_default_oper_chan(hdd_ctx->hHal,
8658 * sap_config->acs_cfg.hw_mode);
8659 */
8660 }
8661
8662 switch (reason) {
8663 /* SAP init case */
8664 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8665 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8666 /* Update Hostapd */
8667 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8668 break;
8669
8670 /* DFS detected on current channel */
8671 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8672 wlan_sap_update_next_channel(
8673 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8674 channel_list->pri_ch,
8675 channel_list->chan_width);
8676 status = sme_update_new_channel_event(
8677 WLAN_HDD_GET_HAL_CTX(adapter),
8678 adapter->sessionId);
8679 break;
8680
8681 /* LTE coex event on current channel */
8682 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8683 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8684 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8685 hdd_ap_ctx->sapConfig.ch_width_orig =
8686 channel_list->chan_width;
8687 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8688 break;
8689
8690 default:
8691 hdd_info("invalid reason for timer invoke");
8692 }
8693 qdf_mem_free(channel_list);
8694 EXIT();
8695 return status;
8696}
8697
8698/**
8699 * Define short name for vendor channel set config
8700 */
8701#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8702#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8703#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8704#define SET_CHAN_PRIMARY_CHANNEL \
8705 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8706#define SET_CHAN_SECONDARY_CHANNEL \
8707 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8708#define SET_CHAN_SEG0_CENTER_CHANNEL \
8709 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8710#define SET_CHAN_SEG1_CENTER_CHANNEL \
8711 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8712#define SET_CHAN_CHANNEL_WIDTH \
8713 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8714#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8715
8716/**
8717 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8718 * @channel_list: pointer to hdd_vendor_chan_info
8719 * @reason: channel change reason
8720 * @channel_cnt: channel count
8721 * @data: data
8722 * @data_len: data len
8723 *
8724 * Return: 0 on success, negative errno on failure
8725 */
8726static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8727 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8728 const void *data, int data_len)
8729{
8730 int rem, i = 0;
8731 struct nlattr *tb[SET_CHAN_MAX + 1];
8732 struct nlattr *tb2[SET_CHAN_MAX + 1];
8733 struct nlattr *curr_attr;
8734 struct hdd_vendor_chan_info *channel_list;
8735
8736 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8737 hdd_err("Invalid ATTR");
8738 return -EINVAL;
8739 }
8740
8741 if (tb[SET_CHAN_REASON])
8742 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8743
8744 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8745 *channel_cnt = nla_get_u8(tb[
8746 SET_CHAN_CHANNEL_COUNT]);
8747 hdd_info("channel count %d", *channel_cnt);
8748 }
8749
8750 if (!(*channel_cnt)) {
8751 hdd_err("channel count is %d", *channel_cnt);
8752 return -EINVAL;
8753 }
8754
8755 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8756 (*channel_cnt));
8757
8758 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8759 if (nla_parse(tb2,
8760 SET_CHAN_MAX,
8761 nla_data(curr_attr), nla_len(curr_attr),
8762 NULL)) {
8763 hdd_err("nla_parse failed");
8764 return -EINVAL;
8765 }
8766 /* Parse and Fetch allowed SSID list*/
8767 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8768 channel_list[i].pri_ch =
8769 nla_get_u8(
8770 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8771 }
8772 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8773 channel_list[i].ht_sec_ch =
8774 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8775 }
8776 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8777 channel_list[i].vht_seg0_center_ch =
8778 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8779 }
8780 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8781 channel_list[i].vht_seg1_center_ch =
8782 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8783 }
8784 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8785 channel_list[i].chan_width =
8786 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8787 }
8788 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8789 i, channel_list[i].pri_ch,
8790 channel_list[i].ht_sec_ch,
8791 channel_list[i].vht_seg0_center_ch,
8792 channel_list[i].vht_seg1_center_ch,
8793 channel_list[i].chan_width);
8794 i++;
8795 if (i > *channel_cnt)
8796 break;
8797 }
8798 *chan_list_ptr = channel_list;
8799
8800 return 0;
8801}
8802
8803/**
8804 * Undef short names for vendor set channel configuration
8805 */
8806#undef SET_CHAN_REASON
8807#undef SET_CHAN_CHANNEL_COUNT
8808#undef SET_CHAN_CHAN_LIST
8809#undef SET_CHAN_PRIMARY_CHANNEL
8810#undef SET_CHAN_SECONDARY_CHANNEL
8811#undef SET_CHAN_SEG0_CENTER_CHANNEL
8812#undef SET_CHAN_SEG1_CENTER_CHANNEL
8813#undef SET_CHAN_CHANNEL_WIDTH
8814#undef SET_CHAN_MAX
8815
8816/**
8817 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8818 * @wiphy: Pointer to wireless phy
8819 * @wdev: Pointer to wireless device
8820 * @data: Pointer to data
8821 * @data_len: Length of @data
8822 *
8823 * Return: 0 on success, negative errno on failure
8824 */
8825static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8826 struct wireless_dev *wdev,
8827 const void *data, int data_len)
8828{
8829 int ret_val;
8830 QDF_STATUS qdf_status;
8831 uint8_t channel_cnt = 0, reason = -1;
8832 struct hdd_vendor_chan_info *channel_list = NULL;
8833 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8834 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8835
8836 ENTER();
8837
8838 ret_val = wlan_hdd_validate_context(hdd_ctx);
8839 if (ret_val)
8840 return ret_val;
8841
8842 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8843 hdd_err("Command not allowed in FTM mode");
8844 return -EINVAL;
8845 }
8846
8847 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8848 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8849 else {
8850 hdd_err("already timeout happened for acs");
8851 return -EINVAL;
8852 }
8853
8854 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8855 &channel_cnt, data, data_len);
8856 if (ret_val)
8857 return ret_val;
8858
8859 /* Validate channel to be set */
8860 while (channel_cnt && channel_list) {
8861 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8862 channel_list->pri_ch,
8863 channel_list->chan_width);
8864 if (qdf_status == QDF_STATUS_SUCCESS)
8865 break;
8866 channel_cnt--;
8867 channel_list++;
8868 }
8869 if ((channel_cnt <= 0) || !channel_list) {
8870 hdd_err("no available channel/chanlist %p", channel_list);
8871 return -EINVAL;
8872 }
8873
8874 qdf_status = hdd_update_acs_channel(adapter, reason,
8875 channel_cnt, channel_list);
8876 return qdf_status_to_os_return(qdf_status);
8877}
8878
8879/**
8880 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8881 * @wiphy: Pointer to wireless phy
8882 * @wdev: Pointer to wireless device
8883 * @data: Pointer to data
8884 * @data_len: Length of @data
8885 *
8886 * Return: 0 on success, negative errno on failure
8887 */
8888static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8889 struct wireless_dev *wdev,
8890 const void *data, int data_len)
8891{
8892 int ret;
8893
8894 cds_ssr_protect(__func__);
8895 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8896 data_len);
8897 cds_ssr_protect(__func__);
8898
8899 return ret;
8900}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308901
8902/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308903 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8904 * @wiphy: wiphy structure pointer
8905 * @wdev: Wireless device structure pointer
8906 * @data: Pointer to the data received
8907 * @data_len: Length of @data
8908 *
8909 * Return: 0 on success; errno on failure
8910 */
8911static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8912 struct wireless_dev *wdev,
8913 const void *data, int data_len)
8914{
8915 int ret;
8916
8917 cds_ssr_protect(__func__);
8918 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8919 cds_ssr_unprotect(__func__);
8920
8921 return ret;
8922}
8923
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008924/**
8925 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8926 * @nl80211_value: Vendor command attribute value
8927 * @wmi_value: Pointer to return converted WMI return value
8928 *
8929 * Convert NL80211 vendor command value for SAR limit set to WMI value
8930 * Return: 0 on success, -1 on invalid value
8931 */
8932static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8933 u32 *wmi_value)
8934{
8935 int ret = 0;
8936
8937 switch (nl80211_value) {
8938 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8939 *wmi_value = WMI_SAR_FEATURE_OFF;
8940 break;
8941 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8942 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8943 break;
8944 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8945 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8946 break;
8947 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8948 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8949 break;
8950 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8951 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8952 break;
8953 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8954 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8955 break;
8956 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8957 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8958 break;
8959 default:
8960 ret = -1;
8961 }
8962 return ret;
8963}
8964
8965/**
8966 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8967 * @nl80211_value: Vendor command attribute value
8968 * @wmi_value: Pointer to return converted WMI return value
8969 *
8970 * Convert NL80211 vendor command value for SAR BAND to WMI value
8971 * Return: 0 on success, -1 on invalid value
8972 */
8973static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8974{
8975 int ret = 0;
8976
8977 switch (nl80211_value) {
8978 case NL80211_BAND_2GHZ:
8979 *wmi_value = WMI_SAR_2G_ID;
8980 break;
8981 case NL80211_BAND_5GHZ:
8982 *wmi_value = WMI_SAR_5G_ID;
8983 break;
8984 default:
8985 ret = -1;
8986 }
8987 return ret;
8988}
8989
8990/**
8991 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8992 * @nl80211_value: Vendor command attribute value
8993 * @wmi_value: Pointer to return converted WMI return value
8994 *
8995 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8996 * Return: 0 on success, -1 on invalid value
8997 */
8998static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8999 u32 *wmi_value)
9000{
9001 int ret = 0;
9002
9003 switch (nl80211_value) {
9004 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9005 *wmi_value = WMI_SAR_MOD_CCK;
9006 break;
9007 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9008 *wmi_value = WMI_SAR_MOD_OFDM;
9009 break;
9010 default:
9011 ret = -1;
9012 }
9013 return ret;
9014}
9015
9016
9017/**
9018 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9019 * @wiphy: Pointer to wireless phy
9020 * @wdev: Pointer to wireless device
9021 * @data: Pointer to data
9022 * @data_len: Length of @data
9023 *
9024 * This function is used to setup Specific Absorption Rate limit specs.
9025 *
9026 * Return: 0 on success, negative errno on failure
9027 */
9028static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9029 struct wireless_dev *wdev,
9030 const void *data, int data_len)
9031{
9032 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9033 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9034 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9035 *sar_spec_list;
9036 struct sar_limit_cmd_params sar_limit_cmd = {0};
9037 int ret = -EINVAL, i = 0, rem = 0;
9038
9039 ENTER();
9040
9041 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9042 hdd_err("Command not allowed in FTM mode");
9043 return -EPERM;
9044 }
9045
9046 if (wlan_hdd_validate_context(hdd_ctx))
9047 return -EINVAL;
9048
9049 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9050 data, data_len, NULL)) {
9051 hdd_err("Invalid SAR attributes");
9052 return -EINVAL;
9053 }
9054
9055 /* Vendor command manadates all SAR Specs in single call */
9056 sar_limit_cmd.commit_limits = 1;
9057 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9058 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9059 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9060 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9061 &sar_limit_cmd.sar_enable) < 0) {
9062 hdd_err("Invalid SAR Enable attr");
9063 goto fail;
9064 }
9065 }
9066 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9067
9068 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9069 sar_limit_cmd.num_limit_rows = nla_get_u32(
9070 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9071 hdd_info("attr sar num_limit_rows %d",
9072 sar_limit_cmd.num_limit_rows);
9073 }
9074 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9075 hdd_err("SAR Spec list exceed supported size");
9076 goto fail;
9077 }
9078 if (sar_limit_cmd.num_limit_rows == 0)
9079 goto send_sar_limits;
9080 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9081 struct sar_limit_cmd_row) *
9082 sar_limit_cmd.num_limit_rows);
9083 if (!sar_limit_cmd.sar_limit_row_list) {
9084 ret = -ENOMEM;
9085 goto fail;
9086 }
9087 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9088 hdd_err("Invalid SAR SPECs list");
9089 goto fail;
9090 }
9091
9092 nla_for_each_nested(sar_spec_list,
9093 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9094 if (i == sar_limit_cmd.num_limit_rows) {
9095 hdd_warn("SAR Cmd has excess SPECs in list");
9096 break;
9097 }
9098
9099 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9100 nla_data(sar_spec_list), nla_len(sar_spec_list),
9101 NULL)) {
9102 hdd_err("nla_parse failed for SAR Spec list");
9103 goto fail;
9104 }
9105 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9106 if (sar_spec[
9107 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9108 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9109 nla_get_u32(sar_spec[
9110 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9111 } else {
9112 hdd_err("SAR Spec does not have power limit value");
9113 goto fail;
9114 }
9115
9116 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9117 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9118 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9119 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9120 < 0) {
9121 hdd_err("Invalid SAR Band attr");
9122 goto fail;
9123 }
9124 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9125 WMI_SAR_BAND_ID_VALID_MASK;
9126 }
9127 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9128 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9129 nla_get_u32(sar_spec[
9130 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9131 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9132 WMI_SAR_CHAIN_ID_VALID_MASK;
9133 }
9134 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9135 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9136 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9137 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9138 < 0) {
9139 hdd_err("Invalid SAR Modulation attr");
9140 goto fail;
9141 }
9142 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9143 WMI_SAR_MOD_ID_VALID_MASK;
9144 }
9145 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9146 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9147 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9148 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9149 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9150 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9151 i++;
9152 }
9153
9154 if (i < sar_limit_cmd.num_limit_rows) {
9155 hdd_warn("SAR Cmd has less SPECs in list");
9156 sar_limit_cmd.num_limit_rows = i;
9157 }
9158
9159send_sar_limits:
9160 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9161 QDF_STATUS_SUCCESS)
9162 ret = 0;
9163fail:
9164 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9165 return ret;
9166}
9167
9168/**
9169 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9170 * @wiphy: Pointer to wireless phy
9171 * @wdev: Pointer to wireless device
9172 * @data: Pointer to data
9173 * @data_len: Length of @data
9174 *
9175 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9176 *
9177 * Return: 0 on success, negative errno on failure
9178 */
9179static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9180 struct wireless_dev *wdev,
9181 const void *data,
9182 int data_len)
9183{
9184 int ret;
9185
9186 cds_ssr_protect(__func__);
9187 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9188 data_len);
9189 cds_ssr_unprotect(__func__);
9190
9191 return ret;
9192}
9193
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309194static const struct
9195nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9196 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9197 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9198 .len = QDF_MAC_ADDR_SIZE},
9199};
9200
9201/**
9202 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9203 * @wiphy: Pointer to wireless phy
9204 * @wdev: Pointer to wireless device
9205 * @data: Pointer to data
9206 * @data_len: Length of @data
9207 *
9208 * This function is used to enable/disable roaming using vendor commands
9209 *
9210 * Return: 0 on success, negative errno on failure
9211 */
9212static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9213 struct wireless_dev *wdev,
9214 const void *data, int data_len)
9215{
9216 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9217 struct net_device *dev = wdev->netdev;
9218 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9219 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9220 uint32_t is_fast_roam_enabled;
9221 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309222 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309223
9224 ENTER_DEV(dev);
9225
9226 ret = wlan_hdd_validate_context(hdd_ctx);
9227 if (0 != ret)
9228 return ret;
9229
9230 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9231 hdd_err("Command not allowed in FTM mode");
9232 return -EINVAL;
9233 }
9234
9235 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9236 qca_wlan_vendor_attr);
9237 if (ret) {
9238 hdd_err("Invalid ATTR");
9239 return -EINVAL;
9240 }
9241
9242 /* Parse and fetch Enable flag */
9243 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9244 hdd_err("attr enable failed");
9245 return -EINVAL;
9246 }
9247
9248 is_fast_roam_enabled = nla_get_u32(
9249 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009250 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9251 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309252
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009253 if (!adapter->fast_roaming_allowed) {
9254 hdd_err("fast roaming not allowed on %s interface",
9255 adapter->dev->name);
9256 return -EINVAL;
9257 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309258 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309259 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009260 (is_fast_roam_enabled &&
9261 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309262 if (qdf_status != QDF_STATUS_SUCCESS)
9263 hdd_err("sme_config_fast_roaming failed with status=%d",
9264 qdf_status);
9265 ret = qdf_status_to_os_return(qdf_status);
9266
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309267 EXIT();
9268 return ret;
9269}
9270
9271/**
9272 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9273 * @wiphy: Pointer to wireless phy
9274 * @wdev: Pointer to wireless device
9275 * @data: Pointer to data
9276 * @data_len: Length of @data
9277 *
9278 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9279 *
9280 * Return: 0 on success, negative errno on failure
9281 */
9282static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9283 struct wireless_dev *wdev,
9284 const void *data, int data_len)
9285{
9286 int ret;
9287
9288 cds_ssr_protect(__func__);
9289 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9290 cds_ssr_unprotect(__func__);
9291
9292 return ret;
9293}
9294
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309295static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9296 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9297 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9298 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9299 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9300};
9301
9302/**
9303 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9304 * @wiphy: Pointer to wireless phy
9305 * @wdev: Pointer to wireless device
9306 * @data: Pointer to data
9307 * @data_len: Length of @data
9308 *
9309 * Return: 0 on success, negative errno on failure
9310 */
9311static int
9312__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9313 struct wireless_dev *wdev,
9314 const void *data,
9315 int data_len)
9316{
9317 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9318 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9319 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9320 struct nlattr *apth;
9321 int rem;
9322 int ret = 1;
9323 int print_idx = -1;
9324 int module_id = -1;
9325 int bit_mask = -1;
9326 int status;
9327
9328 ENTER();
9329
9330 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9331 hdd_err("Command not allowed in FTM mode");
9332 return -EINVAL;
9333 }
9334
9335 ret = wlan_hdd_validate_context(hdd_ctx);
9336 if (ret != 0)
9337 return -EINVAL;
9338
9339 print_idx = qdf_get_pidx();
9340 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9341 hdd_err("Invalid print controle object index");
9342 return -EINVAL;
9343 }
9344
9345 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9346 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9347 hdd_err("Invalid attr");
9348 return -EINVAL;
9349 }
9350
9351 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9352 hdd_err("attr trace level param failed");
9353 return -EINVAL;
9354 }
9355
9356 nla_for_each_nested(apth,
9357 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9358 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9359 nla_data(apth), nla_len(apth), NULL)) {
9360 hdd_err("Invalid attr");
9361 return -EINVAL;
9362 }
9363
9364 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9365 hdd_err("attr Module ID failed");
9366 return -EINVAL;
9367 }
9368 module_id = nla_get_u32
9369 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9370
9371 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9372 hdd_err("attr Verbose mask failed");
9373 return -EINVAL;
9374 }
9375 bit_mask = nla_get_u32
9376 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9377
9378 status = hdd_qdf_trace_enable(module_id, bit_mask);
9379
9380 if (status != 0)
9381 hdd_err("can not set verbose mask %d for the category %d",
9382 bit_mask, module_id);
9383 }
9384
9385 EXIT();
9386 return ret;
9387}
9388
9389/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309390 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9391 * @wiphy: Pointer to wireless phy
9392 * @wdev: Pointer to wireless device
9393 * @data: Pointer to data
9394 * @data_len: Length of @data
9395 *
9396 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9397 *
9398 * Return: 0 on success, negative errno on failure
9399 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309400
9401static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9402 struct wireless_dev *wdev,
9403 const void *data,
9404 int data_len)
9405{
9406 int ret;
9407
9408 cds_ssr_protect(__func__);
9409 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9410 cds_ssr_unprotect(__func__);
9411
9412 return ret;
9413}
9414
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009415const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9416 {
9417 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9418 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9419 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309420 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009421 .doit = is_driver_dfs_capable
9422 },
9423
9424#ifdef WLAN_FEATURE_NAN
9425 {
9426 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9427 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9428 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9429 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9430 .doit = wlan_hdd_cfg80211_nan_request
9431 },
9432#endif
9433
9434#ifdef WLAN_FEATURE_STATS_EXT
9435 {
9436 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9437 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9438 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9439 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9440 .doit = wlan_hdd_cfg80211_stats_ext_request
9441 },
9442#endif
9443#ifdef FEATURE_WLAN_EXTSCAN
9444 {
9445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9448 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9449 .doit = wlan_hdd_cfg80211_extscan_start
9450 },
9451 {
9452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9455 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9456 .doit = wlan_hdd_cfg80211_extscan_stop
9457 },
9458 {
9459 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9460 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9461 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9462 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9463 },
9464 {
9465 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9466 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9467 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9468 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9469 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9470 },
9471 {
9472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9473 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9474 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9475 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9476 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9477 },
9478 {
9479 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9480 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9481 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9482 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9483 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9484 },
9485 {
9486 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9487 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9488 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9489 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9490 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9491 },
9492 {
9493 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9494 .info.subcmd =
9495 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9496 .flags =
9497 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9498 WIPHY_VENDOR_CMD_NEED_RUNNING,
9499 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9500 },
9501 {
9502 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9503 .info.subcmd =
9504 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9505 .flags =
9506 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9507 WIPHY_VENDOR_CMD_NEED_RUNNING,
9508 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9509 },
9510 {
9511 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9512 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9513 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9514 WIPHY_VENDOR_CMD_NEED_NETDEV |
9515 WIPHY_VENDOR_CMD_NEED_RUNNING,
9516 .doit = wlan_hdd_cfg80211_set_epno_list
9517 },
9518#endif /* FEATURE_WLAN_EXTSCAN */
9519
9520#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9521 {
9522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9525 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9526 .doit = wlan_hdd_cfg80211_ll_stats_clear
9527 },
9528
9529 {
9530 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9531 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9532 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9533 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9534 .doit = wlan_hdd_cfg80211_ll_stats_set
9535 },
9536
9537 {
9538 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9539 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9540 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9541 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9542 .doit = wlan_hdd_cfg80211_ll_stats_get
9543 },
9544#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9545#ifdef FEATURE_WLAN_TDLS
9546 {
9547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9550 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9551 .doit = wlan_hdd_cfg80211_exttdls_enable
9552 },
9553 {
9554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9555 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9556 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9557 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9558 .doit = wlan_hdd_cfg80211_exttdls_disable
9559 },
9560 {
9561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9564 .doit = wlan_hdd_cfg80211_exttdls_get_status
9565 },
9566#endif
9567 {
9568 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9569 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9570 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9571 .doit = wlan_hdd_cfg80211_get_supported_features
9572 },
9573 {
9574 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9575 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9576 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9577 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9578 },
9579 {
9580 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9581 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9582 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309583 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009584 },
9585 {
9586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9589 WIPHY_VENDOR_CMD_NEED_NETDEV,
9590 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9591 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009592 {
9593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9594 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9595 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9596 WIPHY_VENDOR_CMD_NEED_NETDEV,
9597 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9598 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009599 {
9600 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309601 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9602 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9603 WIPHY_VENDOR_CMD_NEED_NETDEV |
9604 WIPHY_VENDOR_CMD_NEED_RUNNING,
9605 .doit = hdd_cfg80211_get_station_cmd
9606 },
9607 {
9608 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009609 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9610 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9611 WIPHY_VENDOR_CMD_NEED_NETDEV |
9612 WIPHY_VENDOR_CMD_NEED_RUNNING,
9613 .doit = wlan_hdd_cfg80211_do_acs
9614 },
9615
9616 {
9617 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9618 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9619 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9620 WIPHY_VENDOR_CMD_NEED_NETDEV,
9621 .doit = wlan_hdd_cfg80211_get_features
9622 },
9623#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9624 {
9625 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9626 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9627 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9628 WIPHY_VENDOR_CMD_NEED_NETDEV |
9629 WIPHY_VENDOR_CMD_NEED_RUNNING,
9630 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9631 },
9632#endif
9633#ifdef FEATURE_WLAN_EXTSCAN
9634 {
9635 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9636 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9637 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9638 WIPHY_VENDOR_CMD_NEED_NETDEV |
9639 WIPHY_VENDOR_CMD_NEED_RUNNING,
9640 .doit = wlan_hdd_cfg80211_set_passpoint_list
9641 },
9642 {
9643 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9644 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9645 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9646 WIPHY_VENDOR_CMD_NEED_NETDEV |
9647 WIPHY_VENDOR_CMD_NEED_RUNNING,
9648 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9649 },
9650 {
9651 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9652 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9653 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9654 WIPHY_VENDOR_CMD_NEED_NETDEV |
9655 WIPHY_VENDOR_CMD_NEED_RUNNING,
9656 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9657 },
9658 {
9659 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9660 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9661 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9662 WIPHY_VENDOR_CMD_NEED_NETDEV |
9663 WIPHY_VENDOR_CMD_NEED_RUNNING,
9664 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9665 },
9666#endif /* FEATURE_WLAN_EXTSCAN */
9667 {
9668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9671 WIPHY_VENDOR_CMD_NEED_NETDEV,
9672 .doit = wlan_hdd_cfg80211_get_wifi_info
9673 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009674#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009675 {
9676 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9677 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9678 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9679 WIPHY_VENDOR_CMD_NEED_NETDEV |
9680 WIPHY_VENDOR_CMD_NEED_RUNNING,
9681 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9682 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009683#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 {
9685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9688 WIPHY_VENDOR_CMD_NEED_NETDEV,
9689 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9690 },
9691 {
9692 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9693 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9694 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9695 WIPHY_VENDOR_CMD_NEED_NETDEV,
9696 .doit = wlan_hdd_cfg80211_wifi_logger_start
9697 },
9698 {
9699 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9700 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9701 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9702 WIPHY_VENDOR_CMD_NEED_NETDEV,
9703 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9704 },
9705 {
9706 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9707 .info.subcmd =
9708 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9709 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9710 WIPHY_VENDOR_CMD_NEED_NETDEV |
9711 WIPHY_VENDOR_CMD_NEED_RUNNING,
9712 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9713 },
9714 {
9715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9716 .info.subcmd =
9717 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9718 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9719 WIPHY_VENDOR_CMD_NEED_NETDEV |
9720 WIPHY_VENDOR_CMD_NEED_RUNNING,
9721 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9722 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009723#ifdef WLAN_FEATURE_TSF
9724 {
9725 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9726 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9727 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9728 WIPHY_VENDOR_CMD_NEED_NETDEV |
9729 WIPHY_VENDOR_CMD_NEED_RUNNING,
9730 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9731 },
9732#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009733#ifdef FEATURE_WLAN_TDLS
9734 {
9735 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9736 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9737 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9738 WIPHY_VENDOR_CMD_NEED_NETDEV |
9739 WIPHY_VENDOR_CMD_NEED_RUNNING,
9740 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9741 },
9742#endif
9743#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9744 {
9745 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9746 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9747 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9748 WIPHY_VENDOR_CMD_NEED_NETDEV |
9749 WIPHY_VENDOR_CMD_NEED_RUNNING,
9750 .doit = wlan_hdd_cfg80211_offloaded_packets
9751 },
9752#endif
9753 {
9754 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9755 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9756 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9757 WIPHY_VENDOR_CMD_NEED_NETDEV |
9758 WIPHY_VENDOR_CMD_NEED_RUNNING,
9759 .doit = wlan_hdd_cfg80211_monitor_rssi
9760 },
9761 {
9762 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309763 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9764 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9765 WIPHY_VENDOR_CMD_NEED_NETDEV |
9766 WIPHY_VENDOR_CMD_NEED_RUNNING,
9767 .doit = wlan_hdd_cfg80211_set_ns_offload
9768 },
9769 {
9770 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009771 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9772 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9773 WIPHY_VENDOR_CMD_NEED_NETDEV |
9774 WIPHY_VENDOR_CMD_NEED_RUNNING,
9775 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9776 },
9777#ifdef WLAN_FEATURE_MEMDUMP
9778 {
9779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9782 WIPHY_VENDOR_CMD_NEED_NETDEV |
9783 WIPHY_VENDOR_CMD_NEED_RUNNING,
9784 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9785 },
9786#endif /* WLAN_FEATURE_MEMDUMP */
9787 {
9788 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9789 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9791 WIPHY_VENDOR_CMD_NEED_NETDEV |
9792 WIPHY_VENDOR_CMD_NEED_RUNNING,
9793 .doit = wlan_hdd_cfg80211_vendor_scan
9794 },
9795
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309796 /* Vendor abort scan */
9797 {
9798 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9799 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9800 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9801 WIPHY_VENDOR_CMD_NEED_NETDEV |
9802 WIPHY_VENDOR_CMD_NEED_RUNNING,
9803 .doit = wlan_hdd_vendor_abort_scan
9804 },
9805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009806 /* OCB commands */
9807 {
9808 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9809 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9810 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9811 WIPHY_VENDOR_CMD_NEED_NETDEV |
9812 WIPHY_VENDOR_CMD_NEED_RUNNING,
9813 .doit = wlan_hdd_cfg80211_ocb_set_config
9814 },
9815 {
9816 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9817 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9818 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9819 WIPHY_VENDOR_CMD_NEED_NETDEV |
9820 WIPHY_VENDOR_CMD_NEED_RUNNING,
9821 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9822 },
9823 {
9824 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9825 .info.subcmd =
9826 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9827 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9828 WIPHY_VENDOR_CMD_NEED_NETDEV |
9829 WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9831 },
9832 {
9833 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9834 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9835 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9836 WIPHY_VENDOR_CMD_NEED_NETDEV |
9837 WIPHY_VENDOR_CMD_NEED_RUNNING,
9838 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9839 },
9840 {
9841 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9842 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9843 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9844 WIPHY_VENDOR_CMD_NEED_NETDEV |
9845 WIPHY_VENDOR_CMD_NEED_RUNNING,
9846 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9847 },
9848 {
9849 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9850 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9851 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9852 WIPHY_VENDOR_CMD_NEED_NETDEV |
9853 WIPHY_VENDOR_CMD_NEED_RUNNING,
9854 .doit = wlan_hdd_cfg80211_dcc_get_stats
9855 },
9856 {
9857 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9858 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9859 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9860 WIPHY_VENDOR_CMD_NEED_NETDEV |
9861 WIPHY_VENDOR_CMD_NEED_RUNNING,
9862 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9863 },
9864 {
9865 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9866 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9867 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9868 WIPHY_VENDOR_CMD_NEED_NETDEV |
9869 WIPHY_VENDOR_CMD_NEED_RUNNING,
9870 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9871 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309872 {
9873 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9874 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9875 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9876 WIPHY_VENDOR_CMD_NEED_NETDEV |
9877 WIPHY_VENDOR_CMD_NEED_RUNNING,
9878 .doit = wlan_hdd_cfg80211_get_link_properties
9879 },
Peng Xu278d0122015-09-24 16:34:17 -07009880 {
Peng Xud2220962016-07-11 17:59:17 -07009881 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009882 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9883 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9884 WIPHY_VENDOR_CMD_NEED_NETDEV |
9885 WIPHY_VENDOR_CMD_NEED_RUNNING,
9886 .doit = wlan_hdd_cfg80211_set_ota_test
9887 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009888#ifdef FEATURE_LFR_SUBNET_DETECTION
9889 {
9890 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9891 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9892 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9893 WIPHY_VENDOR_CMD_NEED_NETDEV |
9894 WIPHY_VENDOR_CMD_NEED_RUNNING,
9895 .doit = wlan_hdd_cfg80211_set_gateway_params
9896 },
9897#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009898 {
Peng Xud2220962016-07-11 17:59:17 -07009899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9902 WIPHY_VENDOR_CMD_NEED_NETDEV |
9903 WIPHY_VENDOR_CMD_NEED_RUNNING,
9904 .doit = wlan_hdd_cfg80211_txpower_scale
9905 },
9906 {
9907 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9908 .info.subcmd =
9909 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9910 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9911 WIPHY_VENDOR_CMD_NEED_NETDEV |
9912 WIPHY_VENDOR_CMD_NEED_RUNNING,
9913 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9914 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309915 {
9916 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9917 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9918 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9919 WIPHY_VENDOR_CMD_NEED_NETDEV |
9920 WIPHY_VENDOR_CMD_NEED_RUNNING,
9921 .doit = wlan_hdd_cfg80211_bpf_offload
9922 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309923 {
9924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9927 WIPHY_VENDOR_CMD_NEED_NETDEV |
9928 WIPHY_VENDOR_CMD_NEED_RUNNING,
9929 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9930 },
9931 {
9932 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309933 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9934 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9935 WIPHY_VENDOR_CMD_NEED_NETDEV |
9936 WIPHY_VENDOR_CMD_NEED_RUNNING,
9937 .doit = wlan_hdd_cfg80211_sta_roam_policy
9938 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309939#ifdef FEATURE_WLAN_CH_AVOID
9940 {
9941 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9942 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9943 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9944 WIPHY_VENDOR_CMD_NEED_NETDEV |
9945 WIPHY_VENDOR_CMD_NEED_RUNNING,
9946 .doit = wlan_hdd_cfg80211_avoid_freq
9947 },
9948#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309949 {
9950 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309951 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9952 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9953 WIPHY_VENDOR_CMD_NEED_NETDEV |
9954 WIPHY_VENDOR_CMD_NEED_RUNNING,
9955 .doit = wlan_hdd_cfg80211_sap_configuration_set
9956 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009957 {
Peng Xu4225c152016-07-14 21:18:14 -07009958 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009959 .info.subcmd =
9960 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9962 WIPHY_VENDOR_CMD_NEED_NETDEV |
9963 WIPHY_VENDOR_CMD_NEED_RUNNING,
9964 .doit = wlan_hdd_cfg80211_p2p_lo_start
9965 },
9966 {
9967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9968 .info.subcmd =
9969 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9970 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9971 WIPHY_VENDOR_CMD_NEED_NETDEV |
9972 WIPHY_VENDOR_CMD_NEED_RUNNING,
9973 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9974 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309975 {
9976 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9977 .info.subcmd =
9978 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9979 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9980 WIPHY_VENDOR_CMD_NEED_NETDEV |
9981 WIPHY_VENDOR_CMD_NEED_RUNNING,
9982 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9983 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009984#ifdef WLAN_FEATURE_NAN_DATAPATH
9985 {
9986 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9987 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9988 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9989 WIPHY_VENDOR_CMD_NEED_NETDEV |
9990 WIPHY_VENDOR_CMD_NEED_RUNNING,
9991 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9992 },
9993#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309994 {
9995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9998 WIPHY_VENDOR_CMD_NEED_NETDEV |
9999 WIPHY_VENDOR_CMD_NEED_RUNNING,
10000 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10001 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010002 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010003 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10004 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10006 WIPHY_VENDOR_CMD_NEED_NETDEV |
10007 WIPHY_VENDOR_CMD_NEED_RUNNING,
10008 .doit = wlan_hdd_cfg80211_get_bus_size
10009 },
10010 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010011 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10012 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10013 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10014 WIPHY_VENDOR_CMD_NEED_NETDEV |
10015 WIPHY_VENDOR_CMD_NEED_RUNNING,
10016 .doit = wlan_hdd_cfg80211_update_vendor_channel
10017 },
10018 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010019 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10020 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10021 WIPHY_VENDOR_CMD_NEED_NETDEV |
10022 WIPHY_VENDOR_CMD_NEED_RUNNING,
10023 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010024 },
10025 {
10026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10027 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10029 WIPHY_VENDOR_CMD_NEED_NETDEV |
10030 WIPHY_VENDOR_CMD_NEED_RUNNING,
10031 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010032 },
10033#ifdef WLAN_FEATURE_DISA
10034 {
10035 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10036 .info.subcmd =
10037 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10039 WIPHY_VENDOR_CMD_NEED_NETDEV |
10040 WIPHY_VENDOR_CMD_NEED_RUNNING,
10041 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10042 },
10043#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010044#ifdef FEATURE_WLAN_TDLS
10045 {
10046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10047 .info.subcmd =
10048 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10049 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10050 WIPHY_VENDOR_CMD_NEED_NETDEV |
10051 WIPHY_VENDOR_CMD_NEED_RUNNING,
10052 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010053 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010054#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010055 {
10056 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10057 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10058 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10059 WIPHY_VENDOR_CMD_NEED_RUNNING,
10060 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10061 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010062 {
10063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10064 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10066 WIPHY_VENDOR_CMD_NEED_NETDEV |
10067 WIPHY_VENDOR_CMD_NEED_RUNNING,
10068 .doit = wlan_hdd_cfg80211_set_trace_level
10069 },
10070
Paul Zhang3a210c52016-12-08 10:18:12 +080010071#ifdef WLAN_UMAC_CONVERGENCE
10072 COMMON_VENDOR_COMMANDS
10073#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010074};
10075
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010076#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10077 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10078 defined(FEATURE_WLAN_SCAN_PNO)
10079/**
10080 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10081 * @wiphy: pointer to wiphy
10082 * @config: pointer to config
10083 *
10084 * Return: None
10085 */
10086static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10087 struct hdd_config *config)
10088{
10089 if (config->configPNOScanSupport) {
10090 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10091 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10092 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10093 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10094 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10095 if (config->max_sched_scan_plan_interval)
10096 wiphy->max_sched_scan_plan_interval =
10097 config->max_sched_scan_plan_interval;
10098 if (config->max_sched_scan_plan_iterations)
10099 wiphy->max_sched_scan_plan_iterations =
10100 config->max_sched_scan_plan_iterations;
10101 }
10102}
10103#else
10104static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10105 struct hdd_config *config)
10106{
10107}
10108#endif
10109
10110
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010111/**
10112 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10113 * @priv_size: Size of the hdd context.
10114 *
10115 * Allocate wiphy context and hdd context.
10116 *
10117 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010119hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010120{
10121 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010122 hdd_context_t *hdd_ctx;
10123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 ENTER();
10125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010126 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10127
10128 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010129 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010130 return NULL;
10131 }
10132
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010133 hdd_ctx = wiphy_priv(wiphy);
10134
10135 hdd_ctx->wiphy = wiphy;
10136
10137 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010138}
10139
10140/*
10141 * FUNCTION: wlan_hdd_cfg80211_update_band
10142 * This function is called from the supplicant through a
10143 * private ioctl to change the band value
10144 */
10145int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10146{
10147 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010148 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149
10150 ENTER();
10151
Dustin Browna30892e2016-10-12 17:28:36 -070010152 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010153
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010154 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010155 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010156
10157 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10158 struct ieee80211_supported_band *band = wiphy->bands[i];
10159
10160 channelEnabledState =
10161 cds_get_channel_state(band->channels[j].
10162 hw_value);
10163
Dustin Browna30892e2016-10-12 17:28:36 -070010164 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010165 /* 5G only */
10166#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10167 /* Enable Social channels for P2P */
10168 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10169 (band->channels[j].center_freq)
10170 && CHANNEL_STATE_ENABLE ==
10171 channelEnabledState)
10172 band->channels[j].flags &=
10173 ~IEEE80211_CHAN_DISABLED;
10174 else
10175#endif
10176 band->channels[j].flags |=
10177 IEEE80211_CHAN_DISABLED;
10178 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010179 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010180 eCSR_BAND_24 == eBand) {
10181 /* 2G only */
10182 band->channels[j].flags |=
10183 IEEE80211_CHAN_DISABLED;
10184 continue;
10185 }
10186
Amar Singhal6842e8f2016-02-23 16:30:32 -080010187 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010188 band->channels[j].flags &=
10189 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010190 }
10191 }
10192 return 0;
10193}
10194
Peng Xuacfdda12017-02-06 16:15:38 -080010195#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010196/*
10197 * FUNCTION: wlan_hdd_cfg80211_init
10198 * This function is called by hdd_wlan_startup()
10199 * during initialization.
10200 * This function is used to initialize and register wiphy structure.
10201 */
10202int wlan_hdd_cfg80211_init(struct device *dev,
10203 struct wiphy *wiphy, struct hdd_config *pCfg)
10204{
10205 int i, j;
10206 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10207
10208 ENTER();
10209
10210 /* Now bind the underlying wlan device with wiphy */
10211 set_wiphy_dev(wiphy, dev);
10212
10213 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10216 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010217 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010218#else
10219 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010220 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221#endif
10222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10224 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10225 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10226#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10227 | WIPHY_FLAG_4ADDR_STATION
10228#endif
10229 | WIPHY_FLAG_OFFCHAN_TX;
10230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010231#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10232 wiphy->wowlan = &wowlan_support_cfg80211_init;
10233#else
10234 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10235 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10236 wiphy->wowlan.pattern_min_len = 1;
10237 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10238#endif
10239
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010240 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010241#ifdef FEATURE_WLAN_ESE
10242 || pCfg->isEseIniFeatureEnabled
10243#endif
10244 ) {
10245 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10246 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010247#ifdef FEATURE_WLAN_TDLS
10248 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10249 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10250#endif
10251
10252 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10253
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010254#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10255 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10256#endif
10257
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010258 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010259
10260#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010261 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262#endif
10263
10264 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010265 * driver can still register regulatory callback and
10266 * it will get regulatory settings in wiphy->band[], but
10267 * driver need to determine what to do with both
10268 * regulatory settings
10269 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010270
10271 wiphy->reg_notifier = hdd_reg_notifier;
10272
10273#if defined QCA_WIFI_FTM
10274}
10275#endif
10276
10277 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10278
10279 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10280
10281 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10282
Arun Khandavallifae92942016-08-01 13:31:08 +053010283 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10284 | BIT(NL80211_IFTYPE_ADHOC)
10285 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10286 | BIT(NL80211_IFTYPE_P2P_GO)
10287 | BIT(NL80211_IFTYPE_AP)
10288 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010289
Arun Khandavallifae92942016-08-01 13:31:08 +053010290 if (pCfg->advertiseConcurrentOperation) {
10291 if (pCfg->enableMCC) {
10292 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010293
Arun Khandavallifae92942016-08-01 13:31:08 +053010294 for (i = 0;
10295 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10296 i++) {
10297 if (!pCfg->allowMCCGODiffBI)
10298 wlan_hdd_iface_combination[i].
10299 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010300 }
10301 }
10302 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010303 ARRAY_SIZE(wlan_hdd_iface_combination);
10304 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010305 }
10306
10307 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010308 * on ini values
10309 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010310 if (!pCfg->ShortGI20MhzEnable) {
10311 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10312 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010313 }
10314
10315 if (!pCfg->ShortGI40MhzEnable) {
10316 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10317 }
10318
10319 if (!pCfg->nChannelBondingMode5GHz) {
10320 wlan_hdd_band_5_ghz.ht_cap.cap &=
10321 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10322 }
10323
Abhishek Singhf512bf32016-05-04 16:47:46 +053010324 /*
10325 * In case of static linked driver at the time of driver unload,
10326 * module exit doesn't happens. Module cleanup helps in cleaning
10327 * of static memory.
10328 * If driver load happens statically, at the time of driver unload,
10329 * wiphy flags don't get reset because of static memory.
10330 * It's better not to store channel in static memory.
10331 */
Dustin Browna30892e2016-10-12 17:28:36 -070010332 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10333 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010334 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010335 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010336 hdd_err("Not enough memory to allocate channels");
10337 return -ENOMEM;
10338 }
Dustin Browna30892e2016-10-12 17:28:36 -070010339 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010340 &hdd_channels_2_4_ghz[0],
10341 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010342 if ((hdd_is_5g_supported(pHddCtx)) &&
10343 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10344 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10345 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10346 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010347 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10348 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010349 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010350 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010351 hdd_err("Not enough memory to allocate channels");
10352 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010353 bands[NL80211_BAND_2GHZ]->channels);
10354 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010355 return -ENOMEM;
10356 }
Dustin Browna30892e2016-10-12 17:28:36 -070010357 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010358 &hdd_channels_5_ghz[0],
10359 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010360 }
10361
Dustin Browna30892e2016-10-12 17:28:36 -070010362 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010364 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010365 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366
10367 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10368 struct ieee80211_supported_band *band = wiphy->bands[i];
10369
Dustin Browna30892e2016-10-12 17:28:36 -070010370 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010371 eCSR_BAND_5G == pCfg->nBandCapability) {
10372 /* 5G only */
10373#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10374 /* Enable social channels for P2P */
10375 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10376 (band->channels[j].center_freq))
10377 band->channels[j].flags &=
10378 ~IEEE80211_CHAN_DISABLED;
10379 else
10380#endif
10381 band->channels[j].flags |=
10382 IEEE80211_CHAN_DISABLED;
10383 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010384 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010385 eCSR_BAND_24 == pCfg->nBandCapability) {
10386 /* 2G only */
10387 band->channels[j].flags |=
10388 IEEE80211_CHAN_DISABLED;
10389 continue;
10390 }
10391 }
10392 }
10393 /*Initialise the supported cipher suite details */
10394 wiphy->cipher_suites = hdd_cipher_suites;
10395 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10396
10397 /*signal strength in mBm (100*dBm) */
10398 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10399 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10400
Anurag Chouhan6d760662016-02-20 16:05:43 +053010401 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010402 wiphy->n_vendor_commands =
10403 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10404 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10405
10406 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10407 wiphy->n_vendor_events =
10408 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10409 }
10410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411 if (pCfg->enableDFSMasterCap) {
10412 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10413 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414
10415 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10416
10417#ifdef QCA_HT_2040_COEX
10418 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10419#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010420 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010421
10422#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10423 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10424 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10425 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10426 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10427#endif
10428
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010429 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010430 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010431
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010432 EXIT();
10433 return 0;
10434}
10435
Abhishek Singhf512bf32016-05-04 16:47:46 +053010436/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010437 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10438 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010439 *
10440 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010441 * memory allocated in wlan_hdd_cfg80211_init also
10442 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010443 *
10444 * Return: void
10445 */
10446void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10447{
10448 int i;
10449
Dustin Browna30892e2016-10-12 17:28:36 -070010450 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010451 if (NULL != wiphy->bands[i] &&
10452 (NULL != wiphy->bands[i]->channels)) {
10453 qdf_mem_free(wiphy->bands[i]->channels);
10454 wiphy->bands[i]->channels = NULL;
10455 }
10456 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010457 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010458}
10459
Yingying Tang80e15f32016-09-27 18:23:01 +080010460/**
10461 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10462 * @hdd_ctx: HDD context
10463 *
10464 * this function will update capabilities for supported bands
10465 *
10466 * Return: void
10467 */
10468static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10469{
10470 uint32_t val32;
10471 uint16_t val16;
10472 tSirMacHTCapabilityInfo *ht_cap_info;
10473 QDF_STATUS status;
10474
10475 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10476 if (QDF_STATUS_SUCCESS != status) {
10477 hdd_err("could not get HT capability info");
10478 val32 = 0;
10479 }
10480 val16 = (uint16_t)val32;
10481 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10482
10483 if (ht_cap_info->txSTBC == true) {
10484 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10485 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10486 IEEE80211_HT_CAP_TX_STBC;
10487 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10488 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10489 IEEE80211_HT_CAP_TX_STBC;
10490 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010491
10492 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10493 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10494 vht_cap.vht_supported = 0;
10495 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10496 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10497 vht_cap.vht_supported = 0;
10498 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10499 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010500}
10501
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010502/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010503 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010504 * initialization. In wlan_hdd_cfg80211_init, only the
10505 * default values will be initialized. The final initialization
10506 * of all required members can be done here.
10507 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010508void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509{
Yingying Tang80e15f32016-09-27 18:23:01 +080010510 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10511
10512 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010513}
10514
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010515/**
10516 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10517 * @cfg: hdd cfg
10518 *
10519 * this function update 11n mode in hdd cfg
10520 *
10521 * Return: void
10522 */
10523void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10524{
10525 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10526 hdd_notice("support 11ac");
10527 } else {
10528 hdd_notice("not support 11ac");
10529 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10530 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10531 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10532 cfg->sap_p2p_11ac_override = 0;
10533 }
10534 }
10535}
10536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010537/* In this function we are registering wiphy. */
10538int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10539{
10540 ENTER();
10541 /* Register our wiphy dev with cfg80211 */
10542 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010543 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010544 return -EIO;
10545 }
10546
10547 EXIT();
10548 return 0;
10549}
10550
10551/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010552 * HDD function to update wiphy capability based on target offload status.
10553 *
10554 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10555 * capability even before downloading firmware to the target. In discrete
10556 * case, host will get know certain offload capability (say sched_scan
10557 * caps) only after downloading firmware to the target and target boots up.
10558 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10559 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010560 */
10561void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10562{
10563#ifdef FEATURE_WLAN_SCAN_PNO
10564 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10565 struct hdd_config *pCfg = pHddCtx->config;
10566
10567 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10568 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010569 * have PNO support.
10570 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010571 if (!pCfg->PnoOffload) {
10572 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10573 wiphy->max_sched_scan_ssids = 0;
10574 wiphy->max_match_sets = 0;
10575 wiphy->max_sched_scan_ie_len = 0;
10576 }
10577#endif
10578}
10579
10580/* This function registers for all frame which supplicant is interested in */
10581void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10582{
10583 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10584 /* Register for all P2P action, public action etc frames */
10585 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10586
10587 ENTER();
10588
Abhishek Singh7996eb72015-12-30 17:24:02 +053010589 /* Register frame indication call back */
10590 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10591
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010592 /* Register for p2p ack indication */
10593 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010595 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010596 * initialized. Once we will move to 2.6.37 kernel, in which we have
10597 * frame register ops, we will move this code as a part of that
10598 */
10599
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010600 /* GAS Initial Request */
10601 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10602 (uint8_t *) GAS_INITIAL_REQ,
10603 GAS_INITIAL_REQ_SIZE);
10604
10605 /* GAS Initial Response */
10606 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10607 (uint8_t *) GAS_INITIAL_RSP,
10608 GAS_INITIAL_RSP_SIZE);
10609
10610 /* GAS Comeback Request */
10611 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10612 (uint8_t *) GAS_COMEBACK_REQ,
10613 GAS_COMEBACK_REQ_SIZE);
10614
10615 /* GAS Comeback Response */
10616 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10617 (uint8_t *) GAS_COMEBACK_RSP,
10618 GAS_COMEBACK_RSP_SIZE);
10619
10620 /* P2P Public Action */
10621 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10622 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10623 P2P_PUBLIC_ACTION_FRAME_SIZE);
10624
10625 /* P2P Action */
10626 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10627 (uint8_t *) P2P_ACTION_FRAME,
10628 P2P_ACTION_FRAME_SIZE);
10629
10630 /* WNM BSS Transition Request frame */
10631 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10632 (uint8_t *) WNM_BSS_ACTION_FRAME,
10633 WNM_BSS_ACTION_FRAME_SIZE);
10634
10635 /* WNM-Notification */
10636 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10637 (uint8_t *) WNM_NOTIFICATION_FRAME,
10638 WNM_NOTIFICATION_FRAME_SIZE);
10639}
10640
10641void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10642{
10643 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10644 /* Register for all P2P action, public action etc frames */
10645 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10646
10647 ENTER();
10648
10649 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010650 * initialized. Once we will move to 2.6.37 kernel, in which we have
10651 * frame register ops, we will move this code as a part of that
10652 */
10653
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010654 /* GAS Initial Request */
10655
10656 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10657 (uint8_t *) GAS_INITIAL_REQ,
10658 GAS_INITIAL_REQ_SIZE);
10659
10660 /* GAS Initial Response */
10661 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10662 (uint8_t *) GAS_INITIAL_RSP,
10663 GAS_INITIAL_RSP_SIZE);
10664
10665 /* GAS Comeback Request */
10666 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10667 (uint8_t *) GAS_COMEBACK_REQ,
10668 GAS_COMEBACK_REQ_SIZE);
10669
10670 /* GAS Comeback Response */
10671 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10672 (uint8_t *) GAS_COMEBACK_RSP,
10673 GAS_COMEBACK_RSP_SIZE);
10674
10675 /* P2P Public Action */
10676 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10677 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10678 P2P_PUBLIC_ACTION_FRAME_SIZE);
10679
10680 /* P2P Action */
10681 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10682 (uint8_t *) P2P_ACTION_FRAME,
10683 P2P_ACTION_FRAME_SIZE);
10684
10685 /* WNM-Notification */
10686 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10687 (uint8_t *) WNM_NOTIFICATION_FRAME,
10688 WNM_NOTIFICATION_FRAME_SIZE);
10689}
10690
10691#ifdef FEATURE_WLAN_WAPI
10692void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10693 const uint8_t *mac_addr, const uint8_t *key,
10694 int key_Len)
10695{
10696 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10697 tCsrRoamSetKey setKey;
10698 bool isConnected = true;
10699 int status = 0;
10700 uint32_t roamId = 0xFF;
10701 uint8_t *pKeyPtr = NULL;
10702 int n = 0;
10703
Jeff Johnson46b40792016-06-29 14:03:14 -070010704 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010705 hdd_device_mode_to_string(pAdapter->device_mode),
10706 pAdapter->device_mode);
10707
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010708 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010709 setKey.keyId = key_index; /* Store Key ID */
10710 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10711 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10712 setKey.paeRole = 0; /* the PAE role */
10713 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010714 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010715 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010716 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010717 }
10718 setKey.keyLength = key_Len;
10719 pKeyPtr = setKey.Key;
10720 memcpy(pKeyPtr, key, key_Len);
10721
Jeff Johnson46b40792016-06-29 14:03:14 -070010722 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010723 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010724 hdd_notice("WAPI KEY Data[%d]:%02x ",
10725 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010726
10727 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10728 if (isConnected) {
10729 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10730 pAdapter->sessionId, &setKey, &roamId);
10731 }
10732 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010733 hdd_err("sme_roam_set_key returned ERROR status= %d",
10734 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010735 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10736 }
10737}
10738#endif /* FEATURE_WLAN_WAPI */
10739
10740uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10741 uint8_t eid)
10742{
10743 int left = length;
10744 uint8_t *ptr = (uint8_t *)ies_ptr;
10745 uint8_t elem_id, elem_len;
10746
10747 while (left >= 2) {
10748 elem_id = ptr[0];
10749 elem_len = ptr[1];
10750 left -= 2;
10751 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010752 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010753 eid, elem_len, left);
10754 return NULL;
10755 }
10756 if (elem_id == eid) {
10757 return ptr;
10758 }
10759
10760 left -= elem_len;
10761 ptr += (elem_len + 2);
10762 }
10763 return NULL;
10764}
10765
10766/*
10767 * FUNCTION: wlan_hdd_validate_operation_channel
10768 * called by wlan_hdd_cfg80211_start_bss() and
10769 * wlan_hdd_set_channel()
10770 * This function validates whether given channel is part of valid
10771 * channel list.
10772 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010773QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010774 int channel)
10775{
10776
10777 uint32_t num_ch = 0;
10778 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10779 u32 indx = 0;
10780 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10781 uint8_t fValidChannel = false, count = 0;
10782 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10783
10784 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10785
10786 if (hdd_pConfig_ini->sapAllowAllChannel) {
10787 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010788 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010789 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010790 fValidChannel = true;
10791 break;
10792 }
10793 }
10794 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010795 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010796 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010797 }
10798 } else {
10799 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10800 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010801 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010802 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010803 }
10804 for (indx = 0; indx < num_ch; indx++) {
10805 if (channel == valid_ch[indx]) {
10806 break;
10807 }
10808 }
10809
10810 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010811 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010812 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813 }
10814 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010815 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816
10817}
10818
10819#ifdef DHCP_SERVER_OFFLOAD
10820static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10821{
10822 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10823 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10824 uint8_t numEntries = 0;
10825 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10826 uint8_t num;
10827 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010828 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010829 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010830 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 return;
10832 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010833 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10834 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10835 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10836 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10837 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10838 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010839 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 goto end;
10841 }
10842 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010843 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010844 goto end;
10845 }
10846 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010847 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010848 goto end;
10849 }
10850 for (num = 0; num < numEntries; num++) {
10851 temp = srv_ip[num];
10852 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10853 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010854 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010856 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857 goto end;
10858 }
Jeff Johnson77848112016-06-29 14:52:06 -070010859 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010860end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010861 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862 return;
10863}
10864#endif /* DHCP_SERVER_OFFLOAD */
10865
10866static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10867 struct net_device *dev,
10868 struct bss_parameters *params)
10869{
10870 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10871 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10872 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010873 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010874
10875 ENTER();
10876
Anurag Chouhan6d760662016-02-20 16:05:43 +053010877 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010878 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010879 return -EINVAL;
10880 }
10881
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010882 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10883 hdd_err("invalid session id: %d", pAdapter->sessionId);
10884 return -EINVAL;
10885 }
10886
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010887 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010888 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10889 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010890 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010891 hdd_device_mode_to_string(pAdapter->device_mode),
10892 pAdapter->device_mode, params->ap_isolate);
10893
10894 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10895 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010896 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010898
Krunal Sonib4326f22016-03-10 13:05:51 -080010899 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10900 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010901 return -EOPNOTSUPP;
10902 }
10903
10904 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010905 * want to update this parameter
10906 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 if (-1 != params->ap_isolate) {
10908 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10909 !!params->ap_isolate;
10910
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010911 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010912 pAdapter->sessionId,
10913 pAdapter->sessionCtx.
10914 ap.
10915 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010916 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917 ret = -EINVAL;
10918 }
10919 }
10920
10921 EXIT();
10922 return ret;
10923}
10924
Krunal Soni8c37e322016-02-03 16:08:37 -080010925/**
10926 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10927 * @ndev: pointer to net device provided by supplicant
10928 * @type: type of the interface, upper layer wanted to change
10929 *
10930 * Upper layer provides the new interface mode that needs to be changed
10931 * for given net device
10932 *
10933 * Return: success or failure in terms of integer value
10934 */
10935static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010936 enum nl80211_iftype type)
10937{
Krunal Soni8c37e322016-02-03 16:08:37 -080010938 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10939 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10940 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 hdd_wext_state_t *wext;
10942 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010943 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010944
10945 ENTER();
10946
Krunal Soni8c37e322016-02-03 16:08:37 -080010947 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010948 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010949 return 0;
10950 }
10951
10952 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010953 hdd_stop_adapter(hdd_ctx, adapter, true);
10954 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010955 wdev->iftype = type;
10956 /*Check for sub-string p2p to confirm its a p2p interface */
10957 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010958 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010959 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010960 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010961 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010962 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010963 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010964 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010966 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010968 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10969 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010970 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10971 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010972 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010973 adapter->scan_info.scanAddIE.length;
10974 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010975 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010976 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10977 wext->roamProfile.phyMode =
10978 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10979 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010980 EXIT();
10981 return status;
10982}
10983
10984static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10985 struct net_device *dev,
10986 struct bss_parameters *params)
10987{
10988 int ret;
10989
10990 cds_ssr_protect(__func__);
10991 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10992 cds_ssr_unprotect(__func__);
10993
10994 return ret;
10995}
10996
10997/* FUNCTION: wlan_hdd_change_country_code_cd
10998 * to wait for contry code completion
10999 */
11000void *wlan_hdd_change_country_code_cb(void *pAdapter)
11001{
11002 hdd_adapter_t *call_back_pAdapter = pAdapter;
11003 complete(&call_back_pAdapter->change_country_code);
11004 return NULL;
11005}
11006
Rajeev Kumar98edb772016-01-19 12:42:19 -080011007/**
11008 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11009 * @wiphy: Pointer to the wiphy structure
11010 * @ndev: Pointer to the net device
11011 * @type: Interface type
11012 * @flags: Flags for change interface
11013 * @params: Pointer to change interface parameters
11014 *
11015 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 */
11017static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11018 struct net_device *ndev,
11019 enum nl80211_iftype type,
11020 u32 *flags,
11021 struct vif_params *params)
11022{
11023 struct wireless_dev *wdev;
11024 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11025 hdd_context_t *pHddCtx;
11026 tCsrRoamProfile *pRoamProfile = NULL;
11027 eCsrRoamBssType LastBSSType;
11028 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011029 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011030 int status;
11031
11032 ENTER();
11033
Anurag Chouhan6d760662016-02-20 16:05:43 +053011034 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011035 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011036 return -EINVAL;
11037 }
11038
11039 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11040 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011041 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011042 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011043
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011044 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11046 pAdapter->sessionId, type));
11047
Jeff Johnson77848112016-06-29 14:52:06 -070011048 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011049 pAdapter->device_mode, type);
11050
Arun Khandavallifae92942016-08-01 13:31:08 +053011051 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11052 if (status) {
11053 hdd_err("Failed to start modules");
11054 return -EINVAL;
11055 }
11056
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011057 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011058 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11059 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011060 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011061 return -EINVAL;
11062 }
11063
11064 pConfig = pHddCtx->config;
11065 wdev = ndev->ieee80211_ptr;
11066
11067 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011068 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069
Nitesh Shahe6359752017-02-23 19:57:50 +053011070 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011071 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11072 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11073 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11074 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011075 hdd_wext_state_t *pWextState =
11076 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11077
11078 pRoamProfile = &pWextState->roamProfile;
11079 LastBSSType = pRoamProfile->BSSType;
11080
11081 switch (type) {
11082 case NL80211_IFTYPE_STATION:
11083 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011084 case NL80211_IFTYPE_ADHOC:
11085 if (type == NL80211_IFTYPE_ADHOC) {
11086 wlan_hdd_tdls_exit(pAdapter);
11087 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011088 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011089 }
11090 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11091 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011092 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011093 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011094 if (hdd_start_adapter(pAdapter)) {
11095 hdd_err("Failed to start adapter :%d",
11096 pAdapter->device_mode);
11097 return -EINVAL;
11098 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011100 case NL80211_IFTYPE_AP:
11101 case NL80211_IFTYPE_P2P_GO:
11102 {
Jeff Johnson77848112016-06-29 14:52:06 -070011103 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011104 (type ==
11105 NL80211_IFTYPE_AP) ? "SoftAP" :
11106 "P2pGo");
11107
11108 /* Cancel any remain on channel for GO mode */
11109 if (NL80211_IFTYPE_P2P_GO == type) {
11110 wlan_hdd_cancel_existing_remain_on_channel
11111 (pAdapter);
11112 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011113
Arun Khandavallifae92942016-08-01 13:31:08 +053011114 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 /* De-init the adapter */
11116 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11117 memset(&pAdapter->sessionCtx, 0,
11118 sizeof(pAdapter->sessionCtx));
11119 pAdapter->device_mode =
11120 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011121 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11122 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011123
11124 /*
11125 * Fw will take care incase of concurrency
11126 */
11127
Krunal Sonib4326f22016-03-10 13:05:51 -080011128 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011130 /* To meet Android requirements create
11131 * a randomized MAC address of the
11132 * form 02:1A:11:Fx:xx:xx
11133 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011134 get_random_bytes(&ndev->dev_addr[3], 3);
11135 ndev->dev_addr[0] = 0x02;
11136 ndev->dev_addr[1] = 0x1A;
11137 ndev->dev_addr[2] = 0x11;
11138 ndev->dev_addr[3] |= 0xF0;
11139 memcpy(pAdapter->macAddressCurrent.
11140 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011141 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 pr_info("wlan: Generated HotSpot BSSID "
11143 MAC_ADDRESS_STR "\n",
11144 MAC_ADDR_ARRAY(ndev->dev_addr));
11145 }
11146
11147 hdd_set_ap_ops(pAdapter->dev);
11148
Arun Khandavallifae92942016-08-01 13:31:08 +053011149 if (hdd_start_adapter(pAdapter)) {
11150 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011151 return -EINVAL;
11152 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 /* Interface type changed update in wiphy structure */
11154 if (wdev) {
11155 wdev->iftype = type;
11156 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011157 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 return -EINVAL;
11159 }
11160 goto done;
11161 }
11162
11163 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011164 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 type);
11166 return -EOPNOTSUPP;
11167 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011168 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11169 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170 switch (type) {
11171 case NL80211_IFTYPE_STATION:
11172 case NL80211_IFTYPE_P2P_CLIENT:
11173 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011174 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11175 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011176 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011178 if (hdd_start_adapter(pAdapter)) {
11179 hdd_err("Failed to start adapter :%d",
11180 pAdapter->device_mode);
11181 return -EINVAL;
11182 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183 goto done;
11184
11185 case NL80211_IFTYPE_AP:
11186 case NL80211_IFTYPE_P2P_GO:
11187 wdev->iftype = type;
11188 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011189 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011190 goto done;
11191
11192 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011193 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011194 type);
11195 return -EOPNOTSUPP;
11196 }
11197 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011198 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011199 pAdapter->device_mode);
11200 return -EOPNOTSUPP;
11201 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011202done:
11203 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011204 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011206 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207
11208 EXIT();
11209 return 0;
11210}
11211
Rajeev Kumar98edb772016-01-19 12:42:19 -080011212/**
11213 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11214 * @wiphy: Pointer to the wiphy structure
11215 * @ndev: Pointer to the net device
11216 * @type: Interface type
11217 * @flags: Flags for change interface
11218 * @params: Pointer to change interface parameters
11219 *
11220 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011221 */
11222static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11223 struct net_device *ndev,
11224 enum nl80211_iftype type,
11225 u32 *flags,
11226 struct vif_params *params)
11227{
11228 int ret;
11229
11230 cds_ssr_protect(__func__);
11231 ret =
11232 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11233 cds_ssr_unprotect(__func__);
11234
11235 return ret;
11236}
11237
11238#ifdef FEATURE_WLAN_TDLS
11239static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11240 int index, uint8_t match)
11241{
11242 int i;
11243 for (i = 0; i < index; i++) {
11244 if (arr[i] == match)
11245 return true;
11246 }
11247 return false;
11248}
11249#endif
11250
11251/**
11252 * __wlan_hdd_change_station() - change station
11253 * @wiphy: Pointer to the wiphy structure
11254 * @dev: Pointer to the net device.
11255 * @mac: bssid
11256 * @params: Pointer to station parameters
11257 *
11258 * Return: 0 for success, error number on failure.
11259 */
11260#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11261static int __wlan_hdd_change_station(struct wiphy *wiphy,
11262 struct net_device *dev,
11263 const uint8_t *mac,
11264 struct station_parameters *params)
11265#else
11266static int __wlan_hdd_change_station(struct wiphy *wiphy,
11267 struct net_device *dev,
11268 uint8_t *mac,
11269 struct station_parameters *params)
11270#endif
11271{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011272 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11274 hdd_context_t *pHddCtx;
11275 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011276 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011277#ifdef FEATURE_WLAN_TDLS
11278 tCsrStaParams StaParams = { 0 };
11279 uint8_t isBufSta = 0;
11280 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011281 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011282#endif
11283 int ret;
11284
11285 ENTER();
11286
Anurag Chouhan6d760662016-02-20 16:05:43 +053011287 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011288 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289 return -EINVAL;
11290 }
11291
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011292 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011293 TRACE_CODE_HDD_CHANGE_STATION,
11294 pAdapter->sessionId, params->listen_interval));
11295
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011296 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11297 hdd_err("invalid session id: %d", pAdapter->sessionId);
11298 return -EINVAL;
11299 }
11300
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011301 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11302 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011303 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305
11306 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11307
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011308 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011309
Krunal Sonib4326f22016-03-10 13:05:51 -080011310 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11311 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11313 status =
11314 hdd_softap_change_sta_state(pAdapter,
11315 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011316 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011318 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011319 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011320 return -EINVAL;
11321 }
11322 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011323 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11324 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325#ifdef FEATURE_WLAN_TDLS
11326 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011327
11328 if (cds_is_sub_20_mhz_enabled()) {
11329 hdd_err("TDLS not allowed with sub 20 MHz");
11330 return -EINVAL;
11331 }
11332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333 StaParams.capability = params->capability;
11334 StaParams.uapsd_queues = params->uapsd_queues;
11335 StaParams.max_sp = params->max_sp;
11336
11337 /* Convert (first channel , number of channels) tuple to
11338 * the total list of channels. This goes with the assumption
11339 * that if the first channel is < 14, then the next channels
11340 * are an incremental of 1 else an incremental of 4 till the number
11341 * of channels.
11342 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011343 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 if (0 != params->supported_channels_len) {
11345 int i = 0, j = 0, k = 0, no_of_channels = 0;
11346 int num_unique_channels;
11347 int next;
11348 for (i = 0;
11349 i < params->supported_channels_len
11350 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11351 int wifi_chan_index;
11352 if (!wlan_hdd_is_duplicate_channel
11353 (StaParams.supported_channels, j,
11354 params->supported_channels[i])) {
11355 StaParams.
11356 supported_channels[j] =
11357 params->
11358 supported_channels[i];
11359 } else {
11360 continue;
11361 }
11362 wifi_chan_index =
11363 ((StaParams.supported_channels[j] <=
11364 HDD_CHANNEL_14) ? 1 : 4);
11365 no_of_channels =
11366 params->supported_channels[i + 1];
11367
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011368 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 -080011369 StaParams.
11370 supported_channels[j],
11371 wifi_chan_index,
11372 no_of_channels);
11373 for (k = 1; k <= no_of_channels &&
11374 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11375 k++) {
11376 next =
11377 StaParams.
11378 supported_channels[j] +
11379 wifi_chan_index;
11380 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11381 StaParams.
11382 supported_channels[j
11383 +
11384 1]
11385 = next;
11386 } else {
11387 continue;
11388 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011389 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390 j + 1,
11391 StaParams.
11392 supported_channels[j +
11393 1]);
11394 j += 1;
11395 }
11396 }
11397 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011398 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011400 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011401 StaParams.
11402 supported_channels[i]);
11403 }
11404 if (MAX_CHANNEL < num_unique_channels)
11405 num_unique_channels = MAX_CHANNEL;
11406 StaParams.supported_channels_len =
11407 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011408 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409 StaParams.supported_channels_len);
11410 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011411 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011412 params->supported_oper_classes,
11413 params->supported_oper_classes_len);
11414 StaParams.supported_oper_classes_len =
11415 params->supported_oper_classes_len;
11416
11417 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011418 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419 params->ext_capab,
11420 sizeof(StaParams.extn_capability));
11421
11422 if (NULL != params->ht_capa) {
11423 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011424 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011425 sizeof(tSirHTCap));
11426 }
11427
11428 StaParams.supported_rates_len =
11429 params->supported_rates_len;
11430
11431 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11432 * The supported_rates array , for all the structures propogating till Add Sta
11433 * to the firmware has to be modified , if the supplicant (ieee80211) is
11434 * modified to send more rates.
11435 */
11436
11437 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11438 */
11439 if (StaParams.supported_rates_len >
11440 SIR_MAC_MAX_SUPP_RATES)
11441 StaParams.supported_rates_len =
11442 SIR_MAC_MAX_SUPP_RATES;
11443
11444 if (0 != StaParams.supported_rates_len) {
11445 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011446 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447 params->supported_rates,
11448 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011449 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011450 StaParams.supported_rates_len);
11451 for (i = 0; i < StaParams.supported_rates_len;
11452 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011453 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011454 StaParams.supported_rates[i]);
11455 }
11456
11457 if (NULL != params->vht_capa) {
11458 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011459 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011460 params->vht_capa,
11461 sizeof(tSirVHTCap));
11462 }
11463
11464 if (0 != params->ext_capab_len) {
11465 /*Define A Macro : TODO Sunil */
11466 if ((1 << 4) & StaParams.extn_capability[3]) {
11467 isBufSta = 1;
11468 }
11469 /* TDLS Channel Switching Support */
11470 if ((1 << 6) & StaParams.extn_capability[3]) {
11471 isOffChannelSupported = 1;
11472 }
11473 }
11474
Nitesh Shah99934ac2016-09-05 15:54:08 +053011475 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011476 (params->ht_capa || params->vht_capa ||
11477 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011478 is_qos_wmm_sta = true;
11479
11480 hdd_notice("%s: TDLS Peer is QOS capable"
11481 " is_qos_wmm_sta= %d HTcapPresent = %d",
11482 __func__, is_qos_wmm_sta,
11483 StaParams.htcap_present);
11484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011485 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011486 &StaParams,
11487 isBufSta,
11488 isOffChannelSupported,
11489 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011490 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011491 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011492 return -EINVAL;
11493 }
11494
11495 status =
11496 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11497 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011498 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011499 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 return -EINVAL;
11501 }
11502 }
11503#endif
11504 }
11505 EXIT();
11506 return ret;
11507}
11508
11509/**
11510 * wlan_hdd_change_station() - cfg80211 change station handler function
11511 * @wiphy: Pointer to the wiphy structure
11512 * @dev: Pointer to the net device.
11513 * @mac: bssid
11514 * @params: Pointer to station parameters
11515 *
11516 * This is the cfg80211 change station handler function which invokes
11517 * the internal function @__wlan_hdd_change_station with
11518 * SSR protection.
11519 *
11520 * Return: 0 for success, error number on failure.
11521 */
11522#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11523static int wlan_hdd_change_station(struct wiphy *wiphy,
11524 struct net_device *dev,
11525 const u8 *mac,
11526 struct station_parameters *params)
11527#else
11528static int wlan_hdd_change_station(struct wiphy *wiphy,
11529 struct net_device *dev,
11530 u8 *mac,
11531 struct station_parameters *params)
11532#endif
11533{
11534 int ret;
11535
11536 cds_ssr_protect(__func__);
11537 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11538 cds_ssr_unprotect(__func__);
11539
11540 return ret;
11541}
11542
11543/*
11544 * FUNCTION: __wlan_hdd_cfg80211_add_key
11545 * This function is used to initialize the key information
11546 */
11547static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11548 struct net_device *ndev,
11549 u8 key_index, bool pairwise,
11550 const u8 *mac_addr,
11551 struct key_params *params)
11552{
11553 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11554 tCsrRoamSetKey setKey;
11555 int status;
11556 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011558 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011559 hdd_context_t *pHddCtx;
11560 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11561
11562 ENTER();
11563
Anurag Chouhan6d760662016-02-20 16:05:43 +053011564 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011565 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011566 return -EINVAL;
11567 }
11568
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011569 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11570 hdd_err("invalid session id: %d", pAdapter->sessionId);
11571 return -EINVAL;
11572 }
11573
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011574 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011575 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11576 pAdapter->sessionId, params->key_len));
11577 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11578 status = wlan_hdd_validate_context(pHddCtx);
11579
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011580 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011581 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011582
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011583 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584 hdd_device_mode_to_string(pAdapter->device_mode),
11585 pAdapter->device_mode);
11586
11587 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011588 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011589
11590 return -EINVAL;
11591 }
11592
11593 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011594 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011595
11596 return -EINVAL;
11597 }
11598
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011599 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600
11601 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011602 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011603 setKey.keyId = key_index;
11604 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011605 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011606
11607 switch (params->cipher) {
11608 case WLAN_CIPHER_SUITE_WEP40:
11609 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11610 break;
11611
11612 case WLAN_CIPHER_SUITE_WEP104:
11613 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11614 break;
11615
11616 case WLAN_CIPHER_SUITE_TKIP:
11617 {
11618 u8 *pKey = &setKey.Key[0];
11619 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11620
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011621 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011623 /* Supplicant sends the 32bytes key in this order
11624 *
11625 * |--------------|----------|----------|
11626 * | Tk1 |TX-MIC | RX Mic |
11627 * |--------------|----------|----------|
11628 * <---16bytes---><--8bytes--><--8bytes-->
11629 *
11630 * Sme expects the 32 bytes key to be in the below order
11631 *
11632 * |--------------|----------|----------|
11633 * | Tk1 |RX-MIC | TX Mic |
11634 * |--------------|----------|----------|
11635 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 */
11637 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011638 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639
11640 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011641 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011642
11643 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011644 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645
11646 break;
11647 }
11648
11649 case WLAN_CIPHER_SUITE_CCMP:
11650 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11651 break;
11652
11653#ifdef FEATURE_WLAN_WAPI
11654 case WLAN_CIPHER_SUITE_SMS4:
11655 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011656 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11658 mac_addr, params->key,
11659 params->key_len);
11660 return 0;
11661 }
11662#endif
11663
11664#ifdef FEATURE_WLAN_ESE
11665 case WLAN_CIPHER_SUITE_KRK:
11666 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11667 break;
11668#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11669 case WLAN_CIPHER_SUITE_BTK:
11670 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11671 break;
11672#endif
11673#endif
11674
11675#ifdef WLAN_FEATURE_11W
11676 case WLAN_CIPHER_SUITE_AES_CMAC:
11677 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11678 break;
11679#endif
11680
11681 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011682 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011683 return -EOPNOTSUPP;
11684 }
11685
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011686 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687
11688 if (!pairwise) {
11689 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011690 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011692 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 } else {
11694 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011695 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011696 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011697 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011699 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011700 /* if a key is already installed, block all subsequent ones */
11701 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011702 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703 return 0;
11704 }
11705
11706 setKey.keyDirection = eSIR_TX_RX;
11707 /*Set the group key */
11708 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11709 pAdapter->sessionId, &setKey, &roamId);
11710
11711 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011712 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 return -EINVAL;
11714 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011715 /* Save the keys here and call sme_roam_set_key for setting
11716 * the PTK after peer joins the IBSS network
11717 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011718 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 &setKey, sizeof(tCsrRoamSetKey));
11720
11721 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11722 return status;
11723 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011724 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11725 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011726 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11727 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011728 status = wlansap_set_key_sta(
11729 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011730 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011731 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011732 __LINE__, status);
11733 }
11734 }
11735
11736 /* Save the key in ap ctx for use on START_BASS and restart */
11737 if (pairwise ||
11738 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11739 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011740 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741 sizeof(tCsrRoamSetKey));
11742 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011743 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744 sizeof(tCsrRoamSetKey));
11745
Krunal Sonib4326f22016-03-10 13:05:51 -080011746 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11747 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748 hdd_wext_state_t *pWextState =
11749 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11750 hdd_station_ctx_t *pHddStaCtx =
11751 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11752
11753 if (!pairwise) {
11754 /* set group key */
11755 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011756 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757 __func__, __LINE__);
11758 hdd_perform_roam_set_key_complete(pAdapter);
11759 }
11760 }
11761
11762 pWextState->roamProfile.Keys.KeyLength[key_index] =
11763 (u8) params->key_len;
11764
11765 pWextState->roamProfile.Keys.defaultIndex = key_index;
11766
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011767 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 KeyMaterial[key_index][0], params->key,
11769 params->key_len);
11770
11771 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11772
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011773 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011774 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11775 setKey.keyDirection);
11776
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011777 /* The supplicant may attempt to set the PTK once
11778 * pre-authentication is done. Save the key in the
11779 * UMAC and include it in the ADD BSS request
11780 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011781 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011783 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011784 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011785 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011786 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011787 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011788 return -EINVAL;
11789 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790
11791 /* issue set key request to SME */
11792 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11793 pAdapter->sessionId, &setKey, &roamId);
11794
11795 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011796 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797 pHddStaCtx->roam_info.roamingState =
11798 HDD_ROAM_STATE_NONE;
11799 return -EINVAL;
11800 }
11801
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011802 /* in case of IBSS as there was no information
11803 * available about WEP keys during IBSS join, group
11804 * key intialized with NULL key, so re-initialize
11805 * group key with correct value
11806 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807 if ((eCSR_BSS_TYPE_START_IBSS ==
11808 pWextState->roamProfile.BSSType)
11809 &&
11810 !((IW_AUTH_KEY_MGMT_802_1X ==
11811 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11812 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11813 pHddStaCtx->conn_info.authType)
11814 )
11815 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11816 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11817 )
11818 ) {
11819 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011820 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011822 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11824 setKey.keyDirection);
11825
11826 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11827 pAdapter->sessionId, &setKey,
11828 &roamId);
11829
11830 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011831 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832 pHddStaCtx->roam_info.roamingState =
11833 HDD_ROAM_STATE_NONE;
11834 return -EINVAL;
11835 }
11836 }
11837 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011838 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839 return 0;
11840}
11841
11842static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11843 struct net_device *ndev,
11844 u8 key_index, bool pairwise,
11845 const u8 *mac_addr,
11846 struct key_params *params)
11847{
11848 int ret;
11849 cds_ssr_protect(__func__);
11850 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11851 mac_addr, params);
11852 cds_ssr_unprotect(__func__);
11853
11854 return ret;
11855}
11856
11857/*
11858 * FUNCTION: __wlan_hdd_cfg80211_get_key
11859 * This function is used to get the key information
11860 */
11861static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11862 struct net_device *ndev,
11863 u8 key_index, bool pairwise,
11864 const u8 *mac_addr, void *cookie,
11865 void (*callback)(void *cookie,
11866 struct key_params *)
11867 )
11868{
11869 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11870 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11871 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11872 struct key_params params;
11873
11874 ENTER();
11875
Anurag Chouhan6d760662016-02-20 16:05:43 +053011876 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011877 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011878 return -EINVAL;
11879 }
11880
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011881 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882 hdd_device_mode_to_string(pAdapter->device_mode),
11883 pAdapter->device_mode);
11884
11885 memset(&params, 0, sizeof(params));
11886
11887 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011888 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889 key_index);
11890 return -EINVAL;
11891 }
11892
11893 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11894 case eCSR_ENCRYPT_TYPE_NONE:
11895 params.cipher = IW_AUTH_CIPHER_NONE;
11896 break;
11897
11898 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11899 case eCSR_ENCRYPT_TYPE_WEP40:
11900 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11901 break;
11902
11903 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11904 case eCSR_ENCRYPT_TYPE_WEP104:
11905 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11906 break;
11907
11908 case eCSR_ENCRYPT_TYPE_TKIP:
11909 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11910 break;
11911
11912 case eCSR_ENCRYPT_TYPE_AES:
11913 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11914 break;
11915
11916 default:
11917 params.cipher = IW_AUTH_CIPHER_NONE;
11918 break;
11919 }
11920
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011921 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011922 TRACE_CODE_HDD_CFG80211_GET_KEY,
11923 pAdapter->sessionId, params.cipher));
11924
11925 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11926 params.seq_len = 0;
11927 params.seq = NULL;
11928 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11929 callback(cookie, &params);
11930
11931 EXIT();
11932 return 0;
11933}
11934
11935static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11936 struct net_device *ndev,
11937 u8 key_index, bool pairwise,
11938 const u8 *mac_addr, void *cookie,
11939 void (*callback)(void *cookie,
11940 struct key_params *)
11941 )
11942{
11943 int ret;
11944
11945 cds_ssr_protect(__func__);
11946 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11947 mac_addr, cookie, callback);
11948 cds_ssr_unprotect(__func__);
11949
11950 return ret;
11951}
11952
11953/**
11954 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11955 * @wiphy: wiphy interface context
11956 * @ndev: pointer to net device
11957 * @key_index: Key index used in 802.11 frames
11958 * @unicast: true if it is unicast key
11959 * @multicast: true if it is multicast key
11960 *
11961 * This function is required for cfg80211_ops API.
11962 * It is used to delete the key information
11963 * Underlying hardware implementation does not have API to delete the
11964 * encryption key. It is automatically deleted when the peer is
11965 * removed. Hence this function currently does nothing.
11966 * Future implementation may interprete delete key operation to
11967 * replacing the key with a random junk value, effectively making it
11968 * useless.
11969 *
11970 * Return: status code, always 0.
11971 */
11972
11973static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11974 struct net_device *ndev,
11975 u8 key_index,
11976 bool pairwise, const u8 *mac_addr)
11977{
11978 EXIT();
11979 return 0;
11980}
11981
11982/**
11983 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11984 * @wiphy: Pointer to wiphy structure.
11985 * @dev: Pointer to net_device structure.
11986 * @key_index: key index
11987 * @pairwise: pairwise
11988 * @mac_addr: mac address
11989 *
11990 * This is the cfg80211 delete key handler function which invokes
11991 * the internal function @__wlan_hdd_cfg80211_del_key with
11992 * SSR protection.
11993 *
11994 * Return: 0 for success, error number on failure.
11995 */
11996static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11997 struct net_device *dev,
11998 u8 key_index,
11999 bool pairwise, const u8 *mac_addr)
12000{
12001 int ret;
12002
12003 cds_ssr_protect(__func__);
12004 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12005 pairwise, mac_addr);
12006 cds_ssr_unprotect(__func__);
12007
12008 return ret;
12009}
12010
12011/*
12012 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12013 * This function is used to set the default tx key index
12014 */
12015static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12016 struct net_device *ndev,
12017 u8 key_index,
12018 bool unicast, bool multicast)
12019{
12020 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12021 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12022 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12023 hdd_context_t *pHddCtx;
12024 int status;
12025
12026 ENTER();
12027
Anurag Chouhan6d760662016-02-20 16:05:43 +053012028 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012029 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 return -EINVAL;
12031 }
12032
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012033 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12034 hdd_err("invalid session id: %d", pAdapter->sessionId);
12035 return -EINVAL;
12036 }
12037
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012038 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12040 pAdapter->sessionId, key_index));
12041
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012042 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 hdd_device_mode_to_string(pAdapter->device_mode),
12044 pAdapter->device_mode, key_index);
12045
12046 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012047 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012048 return -EINVAL;
12049 }
12050
12051 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12052 status = wlan_hdd_validate_context(pHddCtx);
12053
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012054 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012055 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056
Krunal Sonib4326f22016-03-10 13:05:51 -080012057 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12058 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012059 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12060 pHddStaCtx->conn_info.ucEncryptionType) &&
12061 (eCSR_ENCRYPT_TYPE_AES !=
12062 pHddStaCtx->conn_info.ucEncryptionType)) {
12063 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012064 * then update the default key index
12065 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012066
12067 tCsrRoamSetKey setKey;
12068 uint32_t roamId = 0xFF;
12069 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12070
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012071 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072
12073 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012074 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012075 setKey.keyId = key_index;
12076 setKey.keyLength = Keys->KeyLength[key_index];
12077
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012078 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012079 &Keys->KeyMaterial[key_index][0],
12080 Keys->KeyLength[key_index]);
12081
12082 setKey.keyDirection = eSIR_TX_RX;
12083
Anurag Chouhanc5548422016-02-24 18:33:27 +053012084 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012085 &pHddStaCtx->conn_info.bssId);
12086
12087 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12088 pWextState->roamProfile.EncryptionType.
12089 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012090 /* In the case of dynamic wep
12091 * supplicant hardcodes DWEP type to
12092 * eCSR_ENCRYPT_TYPE_WEP104 even
12093 * though ap is configured for WEP-40
12094 * encryption. In this canse the key
12095 * length is 5 but the encryption type
12096 * is 104 hence checking the key
12097 * lenght(5) and encryption type(104)
12098 * and switching encryption type to 40
12099 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 pWextState->roamProfile.EncryptionType.
12101 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12102 pWextState->roamProfile.mcEncryptionType.
12103 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12104 }
12105
12106 setKey.encType =
12107 pWextState->roamProfile.EncryptionType.
12108 encryptionType[0];
12109
12110 /* Issue set key request */
12111 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12112 pAdapter->sessionId, &setKey,
12113 &roamId);
12114
12115 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012116 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 status);
12118 return -EINVAL;
12119 }
12120 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012121 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122 /* In SoftAp mode setting key direction for default mode */
12123 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12124 pWextState->roamProfile.EncryptionType.encryptionType[0])
12125 && (eCSR_ENCRYPT_TYPE_AES !=
12126 pWextState->roamProfile.EncryptionType.
12127 encryptionType[0])) {
12128 /* Saving key direction for default key index to TX default */
12129 hdd_ap_ctx_t *pAPCtx =
12130 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12131 pAPCtx->wepKey[key_index].keyDirection =
12132 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012133 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012134 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012135 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 }
12137 }
12138
12139 EXIT();
12140 return status;
12141}
12142
12143static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12144 struct net_device *ndev,
12145 u8 key_index,
12146 bool unicast, bool multicast)
12147{
12148 int ret;
12149 cds_ssr_protect(__func__);
12150 ret =
12151 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12152 multicast);
12153 cds_ssr_unprotect(__func__);
12154
12155 return ret;
12156}
12157
Abhishek Singhc9941602016-08-09 16:06:22 +053012158/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012159 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12160 * interface that BSS might have been lost.
12161 * @pAdapter: adaptor
12162 * @bssid: bssid which might have been lost
12163 *
12164 * Return: bss which is unlinked from kernel cache
12165 */
12166struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12167 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012168{
12169 struct net_device *dev = pAdapter->dev;
12170 struct wireless_dev *wdev = dev->ieee80211_ptr;
12171 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012172 struct cfg80211_bss *bss = NULL;
12173
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012174 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012175 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012176 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012177 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012178 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012179 hdd_info("cfg80211_unlink_bss called for BSSID "
12180 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181 cfg80211_unlink_bss(wiphy, bss);
12182 }
12183 return bss;
12184}
12185
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012186#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12187 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12188static struct cfg80211_bss *
12189wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12190 struct ieee80211_channel *chan,
12191 struct ieee80211_mgmt *mgmt,
12192 size_t frame_len,
12193 int rssi, gfp_t gfp,
12194 uint64_t boottime_ns)
12195{
12196 struct cfg80211_bss *bss_status = NULL;
12197 struct cfg80211_inform_bss data = {0};
12198
12199 data.chan = chan;
12200 data.boottime_ns = boottime_ns;
12201 data.signal = rssi;
12202 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12203 frame_len, gfp);
12204 return bss_status;
12205}
12206#else
12207static struct cfg80211_bss *
12208wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12209 struct ieee80211_channel *chan,
12210 struct ieee80211_mgmt *mgmt,
12211 size_t frame_len,
12212 int rssi, gfp_t gfp,
12213 uint64_t boottime_ns)
12214{
12215 struct cfg80211_bss *bss_status = NULL;
12216
12217 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12218 rssi, gfp);
12219 return bss_status;
12220}
12221#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223/**
12224 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12225 * @pAdapter: Pointer to adapter
12226 * @bss_desc: Pointer to bss descriptor
12227 *
12228 * This function is used to inform the BSS details to nl80211 interface.
12229 *
12230 * Return: struct cfg80211_bss pointer
12231 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012232struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12233 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012234{
12235 /*
12236 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12237 * already exists in bss data base of cfg80211 for that particular BSS
12238 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12239 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12240 * As of now there is no possibility to get the mgmt(probe response)
12241 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12242 * and passing to cfg80211_inform_bss_frame.
12243 */
12244 struct net_device *dev = pAdapter->dev;
12245 struct wireless_dev *wdev = dev->ieee80211_ptr;
12246 struct wiphy *wiphy = wdev->wiphy;
12247 int chan_no = bss_desc->channelId;
12248#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12249 qcom_ie_age *qie_age = NULL;
12250 int ie_length =
12251 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12252#else
12253 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12254#endif
12255 const char *ie =
12256 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12257 unsigned int freq;
12258 struct ieee80211_channel *chan;
12259 struct ieee80211_mgmt *mgmt = NULL;
12260 struct cfg80211_bss *bss_status = NULL;
12261 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12262 int rssi = 0;
12263 hdd_context_t *pHddCtx;
12264 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012265 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012266 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012267
12268 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12269 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012270 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012271 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012272
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012273 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012274 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012275 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012276 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012277 return NULL;
12278 }
12279
12280 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012283 * Instead it wants a monotonic increasing value
12284 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012285 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012286 mgmt->u.probe_resp.timestamp =
12287 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288
12289 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12290 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12291
12292#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12293 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12294 /* Assuming this is the last IE, copy at the end */
12295 ie_length -= sizeof(qcom_ie_age);
12296 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12297 qie_age->element_id = QCOM_VENDOR_IE_ID;
12298 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12299 qie_age->oui_1 = QCOM_OUI1;
12300 qie_age->oui_2 = QCOM_OUI2;
12301 qie_age->oui_3 = QCOM_OUI3;
12302 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012303 /*
12304 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12305 * all bss related timestamp is in units of ms. Due to this when scan
12306 * results are sent to lowi the scan age is high.To address this,
12307 * send age in units of 1/10 ms.
12308 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012309 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012310 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012311 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012312 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12313 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012314 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12315 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012316#endif
12317
12318 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12319 if (bss_desc->fProbeRsp) {
12320 mgmt->frame_control |=
12321 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12322 } else {
12323 mgmt->frame_control |=
12324 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12325 }
12326
12327 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012328 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329 freq =
12330 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012331 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012332 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012333 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 freq =
12335 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012336 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012337 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012338 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012339 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340 return NULL;
12341 }
12342
12343 chan = __ieee80211_get_channel(wiphy, freq);
12344 /* When the band is changed on the fly using the GUI, three things are done
12345 * 1. scan abort
12346 * 2. flush scan results from cache
12347 * 3. update the band with the new band user specified (refer to the
12348 * hdd_set_band_helper function) as part of the scan abort, message will be
12349 * queued to PE and we proceed with flushing and changinh the band.
12350 * PE will stop the scanning further and report back the results what ever
12351 * it had till now by calling the call back function.
12352 * if the time between update band and scandone call back is sufficient
12353 * enough the band change reflects in SME, SME validates the channels
12354 * and discards the channels correponding to previous band and calls back
12355 * with zero bss results. but if the time between band update and scan done
12356 * callback is very small then band change will not reflect in SME and SME
12357 * reports to HDD all the channels correponding to previous band.this is due
12358 * to race condition.but those channels are invalid to the new band and so
12359 * this function __ieee80211_get_channel will return NULL.Each time we
12360 * report scan result with this pointer null warning kernel trace is printed.
12361 * if the scan results contain large number of APs continuosly kernel
12362 * warning trace is printed and it will lead to apps watch dog bark.
12363 * So drop the bss and continue to next bss.
12364 */
12365 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012366 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12367 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012368 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012369 return NULL;
12370 }
12371
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012372 /* Based on .ini configuration, raw rssi can be reported for bss.
12373 * Raw rssi is typically used for estimating power.
12374 */
12375
12376 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12377 bss_desc->rssi;
12378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012380 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012381
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012382 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012384 (int)(rssi / 100),
12385 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012386
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012387 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12388 frame_len, rssi,
12389 GFP_KERNEL,
12390 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012391 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012392 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012393 return bss_status;
12394}
12395
12396/**
12397 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12398 * @pAdapter: Pointer to adapter
12399 * @pRoamInfo: Pointer to roam info
12400 *
12401 * This function is used to update the BSS data base of CFG8011
12402 *
12403 * Return: struct cfg80211_bss pointer
12404 */
12405struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12406 tCsrRoamInfo *pRoamInfo)
12407{
12408 tCsrRoamConnectedProfile roamProfile;
12409 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12410 struct cfg80211_bss *bss = NULL;
12411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012412 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12413 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12414
12415 if (NULL != roamProfile.pBssDesc) {
12416 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12417 roamProfile.pBssDesc);
12418
12419 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012420 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012421
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012422 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012423 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012424 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012426 return bss;
12427}
12428/**
12429 * wlan_hdd_cfg80211_update_bss() - update bss
12430 * @wiphy: Pointer to wiphy
12431 * @pAdapter: Pointer to adapter
12432 * @scan_time: scan request timestamp
12433 *
12434 * Return: zero if success, non-zero otherwise
12435 */
12436int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12437 hdd_adapter_t *pAdapter,
12438 uint32_t scan_time)
12439{
12440 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12441 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012442 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012443 tScanResultHandle pResult;
12444 struct cfg80211_bss *bss_status = NULL;
12445 hdd_context_t *pHddCtx;
12446 int ret;
12447
12448 ENTER();
12449
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012450 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12451 hdd_err("invalid session id: %d", pAdapter->sessionId);
12452 return -EINVAL;
12453 }
12454
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012455 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012456 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12457 NO_SESSION, pAdapter->sessionId));
12458
12459 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12460 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012461 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012462 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463
12464 /* start getting scan results and populate cgf80211 BSS database */
12465 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12466
12467 /* no scan results */
12468 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012469 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012470 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 }
12472
12473 pScanResult = sme_scan_result_get_first(hHal, pResult);
12474
12475 while (pScanResult) {
12476 /*
12477 * - cfg80211_inform_bss() is not updating ie field of bss
12478 * entry if entry already exists in bss data base of cfg80211
12479 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12480 * to update thebss entry instead of cfg80211_inform_bss,
12481 * But this call expects mgmt packet as input. As of now
12482 * there is no possibility to get the mgmt(probe response)
12483 * frame from PE, converting bss_desc to
12484 * ieee80211_mgmt(probe response) and passing to c
12485 * fg80211_inform_bss_frame.
12486 * - Update BSS only if beacon timestamp is later than
12487 * scan request timestamp.
12488 */
12489 if ((scan_time == 0) ||
12490 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012491 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492 bss_status =
12493 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12494 &pScanResult->BssDescriptor);
12495
12496 if (NULL == bss_status) {
12497 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12498 } else {
12499 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012501 bss_status);
12502 }
12503 } else {
12504 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12505 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12506 }
12507 pScanResult = sme_scan_result_get_next(hHal, pResult);
12508 }
12509
12510 sme_scan_result_purge(hHal, pResult);
12511 /*
12512 * For SAP mode, scan is invoked by hostapd during SAP start
12513 * if hostapd is restarted, we need to flush previous scan
12514 * result so that it will reflect environment change
12515 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012516 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012517#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12518 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12519#endif
12520 )
12521 sme_scan_flush_result(hHal);
12522
12523 EXIT();
12524 return 0;
12525}
12526
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012527/**
12528 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12529 * @pAdapter: Pointer to adapter
12530 * @pRoamInfo: Pointer to roam info
12531 * @index: Index
12532 * @preauth: Preauth flag
12533 *
12534 * This function is used to notify the supplicant of a new PMKSA candidate.
12535 *
12536 * Return: 0 for success, non-zero for failure
12537 */
12538int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12539 tCsrRoamInfo *pRoamInfo,
12540 int index, bool preauth)
12541{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012542 struct net_device *dev = pAdapter->dev;
12543 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12544
12545 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012546 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012547
12548 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012549 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550 return -EINVAL;
12551 }
12552
12553 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012554 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12556 cfg80211_pmksa_candidate_notify(dev, index,
12557 pRoamInfo->bssid.bytes,
12558 preauth, GFP_KERNEL);
12559 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012560 return 0;
12561}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562
12563#ifdef FEATURE_WLAN_LFR_METRICS
12564/**
12565 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12566 * @pAdapter: Pointer to adapter
12567 * @pRoamInfo: Pointer to roam info
12568 *
12569 * 802.11r/LFR metrics reporting function to report preauth initiation
12570 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012571 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 */
12573#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012574QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 tCsrRoamInfo *pRoamInfo)
12576{
12577 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12578 union iwreq_data wrqu;
12579
12580 ENTER();
12581
12582 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012583 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012584 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012585 }
12586
12587 /* create the event */
12588 memset(&wrqu, 0, sizeof(wrqu));
12589 memset(metrics_notification, 0, sizeof(metrics_notification));
12590
12591 wrqu.data.pointer = metrics_notification;
12592 wrqu.data.length = scnprintf(metrics_notification,
12593 sizeof(metrics_notification),
12594 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12595 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12596
12597 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12598 metrics_notification);
12599
12600 EXIT();
12601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012602 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012603}
12604
12605/**
12606 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12607 * @pAdapter: Pointer to adapter
12608 * @pRoamInfo: Pointer to roam info
12609 * @preauth_status: Preauth status
12610 *
12611 * 802.11r/LFR metrics reporting function to report handover initiation
12612 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012613 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012614 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012615QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012616wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12617 tCsrRoamInfo *pRoamInfo,
12618 bool preauth_status)
12619{
12620 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12621 union iwreq_data wrqu;
12622
12623 ENTER();
12624
12625 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012626 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012627 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012628 }
12629
12630 /* create the event */
12631 memset(&wrqu, 0, sizeof(wrqu));
12632 memset(metrics_notification, 0, sizeof(metrics_notification));
12633
12634 scnprintf(metrics_notification, sizeof(metrics_notification),
12635 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12636 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12637
12638 if (1 == preauth_status)
12639 strlcat(metrics_notification, " true",
12640 sizeof(metrics_notification));
12641 else
12642 strlcat(metrics_notification, " false",
12643 sizeof(metrics_notification));
12644
12645 wrqu.data.pointer = metrics_notification;
12646 wrqu.data.length = strlen(metrics_notification);
12647
12648 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12649 metrics_notification);
12650
12651 EXIT();
12652
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012653 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012654}
12655
12656/**
12657 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12658 * @pAdapter: Pointer to adapter
12659 * @pRoamInfo: Pointer to roam info
12660 *
12661 * 802.11r/LFR metrics reporting function to report handover initiation
12662 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012663 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012665QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666 tCsrRoamInfo *pRoamInfo)
12667{
12668 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12669 union iwreq_data wrqu;
12670
12671 ENTER();
12672
12673 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012674 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012675 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012676 }
12677
12678 /* create the event */
12679 memset(&wrqu, 0, sizeof(wrqu));
12680 memset(metrics_notification, 0, sizeof(metrics_notification));
12681
12682 wrqu.data.pointer = metrics_notification;
12683 wrqu.data.length = scnprintf(metrics_notification,
12684 sizeof(metrics_notification),
12685 "QCOM: LFR_PREAUTH_HANDOVER "
12686 MAC_ADDRESS_STR,
12687 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12688
12689 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12690 metrics_notification);
12691
12692 EXIT();
12693
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012694 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012695}
12696#endif
12697
12698/**
12699 * hdd_select_cbmode() - select channel bonding mode
12700 * @pAdapter: Pointer to adapter
12701 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012702 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012703 *
12704 * Return: none
12705 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012706void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12707 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012708{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012709 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012710 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012711 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012712
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012713 /*
12714 * CDS api expects secondary channel for calculating
12715 * the channel params
12716 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012717 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012718 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12719 if (operationChannel >= 1 && operationChannel <= 5)
12720 sec_ch = operationChannel + 4;
12721 else if (operationChannel >= 6 && operationChannel <= 13)
12722 sec_ch = operationChannel - 4;
12723 }
12724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012725 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012726 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012727
12728 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012729 eHddDot11Mode hdd_dot11_mode;
12730 uint8_t iniDot11Mode =
12731 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12732
12733 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12734 switch (iniDot11Mode) {
12735 case eHDD_DOT11_MODE_AUTO:
12736 case eHDD_DOT11_MODE_11ac:
12737 case eHDD_DOT11_MODE_11ac_ONLY:
12738 if (sme_is_feature_supported_by_fw(DOT11AC))
12739 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12740 else
12741 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12742 break;
12743 case eHDD_DOT11_MODE_11n:
12744 case eHDD_DOT11_MODE_11n_ONLY:
12745 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12746 break;
12747 default:
12748 hdd_dot11_mode = iniDot11Mode;
12749 break;
12750 }
12751 ch_info->channel_width = ch_params->ch_width;
12752 ch_info->phy_mode =
12753 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012754 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012755 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012756 hdd_info("ch_info width %d, phymode %d channel %d",
12757 ch_info->channel_width, ch_info->phy_mode,
12758 ch_info->channel);
12759 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760}
12761
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012762/**
12763 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12764 * @adapter: STA adapter
12765 * @roam_profile: STA roam profile
12766 *
12767 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12768 *
12769 * Return: false if sta-sap conc is not allowed, else return true
12770 */
12771static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12772 tCsrRoamProfile *roam_profile)
12773{
12774 hdd_context_t *hdd_ctx;
12775 hdd_adapter_t *ap_adapter;
12776 hdd_ap_ctx_t *hdd_ap_ctx;
12777 hdd_hostapd_state_t *hostapd_state;
12778 uint8_t channel = 0;
12779 QDF_STATUS status;
12780
12781 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12782 if (!hdd_ctx) {
12783 hdd_err("HDD context is NULL");
12784 return true;
12785 }
12786
12787 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12788 /* probably no sap running, no handling required */
12789 if (ap_adapter == NULL)
12790 return true;
12791
12792 /*
12793 * sap is not in started state, so it is fine to go ahead with sta.
12794 * if sap is currently doing CAC then don't allow sta to go further.
12795 */
12796 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12797 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12798 return true;
12799
12800 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12801 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12802 return false;
12803 }
12804
12805 /*
12806 * log and return error, if we allow STA to go through, we don't
12807 * know what is going to happen better stop sta connection
12808 */
12809 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12810 if (NULL == hdd_ap_ctx) {
12811 hdd_err("AP context not found");
12812 return false;
12813 }
12814
12815 /* sap is on non-dfs channel, nothing to handle */
12816 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12817 hdd_info("sap is on non-dfs channel, sta is allowed");
12818 return true;
12819 }
12820 /*
12821 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012822 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012823 */
12824 status = cds_get_channel_from_scan_result(adapter,
12825 roam_profile, &channel);
12826
Nitesh Shah59774522016-09-16 15:14:21 +053012827 /*
12828 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12829 * channels for roaming case.
12830 */
12831 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12832 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12833 return true;
12834 }
12835
12836 /*
12837 * If channel is 0 or DFS then better to call pcl and find out the
12838 * best channel. If channel is non-dfs 5 GHz then better move SAP
12839 * to STA's channel to make scc, so we have room for 3port MCC
12840 * scenario.
12841 */
12842 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012843 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12844 true);
12845
12846 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12847 qdf_event_reset(&hostapd_state->qdf_event);
12848 status = wlansap_set_channel_change_with_csa(
12849 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12850 hdd_ap_ctx->sapConfig.ch_width_orig);
12851
12852 if (QDF_STATUS_SUCCESS != status) {
12853 hdd_err("Set channel with CSA IE failed, can't allow STA");
12854 return false;
12855 }
12856
12857 /*
12858 * wait here for SAP to finish the channel switch. When channel
12859 * switch happens, SAP sends few beacons with CSA_IE. After
12860 * successfully Transmission of those beacons, it will move its
12861 * state from started to disconnected and move to new channel.
12862 * once it moves to new channel, sap again moves its state
12863 * machine from disconnected to started and set this event.
12864 * wait for 10 secs to finish this.
12865 */
12866 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12867 if (!QDF_IS_STATUS_SUCCESS(status)) {
12868 hdd_err("wait for qdf_event failed, STA not allowed!!");
12869 return false;
12870 }
12871
12872 return true;
12873}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012874
Abhishek Singhcfb44482017-03-10 12:42:37 +053012875#ifdef WLAN_FEATURE_11W
12876/**
12877 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12878 * @roam_profile: pointer to roam profile
12879 *
12880 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12881 * or pmf=2 is an explicit configuration in the supplicant
12882 * configuration, drop the connection request.
12883 *
12884 * Return: 0 if check result is valid, otherwise return error code
12885 */
12886static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12887{
12888 if (roam_profile->MFPEnabled &&
12889 !(roam_profile->MFPRequired ||
12890 roam_profile->MFPCapable)) {
12891 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12892 roam_profile->MFPEnabled,
12893 roam_profile->MFPRequired,
12894 roam_profile->MFPCapable);
12895 return -EINVAL;
12896 }
12897 return 0;
12898}
12899#else
12900static inline
12901int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12902{
12903 return 0;
12904}
12905#endif
12906
Krunal Soni31949422016-07-29 17:17:53 -070012907/**
12908 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012909 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012910 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 * @ssid_len: Length of ssid
12912 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012913 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012914 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012915 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916 *
12917 * This function is used to start the association process
12918 *
12919 * Return: 0 for success, non-zero for failure
12920 */
Krunal Soni31949422016-07-29 17:17:53 -070012921static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012922 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012923 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012924 u8 operatingChannel,
12925 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012926{
12927 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012928 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012929 hdd_wext_state_t *pWextState;
12930 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012931 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012932 uint32_t roamId;
12933 tCsrRoamProfile *pRoamProfile;
12934 eCsrAuthType RSNAuthType;
12935 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012936 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012937
12938 ENTER();
12939
12940 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12941 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012942 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012943
12944 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012945 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012946 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012947
12948 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012949 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012950 status = -EINVAL;
12951 goto ret_status;
12952 }
12953
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +053012954 if (true == cds_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012955 hdd_err("Connection refused: conn in progress");
12956 status = -EINVAL;
12957 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 }
12959
12960 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012961 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12962 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012963
12964 if (pRoamProfile) {
12965 hdd_station_ctx_t *pHddStaCtx;
12966 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12967
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012968 /* Restart the opportunistic timer
12969 *
12970 * If hw_mode_change_in_progress is true, then wait
12971 * till firmware sends the callback for hw_mode change.
12972 *
12973 * Else set connect_in_progress as true and proceed.
12974 */
12975 cds_restart_opportunistic_timer(false);
12976 if (cds_is_hw_mode_change_in_progress()) {
12977 status = qdf_wait_for_connection_update();
12978 if (!QDF_IS_STATUS_SUCCESS(status)) {
12979 hdd_err("qdf wait for event failed!!");
12980 status = -EINVAL;
12981 goto ret_status;
12982 }
12983 }
12984 cds_set_connection_in_progress(true);
12985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012986 if (HDD_WMM_USER_MODE_NO_QOS ==
12987 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12988 /*QoS not enabled in cfg file */
12989 pRoamProfile->uapsd_mask = 0;
12990 } else {
12991 /*QoS enabled, update uapsd mask from cfg file */
12992 pRoamProfile->uapsd_mask =
12993 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12994 }
12995
12996 pRoamProfile->SSIDs.numOfSSIDs = 1;
12997 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012998 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012999 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013000 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001 ssid, ssid_len);
13002
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013003 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013004 /* cleanup bssid hint */
13005 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13006 QDF_MAC_ADDR_SIZE);
13007 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13008 QDF_MAC_ADDR_SIZE);
13009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010 if (bssid) {
13011 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013012 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013013 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013014 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013015 /*
13016 * Save BSSID in seperate variable as
13017 * pRoamProfile's BSSID is getting zeroed out in the
13018 * association process. In case of join failure
13019 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013020 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013021 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013022 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013023 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013025 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13026 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013027 /*
13028 * Save BSSID in a separate variable as
13029 * pRoamProfile's BSSID is getting zeroed out in the
13030 * association process. In case of join failure
13031 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013032 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013033 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013034 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013035 hdd_info("bssid_hint is given by upper layer %pM",
13036 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013037 }
13038
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013039 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 pRoamProfile->SSIDs.SSIDList->SSID.length,
13041 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13042 operatingChannel);
13043
13044 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13045 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013046 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013047 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13048 }
13049#ifdef FEATURE_WLAN_WAPI
13050 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013051 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 switch (pAdapter->wapi_info.wapiAuthMode) {
13053 case WAPI_AUTH_MODE_PSK:
13054 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013055 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056 pAdapter->wapi_info.wapiAuthMode);
13057 pRoamProfile->AuthType.authType[0] =
13058 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13059 break;
13060 }
13061 case WAPI_AUTH_MODE_CERT:
13062 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013063 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013064 pAdapter->wapi_info.wapiAuthMode);
13065 pRoamProfile->AuthType.authType[0] =
13066 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13067 break;
13068 }
13069 } /* End of switch */
13070 if (pAdapter->wapi_info.wapiAuthMode ==
13071 WAPI_AUTH_MODE_PSK
13072 || pAdapter->wapi_info.wapiAuthMode ==
13073 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013074 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 pRoamProfile->AuthType.numEntries = 1;
13076 pRoamProfile->EncryptionType.numEntries = 1;
13077 pRoamProfile->EncryptionType.encryptionType[0] =
13078 eCSR_ENCRYPT_TYPE_WPI;
13079 pRoamProfile->mcEncryptionType.numEntries = 1;
13080 pRoamProfile->mcEncryptionType.
13081 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13082 }
13083 }
Krunal Soni31949422016-07-29 17:17:53 -070013084#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013085 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 pRoamProfile->csrPersona = pAdapter->device_mode;
13087
13088 if (operatingChannel) {
13089 pRoamProfile->ChannelInfo.ChannelList =
13090 &operatingChannel;
13091 pRoamProfile->ChannelInfo.numOfChannels = 1;
13092 } else {
13093 pRoamProfile->ChannelInfo.ChannelList = NULL;
13094 pRoamProfile->ChannelInfo.numOfChannels = 0;
13095 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013096 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013097 && operatingChannel) {
13098 /*
13099 * Need to post the IBSS power save parameters
13100 * to WMA. WMA will configure this parameters
13101 * to firmware if power save is enabled by the
13102 * firmware.
13103 */
13104 status = hdd_set_ibss_power_save_params(pAdapter);
13105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013106 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013107 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013108 status = -EINVAL;
13109 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013110 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013111 pRoamProfile->ch_params.ch_width =
13112 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013113 /*
13114 * In IBSS mode while operating in 2.4 GHz,
13115 * the device supports only 20 MHz.
13116 */
13117 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13118 pRoamProfile->ch_params.ch_width =
13119 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013120 hdd_select_cbmode(pAdapter, operatingChannel,
13121 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 }
13123
Abhishek Singhcfb44482017-03-10 12:42:37 +053013124 if (wlan_hdd_cfg80211_check_pmf_valid(
13125 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013126 status = -EINVAL;
13127 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013128 }
13129
Krunal Soni31949422016-07-29 17:17:53 -070013130 /*
13131 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013132 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013133 * enhancements, the supplicant is not issuing the scan command
13134 * now. So the unicast frames which are sent from the host are
13135 * not having the additional IEs. If it is P2P CLIENT and there
13136 * is no additional IE present in roamProfile, then use the
13137 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138 */
13139
Krunal Sonib4326f22016-03-10 13:05:51 -080013140 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013141 (!pRoamProfile->pAddIEScan)) {
13142 pRoamProfile->pAddIEScan =
13143 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13144 pRoamProfile->nAddIEScanLength =
13145 pAdapter->scan_info.scanAddIE.length;
13146 }
13147 /*
13148 * When policy manager is enabled from ini file, we shouldn't
13149 * check for other concurrency rules.
13150 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013151 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013152 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013153 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013154 pAdapter, pRoamProfile, &roamId)) {
13155 status = 0;
13156 goto conn_failure;
13157 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013158 }
13159
Krunal Soni3091bcc2016-06-23 12:28:21 -070013160 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013161 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13162 pRoamProfile))) {
13163 hdd_err("sap-sta conc will fail, can't allow sta");
13164 hdd_conn_set_connection_state(pAdapter,
13165 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013166 status = -ENOMEM;
13167 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013168 }
13169
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013170 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171 if (!sme_config) {
13172 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013173 hdd_conn_set_connection_state(pAdapter,
13174 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013175 status = -ENOMEM;
13176 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013178 sme_get_config_param(pHddCtx->hHal, sme_config);
13179 /* These values are not sessionized. So, any change in these SME
13180 * configs on an older or parallel interface will affect the
13181 * cb mode. So, restoring the default INI params before starting
13182 * interfaces such as sta, cli etc.,
13183 */
13184 sme_config->csrConfig.channelBondingMode5GHz =
13185 pHddCtx->config->nChannelBondingMode5GHz;
13186 sme_config->csrConfig.channelBondingMode24GHz =
13187 pHddCtx->config->nChannelBondingMode24GHz;
13188 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013189 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013190 /*
13191 * Change conn_state to connecting before sme_roam_connect(),
13192 * because sme_roam_connect() has a direct path to call
13193 * hdd_sme_roam_callback(), which will change the conn_state
13194 * If direct path, conn_state will be accordingly changed to
13195 * NotConnected or Associated by either
13196 * hdd_association_completion_handler() or
13197 * hdd_dis_connect_handler() in sme_RoamCallback()if
13198 * sme_RomConnect is to be queued,
13199 * Connecting state will remain until it is completed.
13200 *
13201 * If connection state is not changed, connection state will
13202 * remain in eConnectionState_NotConnected state.
13203 * In hdd_association_completion_handler, "hddDisconInProgress"
13204 * is set to true if conn state is
13205 * eConnectionState_NotConnected.
13206 * If "hddDisconInProgress" is set to true then cfg80211 layer
13207 * is not informed of connect result indication which
13208 * is an issue.
13209 */
13210 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013211 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013212 hdd_conn_set_connection_state(pAdapter,
13213 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013214
Komal Seelama89be8d2016-09-29 11:09:26 +053013215 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13216 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013217 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013218 pAdapter->sessionId, pRoamProfile,
13219 &roamId);
13220
Rajeev Kumard31e1542017-01-13 14:37:42 -080013221 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013222 (QDF_STA_MODE == pAdapter->device_mode ||
13223 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013224 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013225 "qdf_status %d. -> NotConnected",
13226 pAdapter->sessionId, qdf_status);
13227 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013228 /* change back to NotAssociated */
13229 hdd_conn_set_connection_state(pAdapter,
13230 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013231 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13232 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 }
13234
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013235 /* Reset connect_in_progress */
13236 cds_set_connection_in_progress(false);
13237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 pRoamProfile->ChannelInfo.ChannelList = NULL;
13239 pRoamProfile->ChannelInfo.numOfChannels = 0;
13240
Nitesh Shah044fd672016-10-13 18:53:25 +053013241 if ((QDF_STA_MODE == pAdapter->device_mode)
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013242 && wma_is_current_hwmode_dbs() &&
13243 !wma_is_hw_dbs_2x2_capable()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013244 cds_get_channel_from_scan_result(pAdapter,
13245 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013246 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013247 if (channel)
13248 cds_checkn_update_hw_mode_single_mac_mode
13249 (channel);
13250 }
13251
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013252 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013253 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013254 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013255 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013256 goto ret_status;
13257
13258conn_failure:
13259 /* Reset connect_in_progress */
13260 cds_set_connection_in_progress(false);
13261
13262ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263 EXIT();
13264 return status;
13265}
13266
13267/**
13268 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13269 * @pAdapter: Pointer to adapter
13270 * @auth_type: Auth type
13271 *
13272 * This function is used to set the authentication type (OPEN/SHARED).
13273 *
13274 * Return: 0 for success, non-zero for failure
13275 */
13276static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13277 enum nl80211_auth_type auth_type)
13278{
13279 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13280 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 /*set authentication type */
13283 switch (auth_type) {
13284 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013285 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13287 break;
13288
13289 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013291 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13293 break;
13294
13295 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013296 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013297 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13298 break;
13299#ifdef FEATURE_WLAN_ESE
13300 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013301 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013302 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13303 break;
13304#endif
13305
13306 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013307 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013308 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13309 return -EINVAL;
13310 }
13311
13312 pWextState->roamProfile.AuthType.authType[0] =
13313 pHddStaCtx->conn_info.authType;
13314 return 0;
13315}
13316
13317/**
13318 * wlan_hdd_set_akm_suite() - set key management type
13319 * @pAdapter: Pointer to adapter
13320 * @key_mgmt: Key management type
13321 *
13322 * This function is used to set the key mgmt type(PSK/8021x).
13323 *
13324 * Return: 0 for success, non-zero for failure
13325 */
13326static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13327{
13328 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013330#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13331#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13332 /*set key mgmt type */
13333 switch (key_mgmt) {
13334 case WLAN_AKM_SUITE_PSK:
13335 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013336 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013337 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13339 break;
13340
13341 case WLAN_AKM_SUITE_8021X_SHA256:
13342 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013343 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013344 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13346 break;
13347#ifdef FEATURE_WLAN_ESE
13348#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13349#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13350 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013351 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013352 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13353 break;
13354#endif
13355#ifndef WLAN_AKM_SUITE_OSEN
13356#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13357#endif
13358 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013359 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013360 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13361 break;
13362
13363 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013364 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 return -EINVAL;
13366
13367 }
13368 return 0;
13369}
13370
13371/**
13372 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13373 * @pAdapter: Pointer to adapter
13374 * @cipher: Cipher type
13375 * @ucast: Unicast flag
13376 *
13377 * This function is used to set the encryption type
13378 * (NONE/WEP40/WEP104/TKIP/CCMP).
13379 *
13380 * Return: 0 for success, non-zero for failure
13381 */
13382static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13383 u32 cipher, bool ucast)
13384{
13385 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13386 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13387 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13388
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013389 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013390 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13392 } else {
13393
13394 /*set encryption method */
13395 switch (cipher) {
13396 case IW_AUTH_CIPHER_NONE:
13397 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13398 break;
13399
13400 case WLAN_CIPHER_SUITE_WEP40:
13401 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13402 break;
13403
13404 case WLAN_CIPHER_SUITE_WEP104:
13405 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13406 break;
13407
13408 case WLAN_CIPHER_SUITE_TKIP:
13409 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13410 break;
13411
13412 case WLAN_CIPHER_SUITE_CCMP:
13413 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13414 break;
13415#ifdef FEATURE_WLAN_WAPI
13416 case WLAN_CIPHER_SUITE_SMS4:
13417 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13418 break;
13419#endif
13420
13421#ifdef FEATURE_WLAN_ESE
13422 case WLAN_CIPHER_SUITE_KRK:
13423 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13424 break;
13425#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13426 case WLAN_CIPHER_SUITE_BTK:
13427 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13428 break;
13429#endif
13430#endif
13431 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013432 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013433 return -EOPNOTSUPP;
13434 }
13435 }
13436
13437 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013438 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013439 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13440 pWextState->roamProfile.EncryptionType.numEntries = 1;
13441 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13442 encryptionType;
13443 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013444 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13446 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13447 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13448 encryptionType;
13449 }
13450
13451 return 0;
13452}
13453
13454/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013455 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13456 * @wext_state: Pointer to wext state
13457 * @gen_ie: Pointer to IE data
13458 * @len: length of IE data
13459 *
13460 * Return: 0 for success, non-zero for failure
13461 */
13462static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13463 const uint8_t *gen_ie, uint16_t len)
13464{
13465 uint16_t cur_add_ie_len =
13466 wext_state->assocAddIE.length;
13467
13468 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13469 (wext_state->assocAddIE.length + len)) {
13470 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13471 QDF_ASSERT(0);
13472 return -ENOMEM;
13473 }
13474 memcpy(wext_state->assocAddIE.addIEdata +
13475 cur_add_ie_len, gen_ie, len);
13476 wext_state->assocAddIE.length += len;
13477
13478 wext_state->roamProfile.pAddIEAssoc =
13479 wext_state->assocAddIE.addIEdata;
13480 wext_state->roamProfile.nAddIEAssocLength =
13481 wext_state->assocAddIE.length;
13482 return 0;
13483}
13484
13485/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013486 * wlan_hdd_cfg80211_set_ie() - set IEs
13487 * @pAdapter: Pointer to adapter
13488 * @ie: Pointer ot ie
13489 * @ie: IE length
13490 *
13491 * Return: 0 for success, non-zero for failure
13492 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013493static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013494 size_t ie_len)
13495{
13496 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13497 const uint8_t *genie = ie;
13498 uint16_t remLen = ie_len;
13499#ifdef FEATURE_WLAN_WAPI
13500 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13501 u16 *tmp;
13502 uint16_t akmsuiteCount;
13503 int *akmlist;
13504#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013505 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013506
13507 /* clear previous assocAddIE */
13508 pWextState->assocAddIE.length = 0;
13509 pWextState->roamProfile.bWPSAssociation = false;
13510 pWextState->roamProfile.bOSENAssociation = false;
13511
13512 while (remLen >= 2) {
13513 uint16_t eLen = 0;
13514 uint8_t elementId;
13515 elementId = *genie++;
13516 eLen = *genie++;
13517 remLen -= 2;
13518
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013519 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520
13521 switch (elementId) {
13522 case DOT11F_EID_WPA:
13523 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 -070013524 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013525 return -EINVAL;
13526 } else if (0 ==
13527 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13528 uint16_t curAddIELen =
13529 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013530 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013531
13532 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13533 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013534 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013535 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013536 return -ENOMEM;
13537 }
13538 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13539 memcpy(pWextState->assocAddIE.addIEdata +
13540 curAddIELen, genie - 2, eLen + 2);
13541 pWextState->assocAddIE.length += eLen + 2;
13542
13543 pWextState->roamProfile.bWPSAssociation = true;
13544 pWextState->roamProfile.pAddIEAssoc =
13545 pWextState->assocAddIE.addIEdata;
13546 pWextState->roamProfile.nAddIEAssocLength =
13547 pWextState->assocAddIE.length;
13548 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013549 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013550 memset(pWextState->WPARSNIE, 0,
13551 MAX_WPA_RSN_IE_LEN);
13552 memcpy(pWextState->WPARSNIE, genie - 2,
13553 (eLen + 2));
13554 pWextState->roamProfile.pWPAReqIE =
13555 pWextState->WPARSNIE;
13556 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13557 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13558 P2P_OUI_TYPE_SIZE))) {
13559 uint16_t curAddIELen =
13560 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013561 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013562
13563 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13564 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013565 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013566 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013567 return -ENOMEM;
13568 }
13569 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13570 memcpy(pWextState->assocAddIE.addIEdata +
13571 curAddIELen, genie - 2, eLen + 2);
13572 pWextState->assocAddIE.length += eLen + 2;
13573
13574 pWextState->roamProfile.pAddIEAssoc =
13575 pWextState->assocAddIE.addIEdata;
13576 pWextState->roamProfile.nAddIEAssocLength =
13577 pWextState->assocAddIE.length;
13578 }
13579#ifdef WLAN_FEATURE_WFD
13580 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13581 WFD_OUI_TYPE_SIZE)) &&
13582 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013583 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013584 pAdapter->device_mode)) {
13585 uint16_t curAddIELen =
13586 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013587 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588
13589 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13590 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013591 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013592 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013593 return -ENOMEM;
13594 }
13595 /* WFD IE is saved to Additional IE ; it should
13596 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013597 * WFD IE
13598 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013599 memcpy(pWextState->assocAddIE.addIEdata +
13600 curAddIELen, genie - 2, eLen + 2);
13601 pWextState->assocAddIE.length += eLen + 2;
13602
13603 pWextState->roamProfile.pAddIEAssoc =
13604 pWextState->assocAddIE.addIEdata;
13605 pWextState->roamProfile.nAddIEAssocLength =
13606 pWextState->assocAddIE.length;
13607 }
13608#endif
13609 /* Appending HS 2.0 Indication Element in Assiciation Request */
13610 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13611 HS20_OUI_TYPE_SIZE))) {
13612 uint16_t curAddIELen =
13613 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013614 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013615
13616 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13617 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013618 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013619 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013620 return -ENOMEM;
13621 }
13622 memcpy(pWextState->assocAddIE.addIEdata +
13623 curAddIELen, genie - 2, eLen + 2);
13624 pWextState->assocAddIE.length += eLen + 2;
13625
13626 pWextState->roamProfile.pAddIEAssoc =
13627 pWextState->assocAddIE.addIEdata;
13628 pWextState->roamProfile.nAddIEAssocLength =
13629 pWextState->assocAddIE.length;
13630 }
13631 /* Appending OSEN Information Element in Assiciation Request */
13632 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13633 OSEN_OUI_TYPE_SIZE))) {
13634 uint16_t curAddIELen =
13635 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013636 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637
13638 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13639 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013640 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013641 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013642 return -ENOMEM;
13643 }
13644 memcpy(pWextState->assocAddIE.addIEdata +
13645 curAddIELen, genie - 2, eLen + 2);
13646 pWextState->assocAddIE.length += eLen + 2;
13647
13648 pWextState->roamProfile.bOSENAssociation = true;
13649 pWextState->roamProfile.pAddIEAssoc =
13650 pWextState->assocAddIE.addIEdata;
13651 pWextState->roamProfile.nAddIEAssocLength =
13652 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013653 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13654 MBO_OUI_TYPE_SIZE))){
13655 hdd_info("Set MBO IE(len %d)", eLen + 2);
13656 status = wlan_hdd_add_assoc_ie(pWextState,
13657 genie - 2, eLen + 2);
13658 if (status)
13659 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 } else {
13661 uint16_t add_ie_len =
13662 pWextState->assocAddIE.length;
13663
13664 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13665
13666 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13667 (pWextState->assocAddIE.length + eLen)) {
13668 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013669 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670 return -ENOMEM;
13671 }
13672
13673 memcpy(pWextState->assocAddIE.addIEdata +
13674 add_ie_len, genie - 2, eLen + 2);
13675 pWextState->assocAddIE.length += eLen + 2;
13676
13677 pWextState->roamProfile.pAddIEAssoc =
13678 pWextState->assocAddIE.addIEdata;
13679 pWextState->roamProfile.nAddIEAssocLength =
13680 pWextState->assocAddIE.length;
13681 }
13682 break;
13683 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013684 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013685 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13686 memcpy(pWextState->WPARSNIE, genie - 2,
13687 (eLen + 2));
13688 pWextState->roamProfile.pRSNReqIE =
13689 pWextState->WPARSNIE;
13690 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13691 break;
13692 /*
13693 * Appending Extended Capabilities with Interworking bit set
13694 * in Assoc Req.
13695 *
13696 * In assoc req this EXT Cap will only be taken into account if
13697 * interworkingService bit is set to 1. Currently
13698 * driver is only interested in interworkingService capability
13699 * from supplicant. If in future any other EXT Cap info is
13700 * required from supplicat, it needs to be handled while
13701 * sending Assoc Req in LIM.
13702 */
13703 case DOT11F_EID_EXTCAP:
13704 {
13705 uint16_t curAddIELen =
13706 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013707 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013708
13709 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13710 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013711 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013712 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 return -ENOMEM;
13714 }
13715 memcpy(pWextState->assocAddIE.addIEdata +
13716 curAddIELen, genie - 2, eLen + 2);
13717 pWextState->assocAddIE.length += eLen + 2;
13718
13719 pWextState->roamProfile.pAddIEAssoc =
13720 pWextState->assocAddIE.addIEdata;
13721 pWextState->roamProfile.nAddIEAssocLength =
13722 pWextState->assocAddIE.length;
13723 break;
13724 }
13725#ifdef FEATURE_WLAN_WAPI
13726 case WLAN_EID_WAPI:
13727 /* Setting WAPI Mode to ON=1 */
13728 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013729 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013730 tmp = (u16 *) ie;
13731 tmp = tmp + 2; /* Skip element Id and Len, Version */
13732 akmsuiteCount = WPA_GET_LE16(tmp);
13733 tmp = tmp + 1;
13734 akmlist = (int *)(tmp);
13735 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13736 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13737 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013738 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013739 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013740 return -EINVAL;
13741 }
13742
13743 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013744 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013745 pAdapter->wapi_info.wapiAuthMode =
13746 WAPI_AUTH_MODE_PSK;
13747 }
13748 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013749 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 pAdapter->wapi_info.wapiAuthMode =
13751 WAPI_AUTH_MODE_CERT;
13752 }
13753 break;
13754#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013755 case DOT11F_EID_SUPPOPERATINGCLASSES:
13756 {
13757 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13758 status = wlan_hdd_add_assoc_ie(pWextState,
13759 genie - 2, eLen + 2);
13760 if (status)
13761 return status;
13762 break;
13763 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013764 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013765 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013766 /* when Unknown IE is received we break
13767 * and continue to the next IE in the buffer
13768 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 break;
13770 }
13771 genie += eLen;
13772 remLen -= eLen;
13773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013774 return 0;
13775}
13776
13777/**
13778 * hdd_is_wpaie_present() - check for WPA ie
13779 * @ie: Pointer to ie
13780 * @ie_len: Ie length
13781 *
13782 * Parse the received IE to find the WPA IE
13783 *
13784 * Return: true if wpa ie is found else false
13785 */
13786static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13787{
13788 uint8_t eLen = 0;
13789 uint16_t remLen = ie_len;
13790 uint8_t elementId = 0;
13791
13792 while (remLen >= 2) {
13793 elementId = *ie++;
13794 eLen = *ie++;
13795 remLen -= 2;
13796 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013797 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013798 return false;
13799 }
13800 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13801 /* OUI - 0x00 0X50 0XF2
13802 * WPA Information Element - 0x01
13803 * WPA version - 0x01
13804 */
13805 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13806 return true;
13807 }
13808 ie += eLen;
13809 remLen -= eLen;
13810 }
13811 return false;
13812}
13813
13814/**
13815 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13816 * @pAdapter: Pointer to adapter
13817 * @req: Pointer to security parameters
13818 *
13819 * Return: 0 for success, non-zero for failure
13820 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013821static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13822 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013823{
13824 int status = 0;
13825 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13826 ENTER();
13827
13828 /*set wpa version */
13829 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13830
13831 if (req->crypto.wpa_versions) {
13832 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13833 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13834 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13835 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13836 }
13837 }
13838
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013839 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840
13841 /*set authentication type */
13842 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13843
13844 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013845 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 return status;
13847 }
13848
13849 /*set key mgmt type */
13850 if (req->crypto.n_akm_suites) {
13851 status =
13852 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13853 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013854 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 return status;
13856 }
13857 }
13858
13859 /*set pairwise cipher type */
13860 if (req->crypto.n_ciphers_pairwise) {
13861 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13862 req->crypto.
13863 ciphers_pairwise[0],
13864 true);
13865 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013866 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867 return status;
13868 }
13869 } else {
13870 /*Reset previous cipher suite to none */
13871 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13872 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013873 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013874 return status;
13875 }
13876 }
13877
13878 /*set group cipher type */
13879 status =
13880 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13881 false);
13882
13883 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013884 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 return status;
13886 }
13887#ifdef WLAN_FEATURE_11W
13888 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13889#endif
13890
13891 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13892 if (req->ie_len) {
13893 status =
13894 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13895 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013896 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013897 return status;
13898 }
13899 }
13900
13901 /*incase of WEP set default key information */
13902 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013903 u8 key_len = req->key_len;
13904 u8 key_idx = req->key_idx;
13905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013906 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13907 || (WLAN_CIPHER_SUITE_WEP104 ==
13908 req->crypto.ciphers_pairwise[0])
13909 ) {
13910 if (IW_AUTH_KEY_MGMT_802_1X
13911 ==
13912 (pWextState->
13913 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013914 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013915 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013916 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917
Jeff Johnson68755312017-02-10 11:46:55 -080013918 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13919 && (CSR_MAX_NUM_KEY > key_idx)) {
13920 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13921 key_idx, key_len);
13922 qdf_mem_copy(&pWextState->roamProfile.
13923 Keys.
13924 KeyMaterial[key_idx][0],
13925 req->key, key_len);
13926 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013928 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013929 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013930 }
13931 }
13932 }
13933
13934 return status;
13935}
13936
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013937int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013938{
13939 unsigned long rc;
13940 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013941 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013942 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013943
13944 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013945 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13946 if (pAdapter->device_mode == QDF_STA_MODE) {
13947 hdd_notice("Stop firmware roaming");
13948 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
13949 }
13950 /*
13951 * If firmware has already started roaming process, driver
13952 * needs to defer the processing of this disconnect request.
13953 *
13954 */
13955 if (hdd_is_roaming_in_progress(pAdapter)) {
13956 /*
13957 * Defer the disconnect action until firmware roaming
13958 * result is received. If STA is in connected state after
13959 * that, send the disconnect command to CSR, otherwise
13960 * CSR would have already sent disconnect event to upper
13961 * layer.
13962 */
13963
13964 hdd_err("Roaming in progress, <try disconnect> deferred.");
13965 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
13966 pAdapter->cfg80211_disconnect_reason =
13967 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13968 return 0;
13969 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013970
Jeff Johnson9edf9572016-10-03 15:24:49 -070013971 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013972 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13973 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13974 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 hdd_conn_set_connection_state(pAdapter,
13976 eConnectionState_Disconnecting);
13977 /* Issue disconnect to CSR */
13978 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013979
13980 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13981 pAdapter->sessionId,
13982 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13983 /*
13984 * Wait here instead of returning directly, this will block the
13985 * next connect command and allow processing of the scan for
13986 * ssid and the previous connect command in CSR. Else we might
13987 * hit some race conditions leading to SME and HDD out of sync.
13988 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013989 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013990 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13991 } else if (0 != status) {
13992 hdd_err("csrRoamDisconnect failure, returned %d",
13993 (int)status);
13994 pHddStaCtx->staDebugState = status;
13995 result = -EINVAL;
13996 goto disconnected;
13997 }
13998
13999 rc = wait_for_completion_timeout(
14000 &pAdapter->disconnect_comp_var,
14001 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014002 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014003 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
14004 pAdapter->sessionId, pHddStaCtx->staDebugState);
14005 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014006 }
14007 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014008 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014010 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014012 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014014 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014015 }
14016 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014017disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014018 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14019 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020}
14021
14022/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014023 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14024 * @adapter: Pointer to the HDD adapter
14025 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014026 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014027 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014028 * This function will start reassociation if prev_bssid is set and bssid/
14029 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014030 *
Naveen Rawat07332902016-07-27 09:13:17 -070014031 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014032 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014033#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14034 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014035static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14036 struct cfg80211_connect_params *req,
14037 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014038{
Naveen Rawat07332902016-07-27 09:13:17 -070014039 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014040 const uint8_t *bssid = NULL;
14041 uint16_t channel = 0;
14042
14043 if (req->bssid)
14044 bssid = req->bssid;
14045 else if (req->bssid_hint)
14046 bssid = req->bssid_hint;
14047
14048 if (req->channel)
14049 channel = req->channel->hw_value;
14050 else if (req->channel_hint)
14051 channel = req->channel_hint->hw_value;
14052
14053 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014054 reassoc = true;
14055 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014056 channel, MAC_ADDR_ARRAY(bssid));
14057 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014058 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014059 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014060 }
Naveen Rawat07332902016-07-27 09:13:17 -070014061 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014062}
14063#else
Naveen Rawat07332902016-07-27 09:13:17 -070014064static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14065 struct cfg80211_connect_params *req,
14066 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014067{
Naveen Rawat07332902016-07-27 09:13:17 -070014068 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014069}
14070#endif
14071
14072/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14074 * @wiphy: Pointer to wiphy
14075 * @dev: Pointer to network device
14076 * @req: Pointer to cfg80211 connect request
14077 *
14078 * This function is used to start the association process
14079 *
14080 * Return: 0 for success, non-zero for failure
14081 */
14082static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14083 struct net_device *ndev,
14084 struct cfg80211_connect_params *req)
14085{
14086 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014087 u16 channel;
14088#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14089 const u8 *bssid_hint = req->bssid_hint;
14090#else
14091 const u8 *bssid_hint = NULL;
14092#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14094 hdd_context_t *pHddCtx;
14095
14096 ENTER();
14097
Anurag Chouhan6d760662016-02-20 16:05:43 +053014098 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014099 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014100 return -EINVAL;
14101 }
14102
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014103 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14104 hdd_err("invalid session id: %d", pAdapter->sessionId);
14105 return -EINVAL;
14106 }
14107
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014108 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014109 TRACE_CODE_HDD_CFG80211_CONNECT,
14110 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014111 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014112 hdd_device_mode_to_string(pAdapter->device_mode),
14113 pAdapter->device_mode);
14114
Krunal Sonib4326f22016-03-10 13:05:51 -080014115 if (pAdapter->device_mode != QDF_STA_MODE &&
14116 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014117 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014118 hdd_device_mode_to_string(pAdapter->device_mode),
14119 pAdapter->device_mode);
14120 return -EINVAL;
14121 }
14122
14123 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14124 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014125 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014126 return -EINVAL;
14127 }
14128
14129 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014130 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014131 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014132
Naveen Rawat07332902016-07-27 09:13:17 -070014133 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014134 return status;
14135
Agrawal Ashishf156e942016-08-04 14:54:47 +053014136 /* Try disconnecting if already in connected state */
14137 status = wlan_hdd_try_disconnect(pAdapter);
14138 if (0 > status) {
14139 hdd_err("Failed to disconnect the existing connection");
14140 return -EALREADY;
14141 }
14142
14143 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014144 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014145 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014146 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014147 pAdapter->device_mode),
14148 req->channel->hw_value, HW_MODE_20_MHZ)) {
14149 hdd_err("This concurrency combination is not allowed");
14150 return -ECONNREFUSED;
14151 }
14152 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014153 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014154 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14156 hdd_err("This concurrency combination is not allowed");
14157 return -ECONNREFUSED;
14158 }
14159 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 /*initialise security parameters */
14162 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14163
14164 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014165 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014166 return status;
14167 }
14168
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014169 if (req->channel)
14170 channel = req->channel->hw_value;
14171 else
14172 channel = 0;
14173 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14174 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014175 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014176 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014177 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014178 return status;
14179 }
14180 EXIT();
14181 return status;
14182}
14183
14184/**
14185 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14186 * @wiphy: Pointer to wiphy
14187 * @dev: Pointer to network device
14188 * @req: Pointer to cfg80211 connect request
14189 *
14190 * Return: 0 for success, non-zero for failure
14191 */
14192static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14193 struct net_device *ndev,
14194 struct cfg80211_connect_params *req)
14195{
14196 int ret;
14197 cds_ssr_protect(__func__);
14198 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14199 cds_ssr_unprotect(__func__);
14200
14201 return ret;
14202}
14203
14204/**
14205 * wlan_hdd_disconnect() - hdd disconnect api
14206 * @pAdapter: Pointer to adapter
14207 * @reason: Disconnect reason code
14208 *
14209 * This function is used to issue a disconnect request to SME
14210 *
14211 * Return: 0 for success, non-zero for failure
14212 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014213static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014214{
14215 int status, result = 0;
14216 unsigned long rc;
14217 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14218 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014219 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014220 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014221
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014222 ENTER();
14223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014224 status = wlan_hdd_validate_context(pHddCtx);
14225
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014226 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014228 if (pAdapter->device_mode == QDF_STA_MODE) {
14229 hdd_notice("Stop firmware roaming");
14230 status = sme_stop_roaming(hal, pAdapter->sessionId,
14231 eCsrHddIssued);
14232 }
14233 /*
14234 * If firmware has already started roaming process, driver
14235 * needs to defer the processing of this disconnect request.
14236 */
14237 if (hdd_is_roaming_in_progress(pAdapter)) {
14238 /*
14239 * Defer the disconnect action until firmware roaming
14240 * result is received. If STA is in connected state after
14241 * that, send the disconnect command to CSR, otherwise
14242 * CSR would have already sent disconnect event to upper
14243 * layer.
14244 */
14245 hdd_err("Roaming in progress, disconnect command deferred.");
14246 pAdapter->defer_disconnect =
14247 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14248 pAdapter->cfg80211_disconnect_reason = reason;
14249 return 0;
14250 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014251
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014252 prev_conn_state = pHddStaCtx->conn_info.connState;
14253
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014254 /* stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014255 hdd_notice("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014256 wlan_hdd_netif_queue_control(pAdapter,
14257 WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014258 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14260 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14261
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014262 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014263
14264 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14265 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014266 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14267 prev_conn_state != eConnectionState_Connecting) {
14268 hdd_notice("status = %d, already disconnected", status);
14269 result = 0;
14270 goto disconnected;
14271 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14272 /*
14273 * Wait here instead of returning directly, this will block the
14274 * next connect command and allow processing of the scan for
14275 * ssid and the previous connect command in CSR. Else we might
14276 * hit some race conditions leading to SME and HDD out of sync.
14277 */
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014278 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014280 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014281 (int)status);
14282 pHddStaCtx->staDebugState = status;
14283 result = -EINVAL;
14284 goto disconnected;
14285 }
14286 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14287 msecs_to_jiffies
14288 (WLAN_WAIT_TIME_DISCONNECT));
14289
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014290 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014291 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014292 result = -ETIMEDOUT;
14293 }
14294disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014295 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14296#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14297 /* Sending disconnect event to userspace for kernel version < 3.11
14298 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14299 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014300 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014301 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14302 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303#endif
14304
14305 return result;
14306}
14307
14308/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014309 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14310 * @reason: ieee80211 reason code.
14311 *
14312 * This utility function helps log string conversion of reason code.
14313 *
14314 * Return: string conversion of reason code, if match found;
14315 * "Unknown" otherwise.
14316 */
14317static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14318{
14319 switch (reason) {
14320 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14321 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14322 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14323 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14324 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14325 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14326 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14327 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14328 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14329 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14330 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14331 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14332 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14333 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14334 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14335 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14336 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14337 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14338 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14339 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14340 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14341 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14342 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14343 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14344 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14345 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14346 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14347 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14348 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14349 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14350 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14351 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14352 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14353 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14354 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14355 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14356 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14357 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14358 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14359 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14360 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14361 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14362 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14363 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14364 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14365 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14366 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14367 default:
14368 return "Unknown";
14369 }
14370}
14371
14372/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014373 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14374 * @wiphy: Pointer to wiphy
14375 * @dev: Pointer to network device
14376 * @reason: Disconnect reason code
14377 *
14378 * This function is used to issue a disconnect request to SME
14379 *
14380 * Return: 0 for success, non-zero for failure
14381 */
14382static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14383 struct net_device *dev, u16 reason)
14384{
14385 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14386 int status;
14387 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14388 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14389#ifdef FEATURE_WLAN_TDLS
14390 uint8_t staIdx;
14391#endif
14392
14393 ENTER();
14394
Anurag Chouhan6d760662016-02-20 16:05:43 +053014395 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014396 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014397 return -EINVAL;
14398 }
14399
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014400 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14401 hdd_err("invalid session id: %d", pAdapter->sessionId);
14402 return -EINVAL;
14403 }
14404
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014405 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014406 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14407 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014408 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014409 hdd_device_mode_to_string(pAdapter->device_mode),
14410 pAdapter->device_mode, reason);
14411
14412 status = wlan_hdd_validate_context(pHddCtx);
14413
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014414 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014415 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014416
14417 /* Issue disconnect request to SME, if station is in connected state */
14418 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14419 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14420 eCsrRoamDisconnectReason reasonCode =
14421 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14422 hdd_scaninfo_t *pScanInfo;
14423
14424 switch (reason) {
14425 case WLAN_REASON_MIC_FAILURE:
14426 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14427 break;
14428
14429 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14430 case WLAN_REASON_DISASSOC_AP_BUSY:
14431 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14432 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14433 break;
14434
14435 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14436 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14437 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14438 break;
14439
14440 case WLAN_REASON_DEAUTH_LEAVING:
14441 reasonCode =
14442 pHddCtx->config->
14443 gEnableDeauthToDisassocMap ?
14444 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14445 eCSR_DISCONNECT_REASON_DEAUTH;
14446 break;
14447 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14448 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14449 break;
14450 default:
14451 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14452 break;
14453 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014454 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014455 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014456 pScanInfo = &pAdapter->scan_info;
14457 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014458 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014459 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014460 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014461 eCSR_SCAN_ABORT_DEFAULT);
14462 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014463 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464#ifdef FEATURE_WLAN_TDLS
14465 /* First clean up the tdls peers if any */
14466 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14467 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14468 pAdapter->sessionId)
14469 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14470 uint8_t *mac;
14471 mac =
14472 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014473 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14474 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475 pHddCtx->tdlsConnInfo[staIdx].staId,
14476 pAdapter->sessionId,
14477 MAC_ADDR_ARRAY(mac));
14478 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14479 (pAdapter),
14480 pAdapter->sessionId, mac);
14481 }
14482 }
14483#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014484 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014485 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014486 hdd_info("Disconnect request from user space with reason: %s",
14487 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014488 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14489 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014490 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014491 return -EINVAL;
14492 }
14493 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014494 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014495 pHddStaCtx->conn_info.connState);
14496 }
14497
14498 return status;
14499}
14500
14501/**
14502 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14503 * @wiphy: Pointer to wiphy
14504 * @dev: Pointer to network device
14505 * @reason: Disconnect reason code
14506 *
14507 * Return: 0 for success, non-zero for failure
14508 */
14509static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14510 struct net_device *dev, u16 reason)
14511{
14512 int ret;
14513 cds_ssr_protect(__func__);
14514 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14515 cds_ssr_unprotect(__func__);
14516
14517 return ret;
14518}
14519
14520/**
14521 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14522 * @pAdapter: Pointer to adapter
14523 * @param: Pointer to IBSS parameters
14524 *
14525 * This function is used to initialize the security settings in IBSS mode
14526 *
14527 * Return: 0 for success, non-zero for failure
14528 */
14529static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14530 struct cfg80211_ibss_params
14531 *params)
14532{
14533 int status = 0;
14534 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14535 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14536 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14537
14538 ENTER();
14539
14540 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014541 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014542 pHddStaCtx->ibss_enc_key_installed = 0;
14543
14544 if (params->ie_len && (NULL != params->ie)) {
14545 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14546 params->ie_len, WLAN_EID_RSN)) {
14547 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14548 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14549 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14550 tDot11fIEWPA dot11WPAIE;
14551 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14552 u8 *ie;
14553
14554 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14555 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14556 params->ie_len,
14557 DOT11F_EID_WPA);
14558 if (NULL != ie) {
14559 pWextState->wpaVersion =
14560 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014561 /* Unpack the WPA IE
14562 * Skip past the EID byte and length byte
14563 * and four byte WiFi OUI
14564 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14566 &ie[2 + 4],
14567 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014568 /* Extract the multicast cipher, the
14569 * encType for unicast cipher for
14570 * wpa-none is none
14571 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 encryptionType =
14573 hdd_translate_wpa_to_csr_encryption_type
14574 (dot11WPAIE.multicast_cipher);
14575 }
14576 }
14577
14578 status =
14579 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14580 params->ie_len);
14581
14582 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014583 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584 return status;
14585 }
14586 }
14587
14588 pWextState->roamProfile.AuthType.authType[0] =
14589 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14590
14591 if (params->privacy) {
14592 /* Security enabled IBSS, At this time there is no information
14593 * available about the security paramters, so initialise the
14594 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14595 * The correct security parameters will be updated later in
14596 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14597 * set inorder enable privacy bit in beacons
14598 */
14599
14600 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14601 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014602 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14604 pWextState->roamProfile.EncryptionType.numEntries = 1;
14605 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14606 encryptionType;
14607 return status;
14608}
14609
14610/**
14611 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14612 * @wiphy: Pointer to wiphy
14613 * @dev: Pointer to network device
14614 * @param: Pointer to IBSS join parameters
14615 *
14616 * This function is used to create/join an IBSS network
14617 *
14618 * Return: 0 for success, non-zero for failure
14619 */
14620static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14621 struct net_device *dev,
14622 struct cfg80211_ibss_params *params)
14623{
14624 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14625 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14626 tCsrRoamProfile *pRoamProfile;
14627 int status;
14628 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14629 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014630 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014631 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632
14633 ENTER();
14634
Anurag Chouhan6d760662016-02-20 16:05:43 +053014635 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014636 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014637 return -EINVAL;
14638 }
14639
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014640 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14641 hdd_err("invalid session id: %d", pAdapter->sessionId);
14642 return -EINVAL;
14643 }
14644
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014645 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014646 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14647 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014648 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014649 hdd_device_mode_to_string(pAdapter->device_mode),
14650 pAdapter->device_mode);
14651
14652 status = wlan_hdd_validate_context(pHddCtx);
14653
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014654 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014655 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656
14657 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014658 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014659 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14660 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14661 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14662 int indx;
14663
14664 /* Get channel number */
14665 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014666 params->
14667 chandef.
14668 chan->
14669 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014670
14671 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14672 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014673 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014674 return -EOPNOTSUPP;
14675 }
14676
14677 for (indx = 0; indx < numChans; indx++) {
14678 if (channelNum == validChan[indx]) {
14679 break;
14680 }
14681 }
14682 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014683 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014684 return -EINVAL;
14685 }
14686 }
14687
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014688 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689 HW_MODE_20_MHZ)) {
14690 hdd_err("This concurrency combination is not allowed");
14691 return -ECONNREFUSED;
14692 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693
Krunal Soni3091bcc2016-06-23 12:28:21 -070014694 status = qdf_reset_connection_update();
14695 if (!QDF_IS_STATUS_SUCCESS(status))
14696 hdd_err("ERR: clear event failed");
14697
14698 status = cds_current_connections_update(pAdapter->sessionId,
14699 channelNum,
14700 SIR_UPDATE_REASON_JOIN_IBSS);
14701 if (QDF_STATUS_E_FAILURE == status) {
14702 hdd_err("ERROR: connections update failed!!");
14703 return -EINVAL;
14704 }
14705
14706 if (QDF_STATUS_SUCCESS == status) {
14707 status = qdf_wait_for_connection_update();
14708 if (!QDF_IS_STATUS_SUCCESS(status)) {
14709 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014710 return -EINVAL;
14711 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712 }
14713
14714 /*Try disconnecting if already in connected state */
14715 status = wlan_hdd_try_disconnect(pAdapter);
14716 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014717 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718 return -EALREADY;
14719 }
14720
14721 pRoamProfile = &pWextState->roamProfile;
14722
14723 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014724 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014725 return -EINVAL;
14726 }
14727
14728 /* enable selected protection checks in IBSS mode */
14729 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14730
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014731 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014732 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14733 pHddCtx->config->
14734 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014735 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 }
14737
14738 /* BSSID is provided by upper layers hence no need to AUTO generate */
14739 if (NULL != params->bssid) {
14740 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014741 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014742 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014743 return -EIO;
14744 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014745 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014746 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14747 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014748 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014749 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750 return -EIO;
14751 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014752 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014753 }
14754 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14755 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14756 pRoamProfile->beaconInterval = params->beacon_interval;
14757 else {
14758 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014759 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014760 params->beacon_interval, pRoamProfile->beaconInterval);
14761 }
14762
14763 /* Set Channel */
14764 if (channelNum) {
14765 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014766 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014767 pRoamProfile->ChannelInfo.numOfChannels = 1;
14768 pHddStaCtx->conn_info.operationChannel = channelNum;
14769 pRoamProfile->ChannelInfo.ChannelList =
14770 &pHddStaCtx->conn_info.operationChannel;
14771 }
14772
14773 /* Initialize security parameters */
14774 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14775 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014776 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014777 return status;
14778 }
14779
14780 /* Issue connect start */
14781 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14782 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014783 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014784 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014785 operationChannel,
14786 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014787
14788 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014789 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014790 return status;
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_join_ibss() - join ibss
14798 * @wiphy: Pointer to wiphy
14799 * @dev: Pointer to network device
14800 * @param: Pointer to IBSS join parameters
14801 *
14802 * This function is used to create/join an IBSS network
14803 *
14804 * Return: 0 for success, non-zero for failure
14805 */
14806static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14807 struct net_device *dev,
14808 struct cfg80211_ibss_params *params)
14809{
14810 int ret = 0;
14811
14812 cds_ssr_protect(__func__);
14813 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14814 cds_ssr_unprotect(__func__);
14815
14816 return ret;
14817}
14818
14819/**
14820 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14821 * @wiphy: Pointer to wiphy
14822 * @dev: Pointer to network device
14823 *
14824 * This function is used to leave an IBSS network
14825 *
14826 * Return: 0 for success, non-zero for failure
14827 */
14828static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14829 struct net_device *dev)
14830{
14831 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14832 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14833 tCsrRoamProfile *pRoamProfile;
14834 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14835 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014836 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014837 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014838 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014839
14840 ENTER();
14841
Anurag Chouhan6d760662016-02-20 16:05:43 +053014842 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014843 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014844 return -EINVAL;
14845 }
14846
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014847 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14848 hdd_err("invalid session id: %d", pAdapter->sessionId);
14849 return -EINVAL;
14850 }
14851
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014852 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14854 pAdapter->sessionId,
14855 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14856 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014857 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014858 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014859
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014860 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014861 hdd_device_mode_to_string(pAdapter->device_mode),
14862 pAdapter->device_mode);
14863 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014864 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014865 return -EIO;
14866 }
14867
14868 pRoamProfile = &pWextState->roamProfile;
14869
14870 /* Issue disconnect only if interface type is set to IBSS */
14871 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014872 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873 return -EINVAL;
14874 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014875 /* Clearing add IE of beacon */
14876 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14877 sizeof(tSirMacAddr));
14878 updateIE.smeSessionId = pAdapter->sessionId;
14879 updateIE.ieBufferlength = 0;
14880 updateIE.pAdditionIEBuffer = NULL;
14881 updateIE.append = true;
14882 updateIE.notify = true;
14883 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14884 &updateIE,
14885 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014886 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014887 }
14888
14889 /* Reset WNI_CFG_PROBE_RSP Flags */
14890 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014891
14892 /* Issue Disconnect request */
14893 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14894 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14895 pAdapter->sessionId,
14896 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014897 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014898 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014899 hal_status);
14900 return -EAGAIN;
14901 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014902
14903 /* wait for mc thread to cleanup and then return to upper stack
14904 * so by the time upper layer calls the change interface, we are
14905 * all set to proceed further
14906 */
14907 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14908 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14909 if (!rc) {
14910 hdd_err("Failed to disconnect, timed out");
14911 return -ETIMEDOUT;
14912 }
14913
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014914 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014915 return 0;
14916}
14917
14918/**
14919 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14920 * @wiphy: Pointer to wiphy
14921 * @dev: Pointer to network device
14922 *
14923 * This function is used to leave an IBSS network
14924 *
14925 * Return: 0 for success, non-zero for failure
14926 */
14927static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14928 struct net_device *dev)
14929{
14930 int ret = 0;
14931
14932 cds_ssr_protect(__func__);
14933 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14934 cds_ssr_unprotect(__func__);
14935
14936 return ret;
14937}
14938
14939/**
14940 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14941 * @wiphy: Pointer to wiphy
14942 * @changed: Parameters changed
14943 *
14944 * This function is used to set the phy parameters. RTS Threshold/FRAG
14945 * Threshold/Retry Count etc.
14946 *
14947 * Return: 0 for success, non-zero for failure
14948 */
14949static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14950 u32 changed)
14951{
14952 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14953 tHalHandle hHal = pHddCtx->hHal;
14954 int status;
14955
14956 ENTER();
14957
Anurag Chouhan6d760662016-02-20 16:05:43 +053014958 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014959 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014960 return -EINVAL;
14961 }
14962
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014963 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014964 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14965 NO_SESSION, wiphy->rts_threshold));
14966 status = wlan_hdd_validate_context(pHddCtx);
14967
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014968 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014969 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970
14971 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14972 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14973 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14974
14975 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14976 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014977 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978 rts_threshold);
14979 return -EINVAL;
14980 }
14981
14982 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14983 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014984 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014985 rts_threshold);
14986 return -EIO;
14987 }
14988
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014989 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014990 }
14991
14992 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14993 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14994 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14995 wiphy->frag_threshold;
14996
14997 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14998 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014999 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015000 frag_threshold);
15001 return -EINVAL;
15002 }
15003
15004 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15005 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015006 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015007 frag_threshold);
15008 return -EIO;
15009 }
15010
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015011 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012 }
15013
15014 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15015 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15016 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15017 wiphy->retry_short : wiphy->retry_long;
15018
15019 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15020 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015021 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 return -EINVAL;
15023 }
15024
15025 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15026 if (0 != sme_cfg_set_int(hHal,
15027 WNI_CFG_LONG_RETRY_LIMIT,
15028 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015029 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 retry_value);
15031 return -EIO;
15032 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015033 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015034 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15035 if (0 != sme_cfg_set_int(hHal,
15036 WNI_CFG_SHORT_RETRY_LIMIT,
15037 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015038 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 retry_value);
15040 return -EIO;
15041 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015042 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 }
15044 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015045 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015046 return 0;
15047}
15048
15049/**
15050 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15051 * @wiphy: Pointer to wiphy
15052 * @changed: Parameters changed
15053 *
15054 * Return: 0 for success, non-zero for failure
15055 */
15056static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15057{
15058 int ret;
15059
15060 cds_ssr_protect(__func__);
15061 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15062 cds_ssr_unprotect(__func__);
15063
15064 return ret;
15065}
15066
15067/**
15068 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15069 * key
15070 * @wiphy: Pointer to wiphy
15071 * @dev: Pointer to network device
15072 * @key_index: Key index
15073 *
15074 * Return: 0
15075 */
15076static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15077 struct net_device *netdev,
15078 u8 key_index)
15079{
15080 ENTER();
15081 return 0;
15082}
15083
15084/**
15085 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15086 * wlan_hdd_set_default_mgmt_key
15087 * @wiphy: pointer to wiphy
15088 * @netdev: pointer to net_device structure
15089 * @key_index: key index
15090 *
15091 * Return: 0 on success, error number on failure
15092 */
15093static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15094 struct net_device *netdev,
15095 u8 key_index)
15096{
15097 int ret;
15098
15099 cds_ssr_protect(__func__);
15100 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15101 cds_ssr_unprotect(__func__);
15102
15103 return ret;
15104}
15105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015106/**
15107 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15108 * @wiphy: Pointer to wiphy
15109 * @dev: Pointer to network device
15110 * @params: Pointer to tx queue parameters
15111 *
15112 * Return: 0
15113 */
15114static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15115 struct net_device *dev,
15116 struct ieee80211_txq_params *params)
15117{
15118 ENTER();
15119 return 0;
15120}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015121
15122/**
15123 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15124 * @wiphy: pointer to wiphy
15125 * @netdev: pointer to net_device structure
15126 * @params: pointer to ieee80211_txq_params
15127 *
15128 * Return: 0 on success, error number on failure
15129 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015130static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15131 struct net_device *dev,
15132 struct ieee80211_txq_params *params)
15133{
15134 int ret;
15135
15136 cds_ssr_protect(__func__);
15137 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15138 cds_ssr_unprotect(__func__);
15139
15140 return ret;
15141}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015142
15143/**
15144 * __wlan_hdd_cfg80211_del_station() - delete station v2
15145 * @wiphy: Pointer to wiphy
15146 * @param: Pointer to delete station parameter
15147 *
15148 * Return: 0 for success, non-zero for failure
15149 */
15150static
15151int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15152 struct net_device *dev,
15153 struct tagCsrDelStaParams *pDelStaParams)
15154{
15155 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15156 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015157 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015158 hdd_hostapd_state_t *hapd_state;
15159 int status;
15160 uint8_t staId;
15161 uint8_t *mac;
15162
15163 ENTER();
15164
Anurag Chouhan6d760662016-02-20 16:05:43 +053015165 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015166 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015167 return -EINVAL;
15168 }
15169
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015170 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15171 hdd_err("invalid session id: %d", pAdapter->sessionId);
15172 return -EINVAL;
15173 }
15174
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015175 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015176 TRACE_CODE_HDD_CFG80211_DEL_STA,
15177 pAdapter->sessionId, pAdapter->device_mode));
15178
15179 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15180 status = wlan_hdd_validate_context(pHddCtx);
15181
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015182 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015183 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015184
15185 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15186
Krunal Sonib4326f22016-03-10 13:05:51 -080015187 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15188 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015189
15190 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15191 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015192 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015193 return 0;
15194 }
15195
Anurag Chouhanc5548422016-02-24 18:33:27 +053015196 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015197 uint16_t i;
15198 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15199 if ((pAdapter->aStaInfo[i].isUsed) &&
15200 (!pAdapter->aStaInfo[i].
15201 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015202 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015203 mac,
15204 pAdapter->aStaInfo[i].
15205 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015206 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015207 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15208 hdd_ipa_wlan_evt(pAdapter,
15209 pAdapter->
15210 aStaInfo[i].
15211 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015212 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015213 mac);
15214 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015215 hdd_notice("Delete STA with MAC::"
15216 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015217 MAC_ADDR_ARRAY(mac));
15218
15219 if (pHddCtx->dev_dfs_cac_status ==
15220 DFS_CAC_IN_PROGRESS)
15221 goto fn_end;
15222
Wei Song2f76f642016-11-18 16:32:53 +080015223 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015224 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015225 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015226 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015227 hdd_softap_sta_deauth(pAdapter,
15228 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015229 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015230 pAdapter->aStaInfo[i].
15231 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015232 qdf_status =
15233 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015234 &hapd_state->
15235 qdf_sta_disassoc_event,
15236 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015237 if (!QDF_IS_STATUS_SUCCESS(
15238 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015239 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015240 }
15241 }
15242 }
15243 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015244 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015245 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015246 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015248 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015249 hdd_notice("Skip DEL STA as this is not used::"
15250 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015251 MAC_ADDR_ARRAY(mac));
15252 return -ENOENT;
15253 }
15254
15255 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15256 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015257 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015258 }
15259
15260 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15261 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015262 hdd_notice("Skip DEL STA as deauth is in progress::"
15263 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 MAC_ADDR_ARRAY(mac));
15265 return -ENOENT;
15266 }
15267
15268 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15269
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015270 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015271 MAC_ADDR_ARRAY(mac));
15272
15273 /* Case: SAP in ACS selected DFS ch and client connected
15274 * Now Radar detected. Then if random channel is another
15275 * DFS ch then new CAC is initiated and no TX allowed.
15276 * So do not send any mgmt frames as it will timeout
15277 * during CAC.
15278 */
15279
15280 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15281 goto fn_end;
15282
Wei Song2f76f642016-11-18 16:32:53 +080015283 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015284 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15285 (pAdapter), pAdapter->sessionId,
15286 (uint8_t *)&pDelStaParams->peerMacAddr,
15287 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015288 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015289 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015290 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291 pAdapter->aStaInfo[staId].isDeauthInProgress =
15292 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015293 hdd_notice("STA removal failed for ::"
15294 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 MAC_ADDR_ARRAY(mac));
15296 return -ENOENT;
15297 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015298 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015299 &hapd_state->
15300 qdf_sta_disassoc_event,
15301 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015302 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015303 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 }
15305 }
15306 }
15307
15308fn_end:
15309 EXIT();
15310 return 0;
15311}
15312
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015313#if defined(USE_CFG80211_DEL_STA_V2)
15314/**
15315 * wlan_hdd_del_station() - delete station wrapper
15316 * @adapter: pointer to the hdd adapter
15317 *
15318 * Return: None
15319 */
15320void wlan_hdd_del_station(hdd_adapter_t *adapter)
15321{
15322 struct station_del_parameters del_sta;
15323 del_sta.mac = NULL;
15324 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15325 del_sta.reason_code = eCsrForcedDeauthSta;
15326
15327 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15328 &del_sta);
15329}
15330#else
15331void wlan_hdd_del_station(hdd_adapter_t *adapter)
15332{
15333 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15334}
15335#endif
15336
15337#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015338/**
15339 * wlan_hdd_cfg80211_del_station() - delete station v2
15340 * @wiphy: Pointer to wiphy
15341 * @param: Pointer to delete station parameter
15342 *
15343 * Return: 0 for success, non-zero for failure
15344 */
15345int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15346 struct net_device *dev,
15347 struct station_del_parameters *param)
15348#else
15349/**
15350 * wlan_hdd_cfg80211_del_station() - delete station
15351 * @wiphy: Pointer to wiphy
15352 * @mac: Pointer to station mac address
15353 *
15354 * Return: 0 for success, non-zero for failure
15355 */
15356#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15357int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15358 struct net_device *dev,
15359 const uint8_t *mac)
15360#else
15361int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15362 struct net_device *dev,
15363 uint8_t *mac)
15364#endif
15365#endif
15366{
15367 int ret;
15368 struct tagCsrDelStaParams delStaParams;
15369
15370 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015371#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015372 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015373 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015374 return -EINVAL;
15375 }
15376 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15377 param->subtype, &delStaParams);
15378#else
15379 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15380 (SIR_MAC_MGMT_DEAUTH >> 4),
15381 &delStaParams);
15382#endif
15383 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15384 cds_ssr_unprotect(__func__);
15385
15386 return ret;
15387}
15388
15389/**
15390 * __wlan_hdd_cfg80211_add_station() - add station
15391 * @wiphy: Pointer to wiphy
15392 * @mac: Pointer to station mac address
15393 * @pmksa: Pointer to add station parameter
15394 *
15395 * Return: 0 for success, non-zero for failure
15396 */
15397static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15398 struct net_device *dev,
15399 const uint8_t *mac,
15400 struct station_parameters *params)
15401{
15402 int status = -EPERM;
15403#ifdef FEATURE_WLAN_TDLS
15404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15405 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15406 u32 mask, set;
15407
15408 ENTER();
15409
Anurag Chouhan6d760662016-02-20 16:05:43 +053015410 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015411 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015412 return -EINVAL;
15413 }
15414
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015415 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15416 hdd_err("invalid session id: %d", pAdapter->sessionId);
15417 return -EINVAL;
15418 }
15419
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015420 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015421 TRACE_CODE_HDD_CFG80211_ADD_STA,
15422 pAdapter->sessionId, params->listen_interval));
15423
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015424 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015425 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015426
15427 mask = params->sta_flags_mask;
15428
15429 set = params->sta_flags_set;
15430
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015431 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 MAC_ADDR_ARRAY(mac));
15433
15434 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15435 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15436 status =
15437 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15438 }
15439 }
15440#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015441 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015442 return status;
15443}
15444
15445/**
15446 * wlan_hdd_cfg80211_add_station() - add station
15447 * @wiphy: Pointer to wiphy
15448 * @mac: Pointer to station mac address
15449 * @pmksa: Pointer to add station parameter
15450 *
15451 * Return: 0 for success, non-zero for failure
15452 */
15453#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15454static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15455 struct net_device *dev,
15456 const uint8_t *mac,
15457 struct station_parameters *params)
15458#else
15459static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15460 struct net_device *dev, uint8_t *mac,
15461 struct station_parameters *params)
15462#endif
15463{
15464 int ret;
15465
15466 cds_ssr_protect(__func__);
15467 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15468 cds_ssr_unprotect(__func__);
15469
15470 return ret;
15471}
15472
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015473/**
15474 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15475 * @wiphy: Pointer to wiphy
15476 * @dev: Pointer to network device
15477 * @pmksa: Pointer to set pmksa parameter
15478 *
15479 * Return: 0 for success, non-zero for failure
15480 */
15481static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15482 struct net_device *dev,
15483 struct cfg80211_pmksa *pmksa)
15484{
15485 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15486 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15487 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015488 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489 int status;
15490 tPmkidCacheInfo pmk_id;
15491
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015492 ENTER();
15493
Anurag Chouhan6d760662016-02-20 16:05:43 +053015494 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015495 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015496 return -EINVAL;
15497 }
15498
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015499 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15500 hdd_err("invalid session id: %d", pAdapter->sessionId);
15501 return -EINVAL;
15502 }
15503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015504 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015505 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015506 return -EINVAL;
15507 }
15508
15509 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015510 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015511 pmksa->bssid, pmksa->pmkid);
15512 return -EINVAL;
15513 }
15514
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015515 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015516 MAC_ADDR_ARRAY(pmksa->bssid));
15517
15518 status = wlan_hdd_validate_context(pHddCtx);
15519
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015520 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015521 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015522
15523 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15524
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015525 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15526 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015527
15528 /* Add to the PMKSA ID Cache in CSR */
15529 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15530 &pmk_id, 1, false);
15531
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015532 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015533 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15534 pAdapter->sessionId, result));
15535
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015536 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015537 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015538}
15539
15540/**
15541 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15542 * @wiphy: Pointer to wiphy
15543 * @dev: Pointer to network device
15544 * @pmksa: Pointer to set pmksa parameter
15545 *
15546 * Return: 0 for success, non-zero for failure
15547 */
15548static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15549 struct net_device *dev,
15550 struct cfg80211_pmksa *pmksa)
15551{
15552 int ret;
15553
15554 cds_ssr_protect(__func__);
15555 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15556 cds_ssr_unprotect(__func__);
15557
15558 return ret;
15559}
15560
15561/**
15562 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15563 * @wiphy: Pointer to wiphy
15564 * @dev: Pointer to network device
15565 * @pmksa: Pointer to pmksa parameter
15566 *
15567 * Return: 0 for success, non-zero for failure
15568 */
15569static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15570 struct net_device *dev,
15571 struct cfg80211_pmksa *pmksa)
15572{
15573 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15574 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15575 tHalHandle halHandle;
15576 int status = 0;
15577
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015578 ENTER();
15579
Anurag Chouhan6d760662016-02-20 16:05:43 +053015580 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015581 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015582 return -EINVAL;
15583 }
15584
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015585 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15586 hdd_err("invalid session id: %d", pAdapter->sessionId);
15587 return -EINVAL;
15588 }
15589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015590 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015591 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592 return -EINVAL;
15593 }
15594
15595 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015596 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597 return -EINVAL;
15598 }
15599
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015600 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 MAC_ADDR_ARRAY(pmksa->bssid));
15602
15603 status = wlan_hdd_validate_context(pHddCtx);
15604
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015605 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015607
15608 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15609
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015610 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015611 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15612 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015613 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015614 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015615 sme_roam_del_pmkid_from_cache(halHandle,
15616 pAdapter->sessionId, pmksa->bssid,
15617 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015618 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015619 MAC_ADDR_ARRAY(pmksa->bssid));
15620 status = -EINVAL;
15621 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015622 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015623 return status;
15624}
15625
15626/**
15627 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15628 * @wiphy: Pointer to wiphy
15629 * @dev: Pointer to network device
15630 * @pmksa: Pointer to pmksa parameter
15631 *
15632 * Return: 0 for success, non-zero for failure
15633 */
15634static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15635 struct net_device *dev,
15636 struct cfg80211_pmksa *pmksa)
15637{
15638 int ret;
15639
15640 cds_ssr_protect(__func__);
15641 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15642 cds_ssr_unprotect(__func__);
15643
15644 return ret;
15645
15646}
15647
15648/**
15649 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15650 * @wiphy: Pointer to wiphy
15651 * @dev: Pointer to network device
15652 *
15653 * Return: 0 for success, non-zero for failure
15654 */
15655static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15656 struct net_device *dev)
15657{
15658 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15659 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15660 tHalHandle halHandle;
15661 int status = 0;
15662
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015663 ENTER();
15664
Anurag Chouhan6d760662016-02-20 16:05:43 +053015665 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015666 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015667 return -EINVAL;
15668 }
15669
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015670 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15671 hdd_err("invalid session id: %d", pAdapter->sessionId);
15672 return -EINVAL;
15673 }
15674
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015675 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676
15677 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15678 status = wlan_hdd_validate_context(pHddCtx);
15679
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015680 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015681 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015682
15683 /* Retrieve halHandle */
15684 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15685
15686 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015687 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015688 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15689 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015690 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015691 status = -EINVAL;
15692 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015693 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015694 return status;
15695}
15696
15697/**
15698 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15699 * @wiphy: Pointer to wiphy
15700 * @dev: Pointer to network device
15701 *
15702 * Return: 0 for success, non-zero for failure
15703 */
15704static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15705 struct net_device *dev)
15706{
15707 int ret;
15708
15709 cds_ssr_protect(__func__);
15710 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15711 cds_ssr_unprotect(__func__);
15712
15713 return ret;
15714}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015715
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015716#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015717/**
15718 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15719 * @wiphy: Pointer to wiphy
15720 * @dev: Pointer to network device
15721 * @ftie: Pointer to fast transition ie parameter
15722 *
15723 * Return: 0 for success, non-zero for failure
15724 */
15725static int
15726__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15727 struct net_device *dev,
15728 struct cfg80211_update_ft_ies_params *ftie)
15729{
15730 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15731 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15732 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15733 int status;
15734
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015735 ENTER();
15736
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015737 status = wlan_hdd_validate_context(hdd_ctx);
15738 if (status)
15739 return status;
15740
Anurag Chouhan6d760662016-02-20 16:05:43 +053015741 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015742 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015743 return -EINVAL;
15744 }
15745
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015746 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15747 hdd_err("invalid session id: %d", pAdapter->sessionId);
15748 return -EINVAL;
15749 }
15750
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015751 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15753 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15754 /* Added for debug on reception of Re-assoc Req. */
15755 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015756 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015758 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015759 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015760 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015761 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015762
15763 /* Pass the received FT IEs to SME */
15764 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15765 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015766 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015767 return 0;
15768}
15769
15770/**
15771 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15772 * @wiphy: Pointer to wiphy
15773 * @dev: Pointer to network device
15774 * @ftie: Pointer to fast transition ie parameter
15775 *
15776 * Return: 0 for success, non-zero for failure
15777 */
15778static int
15779wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15780 struct net_device *dev,
15781 struct cfg80211_update_ft_ies_params *ftie)
15782{
15783 int ret;
15784
15785 cds_ssr_protect(__func__);
15786 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15787 cds_ssr_unprotect(__func__);
15788
15789 return ret;
15790}
15791#endif
15792
Mukul Sharma3d36c392017-01-18 18:39:12 +053015793void wlan_hdd_cfg80211_update_replay_counter_callback(
15794 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015796{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015797 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15798 uint8_t temp_replay_counter[8];
15799 int i;
15800 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015801
15802 ENTER();
15803
Mukul Sharma3d36c392017-01-18 18:39:12 +053015804 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015805 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015806 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015807 }
15808
Mukul Sharma3d36c392017-01-18 18:39:12 +053015809 if (!gtk_rsp_param) {
15810 hdd_err("gtk_rsp_param is Null");
15811 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015812 }
15813
Mukul Sharma3d36c392017-01-18 18:39:12 +053015814 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015815 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015816 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015817 }
15818
Mukul Sharma3d36c392017-01-18 18:39:12 +053015819 hdd_notice("updated replay counter: %llu from fwr",
15820 gtk_rsp_param->replay_counter);
15821 /* convert little to big endian since supplicant works on big endian */
15822 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15823 for (i = 0; i < 8; i++)
15824 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825
Mukul Sharma3d36c392017-01-18 18:39:12 +053015826 hdd_notice("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015828 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015829 gtk_rsp_param->bssid.bytes,
15830 temp_replay_counter, GFP_KERNEL);
15831out:
15832 EXIT();
15833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015834}
15835
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015836static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015837int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015838 struct net_device *dev,
15839 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015840{
15841 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015842 int result, i;
15843 struct pmo_gtk_req *gtk_req = NULL;
15844 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15845 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015846 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015847
15848 ENTER();
15849
Anurag Chouhan6d760662016-02-20 16:05:43 +053015850 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015851 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015852 result = -EINVAL;
15853 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015854 }
15855
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015856 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15857 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015858 result = -EINVAL;
15859 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015860 }
15861
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015862 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015863 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15864 pAdapter->sessionId, pAdapter->device_mode));
15865
Mukul Sharma3d36c392017-01-18 18:39:12 +053015866 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015867 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015868 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015869
Mukul Sharma3d36c392017-01-18 18:39:12 +053015870 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15871 if (!gtk_req) {
15872 hdd_err("cannot allocate gtk_req");
15873 result = -ENOMEM;
15874 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015875 }
15876
Mukul Sharma3d36c392017-01-18 18:39:12 +053015877 /* convert big to little endian since driver work on little endian */
15878 buf = (uint8_t *)&gtk_req->replay_counter;
15879 for (i = 0; i < 8; i++)
15880 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015881
Mukul Sharma3d36c392017-01-18 18:39:12 +053015882 hdd_notice("current replay counter: %llu in user space",
15883 gtk_req->replay_counter);
15884 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15885 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15886 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15887 if (status != QDF_STATUS_SUCCESS) {
15888 hdd_err("Failed to cache GTK Offload");
15889 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015890 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015891out:
15892 if (gtk_req)
15893 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015894 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015896 return result;
15897}
15898
15899/**
15900 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15901 * @wiphy: Pointer to wiphy
15902 * @dev: Pointer to network device
15903 * @data: Pointer to rekey data
15904 *
15905 * This function is used to offload GTK rekeying job to the firmware.
15906 *
15907 * Return: 0 for success, non-zero for failure
15908 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015909static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15911 struct net_device *dev,
15912 struct cfg80211_gtk_rekey_data *data)
15913{
15914 int ret;
15915
15916 cds_ssr_protect(__func__);
15917 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15918 cds_ssr_unprotect(__func__);
15919
15920 return ret;
15921}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922
15923/**
15924 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15925 * @wiphy: Pointer to wiphy
15926 * @dev: Pointer to network device
15927 * @param: Pointer to access control parameter
15928 *
15929 * Return: 0 for success, non-zero for failure
15930 */
15931static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15932 struct net_device *dev,
15933 const struct cfg80211_acl_data *params)
15934{
15935 int i;
15936 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15937 hdd_hostapd_state_t *pHostapdState;
15938 tsap_Config_t *pConfig;
15939 v_CONTEXT_t p_cds_context = NULL;
15940 hdd_context_t *pHddCtx;
15941 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015942 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015943
15944 ENTER();
15945
Anurag Chouhan6d760662016-02-20 16:05:43 +053015946 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015947 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015948 return -EINVAL;
15949 }
15950
15951 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015952 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015953 return -EINVAL;
15954 }
15955
15956 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15957 status = wlan_hdd_validate_context(pHddCtx);
15958
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015959 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015960 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015961
15962 p_cds_context = pHddCtx->pcds_context;
15963 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15964
15965 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015966 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015967 return -EINVAL;
15968 }
15969
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015970 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015971 params->n_acl_entries);
15972
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015973 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015974 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15975 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015976 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15978
15979 /* default value */
15980 pConfig->num_accept_mac = 0;
15981 pConfig->num_deny_mac = 0;
15982
15983 /**
15984 * access control policy
15985 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15986 * listed in hostapd.deny file.
15987 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15988 * listed in hostapd.accept file.
15989 */
15990 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15991 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15992 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15993 params->acl_policy) {
15994 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15995 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015996 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015997 params->acl_policy);
15998 return -ENOTSUPP;
15999 }
16000
16001 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16002 pConfig->num_accept_mac = params->n_acl_entries;
16003 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016004 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
16005 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006 MAC_ADDR_ARRAY(
16007 params->mac_addrs[i].addr));
16008
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016009 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016010 params->mac_addrs[i].addr,
16011 sizeof(qcmacaddr));
16012 }
16013 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16014 pConfig->num_deny_mac = params->n_acl_entries;
16015 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016016 hdd_notice("** Add ACL MAC entry %i in BlackList :"
16017 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018 MAC_ADDR_ARRAY(
16019 params->mac_addrs[i].addr));
16020
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016021 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016022 params->mac_addrs[i].addr,
16023 sizeof(qcmacaddr));
16024 }
16025 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016026 qdf_status = wlansap_set_mac_acl(
16027 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016028 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016029 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016030 return -EINVAL;
16031 }
16032 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016033 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016034 hdd_device_mode_to_string(pAdapter->device_mode),
16035 pAdapter->device_mode);
16036 return -EINVAL;
16037 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016038 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016039 return 0;
16040}
16041
16042/**
16043 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16044 * __wlan_hdd_cfg80211_set_mac_acl
16045 * @wiphy: pointer to wiphy structure
16046 * @dev: pointer to net_device
16047 * @params: pointer to cfg80211_acl_data
16048 *
16049 * Return; 0 on success, error number otherwise
16050 */
16051static int
16052wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16053 struct net_device *dev,
16054 const struct cfg80211_acl_data *params)
16055{
16056 int ret;
16057
16058 cds_ssr_protect(__func__);
16059 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16060 cds_ssr_unprotect(__func__);
16061
16062 return ret;
16063}
16064
16065#ifdef WLAN_NL80211_TESTMODE
16066#ifdef FEATURE_WLAN_LPHB
16067/**
16068 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16069 * @pHddCtx: Pointer to hdd context
16070 * @lphbInd: Pointer to low power heart beat indication parameter
16071 *
16072 * Return: none
16073 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016074static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
16075 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076{
16077 struct sk_buff *skb;
16078
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016079 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016081 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016082 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016083
16084 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016085 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016086 return;
16087 }
16088
16089 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
16090 wiphy, sizeof(tSirLPHBInd),
16091 GFP_ATOMIC);
16092 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016093 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016094 return;
16095 }
16096
16097 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016098 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016099 goto nla_put_failure;
16100 }
16101 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016102 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016103 goto nla_put_failure;
16104 }
16105 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016106 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016107 goto nla_put_failure;
16108 }
16109 cfg80211_testmode_event(skb, GFP_ATOMIC);
16110 return;
16111
16112nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016113 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016114 kfree_skb(skb);
16115
16116 return;
16117}
16118#endif /* FEATURE_WLAN_LPHB */
16119
16120/**
16121 * __wlan_hdd_cfg80211_testmode() - test mode
16122 * @wiphy: Pointer to wiphy
16123 * @data: Data pointer
16124 * @len: Data length
16125 *
16126 * Return: 0 for success, non-zero for failure
16127 */
16128static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16129 void *data, int len)
16130{
16131 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16132 int err;
16133 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16134
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016135 ENTER();
16136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137 err = wlan_hdd_validate_context(pHddCtx);
16138 if (err)
16139 return err;
16140
16141 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16142 len, wlan_hdd_tm_policy);
16143 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016144 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016145 return err;
16146 }
16147
16148 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016149 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016150 return -EINVAL;
16151 }
16152
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016153 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016154 TRACE_CODE_HDD_CFG80211_TESTMODE,
16155 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16157#ifdef FEATURE_WLAN_LPHB
16158 /* Low Power Heartbeat configuration request */
16159 case WLAN_HDD_TM_CMD_WLAN_HB:
16160 {
16161 int buf_len;
16162 void *buf;
16163 tSirLPHBReq *hb_params = NULL;
16164 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016165 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166
16167 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016168 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016169 return -EINVAL;
16170 }
16171
16172 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16173 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16174
16175 hb_params_temp = (tSirLPHBReq *) buf;
16176 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16177 && (hb_params_temp->params.lphbTcpParamReq.
16178 timePeriodSec == 0))
16179 return -EINVAL;
16180
16181 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016182 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016183 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016184 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016185 return -ENOMEM;
16186 }
16187
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016188 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016189 smeStatus =
16190 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16191 hb_params,
16192 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016193 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016194 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016195 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016196 }
16197 return 0;
16198 }
16199#endif /* FEATURE_WLAN_LPHB */
16200
16201#if defined(QCA_WIFI_FTM)
16202 case WLAN_HDD_TM_CMD_WLAN_FTM:
16203 {
16204 int buf_len;
16205 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016206 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016207 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016208 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016209 return -EINVAL;
16210 }
16211
16212 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16213 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16214
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016215 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016216
16217 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16218
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016219 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220 err = -EBUSY;
16221 break;
16222 }
16223#endif
16224
16225 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016226 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16228 return -EOPNOTSUPP;
16229 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016230 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016231 return err;
16232}
16233
16234/**
16235 * wlan_hdd_cfg80211_testmode() - test mode
16236 * @wiphy: Pointer to wiphy
16237 * @dev: Pointer to network device
16238 * @data: Data pointer
16239 * @len: Data length
16240 *
16241 * Return: 0 for success, non-zero for failure
16242 */
16243static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16244#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16245 struct wireless_dev *wdev,
16246#endif
16247 void *data, int len)
16248{
16249 int ret;
16250
16251 cds_ssr_protect(__func__);
16252 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16253 cds_ssr_unprotect(__func__);
16254
16255 return ret;
16256}
16257
16258#if defined(QCA_WIFI_FTM)
16259/**
16260 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16261 * @buf: Pointer to buffer
16262 * @buf_len: Buffer length
16263 *
16264 * Return: none
16265 */
16266void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16267{
16268 struct sk_buff *skb;
16269 hdd_context_t *hdd_ctx;
16270
16271 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016272 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273 return;
16274 }
16275
Anurag Chouhan6d760662016-02-20 16:05:43 +053016276 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016277 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016278 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016279 return;
16280 }
16281
16282 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16283 buf_len, GFP_KERNEL);
16284 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016285 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016286 return;
16287 }
16288
16289 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16290 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16291 goto nla_put_failure;
16292
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016293 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016294
16295 cfg80211_testmode_event(skb, GFP_KERNEL);
16296 return;
16297
16298nla_put_failure:
16299 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016300 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016301}
16302#endif
16303#endif /* CONFIG_NL80211_TESTMODE */
16304
16305#ifdef QCA_HT_2040_COEX
16306/**
16307 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16308 * @wiphy: Pointer to wiphy
16309 * @dev: Pointer to network device
16310 * @chandef: Pointer to channel definition parameter
16311 *
16312 * Return: 0 for success, non-zero for failure
16313 */
16314static int
16315__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16316 struct net_device *dev,
16317 struct cfg80211_chan_def *chandef)
16318{
16319 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16320 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016321 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016322 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016323 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016324
Anurag Chouhan6d760662016-02-20 16:05:43 +053016325 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016326 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016327 return -EINVAL;
16328 }
16329
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016330 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16331 hdd_err("invalid session id: %d", pAdapter->sessionId);
16332 return -EINVAL;
16333 }
16334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016335 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16336 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016337 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016338 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016339
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016340 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016341 sme_get_config_param(pHddCtx->hHal, &sme_config);
16342 switch (chandef->width) {
16343 case NL80211_CHAN_WIDTH_20:
16344 if (sme_config.csrConfig.channelBondingMode24GHz !=
16345 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16346 sme_config.csrConfig.channelBondingMode24GHz =
16347 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16348 sme_update_config(pHddCtx->hHal, &sme_config);
16349 cbModeChange = true;
16350 }
16351 break;
16352
16353 case NL80211_CHAN_WIDTH_40:
16354 if (sme_config.csrConfig.channelBondingMode24GHz ==
16355 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16356 if (NL80211_CHAN_HT40MINUS ==
16357 cfg80211_get_chandef_type(chandef))
16358 sme_config.csrConfig.channelBondingMode24GHz =
16359 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16360 else
16361 sme_config.csrConfig.channelBondingMode24GHz =
16362 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16363 sme_update_config(pHddCtx->hHal, &sme_config);
16364 cbModeChange = true;
16365 }
16366 break;
16367
16368 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016369 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016370 return -EINVAL;
16371 }
16372
16373 if (!cbModeChange)
16374 return 0;
16375
Krunal Sonib4326f22016-03-10 13:05:51 -080016376 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016377 return 0;
16378
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016379 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016380 sme_config.csrConfig.channelBondingMode24GHz);
16381
16382 /* Change SAP ht2040 mode */
16383 status = hdd_set_sap_ht2040_mode(pAdapter,
16384 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016385 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016386 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016387 return -EINVAL;
16388 }
16389
16390 return 0;
16391}
16392
16393/**
16394 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16395 * @wiphy: Pointer to wiphy
16396 * @dev: Pointer to network device
16397 * @chandef: Pointer to channel definition parameter
16398 *
16399 * Return: 0 for success, non-zero for failure
16400 */
16401static int
16402wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16403 struct net_device *dev,
16404 struct cfg80211_chan_def *chandef)
16405{
16406 int ret;
16407
16408 cds_ssr_protect(__func__);
16409 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16410 cds_ssr_unprotect(__func__);
16411
16412 return ret;
16413}
16414#endif
16415
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016416#ifdef CHANNEL_SWITCH_SUPPORTED
16417/**
16418 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16419 * channel in SAP/GO
16420 * @wiphy: wiphy pointer
16421 * @dev: dev pointer.
16422 * @csa_params: Change channel params
16423 *
16424 * This function is called to switch channel in SAP/GO
16425 *
16426 * Return: 0 if success else return non zero
16427 */
16428static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16429 struct net_device *dev,
16430 struct cfg80211_csa_settings *csa_params)
16431{
16432 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16433 hdd_context_t *hdd_ctx;
16434 uint8_t channel;
16435 uint16_t freq;
16436 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016437 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016438
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016439 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016440 csa_params->chandef.chan->center_freq);
16441
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016442 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16443 hdd_err("invalid session id: %d", adapter->sessionId);
16444 return -EINVAL;
16445 }
16446
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016447 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16448 ret = wlan_hdd_validate_context(hdd_ctx);
16449
16450 if (0 != ret)
16451 return ret;
16452
Krunal Sonib4326f22016-03-10 13:05:51 -080016453 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16454 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016455 return -ENOTSUPP;
16456
16457 freq = csa_params->chandef.chan->center_freq;
16458 channel = cds_freq_to_chan(freq);
16459
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016460 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16461
16462 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016463 return ret;
16464}
16465
16466/**
16467 * wlan_hdd_cfg80211_channel_switch()- function to switch
16468 * channel in SAP/GO
16469 * @wiphy: wiphy pointer
16470 * @dev: dev pointer.
16471 * @csa_params: Change channel params
16472 *
16473 * This function is called to switch channel in SAP/GO
16474 *
16475 * Return: 0 if success else return non zero
16476 */
16477static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16478 struct net_device *dev,
16479 struct cfg80211_csa_settings *csa_params)
16480{
16481 int ret;
16482
16483 cds_ssr_protect(__func__);
16484 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16485 cds_ssr_unprotect(__func__);
16486 return ret;
16487}
16488#endif
16489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016490/**
16491 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16492 * translation from NL to policy manager type
16493 * @type: Generic connection mode type defined in NL
16494 *
16495 *
16496 * This function provides the type translation
16497 *
16498 * Return: cds_con_mode enum
16499 */
16500enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16501 enum nl80211_iftype type)
16502{
16503 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16504 switch (type) {
16505 case NL80211_IFTYPE_STATION:
16506 mode = CDS_STA_MODE;
16507 break;
16508 case NL80211_IFTYPE_P2P_CLIENT:
16509 mode = CDS_P2P_CLIENT_MODE;
16510 break;
16511 case NL80211_IFTYPE_P2P_GO:
16512 mode = CDS_P2P_GO_MODE;
16513 break;
16514 case NL80211_IFTYPE_AP:
16515 mode = CDS_SAP_MODE;
16516 break;
16517 case NL80211_IFTYPE_ADHOC:
16518 mode = CDS_IBSS_MODE;
16519 break;
16520 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016521 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016522 type);
16523 }
16524 return mode;
16525}
16526
16527/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016528 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16529 * @wiphy: Handle to struct wiphy to get handle to module context.
16530 * @chandef: Contains information about the capture channel to be set.
16531 *
16532 * This interface is called if and only if monitor mode interface alone is
16533 * active.
16534 *
16535 * Return: 0 success or error code on failure.
16536 */
16537static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16538 struct cfg80211_chan_def *chandef)
16539{
16540 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16541 hdd_adapter_t *adapter;
16542 hdd_station_ctx_t *sta_ctx;
16543 struct hdd_mon_set_ch_info *ch_info;
16544 QDF_STATUS status;
16545 tHalHandle hal_hdl;
16546 struct qdf_mac_addr bssid;
16547 tCsrRoamProfile roam_profile;
16548 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016549 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016550 int ret;
16551 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16552
16553 ENTER();
16554
16555 ret = wlan_hdd_validate_context(hdd_ctx);
16556 if (ret)
16557 return ret;
16558
16559 hal_hdl = hdd_ctx->hHal;
16560
16561 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16562 if (!adapter)
16563 return -EIO;
16564
16565 hdd_info("%s: set monitor mode Channel %d and freq %d",
16566 adapter->dev->name, chan_num, chandef->chan->center_freq);
16567
16568 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16569 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016570 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16571 roam_profile.ChannelInfo.numOfChannels = 1;
16572 roam_profile.phyMode = ch_info->phy_mode;
16573 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016574 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016575
16576 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16577 QDF_MAC_ADDR_SIZE);
16578
16579 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016580 /*
16581 * CDS api expects secondary channel for calculating
16582 * the channel params
16583 */
16584 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16585 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16586 if (chan_num >= 1 && chan_num <= 5)
16587 sec_ch = chan_num + 4;
16588 else if (chan_num >= 6 && chan_num <= 13)
16589 sec_ch = chan_num - 4;
16590 }
16591 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016592 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16593 &roam_profile);
16594 if (status) {
16595 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16596 status);
16597 ret = qdf_status_to_os_return(status);
16598 return ret;
16599 }
16600 EXIT();
16601 return 0;
16602}
16603
16604/**
16605 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16606 * @wiphy: Handle to struct wiphy to get handle to module context.
16607 * @chandef: Contains information about the capture channel to be set.
16608 *
16609 * This interface is called if and only if monitor mode interface alone is
16610 * active.
16611 *
16612 * Return: 0 success or error code on failure.
16613 */
16614static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16615 struct cfg80211_chan_def *chandef)
16616{
16617 int ret;
16618
16619 cds_ssr_protect(__func__);
16620 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16621 cds_ssr_unprotect(__func__);
16622 return ret;
16623}
16624
16625/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016626 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16627 * @adapter: pointer to adapter
16628 *
16629 * Wrapper function to clear link layer stats.
16630 * return - void
16631 */
16632void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16633{
16634 tSirLLStatsClearReq link_layer_stats_clear_req;
16635 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16636
Mukul Sharma491021c2016-09-29 21:39:19 +053016637 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16638 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016639 link_layer_stats_clear_req.stopReq = 0;
16640 link_layer_stats_clear_req.reqId = 1;
16641 link_layer_stats_clear_req.staId = adapter->sessionId;
16642 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16643
16644 return;
16645}
16646
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016647/**
16648 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16649 * @adapter: HDD Adapter
16650 *
16651 * If roaming is in progress and there is a request to
16652 * disconnect the session, then it is deferred. Once
16653 * roaming is complete/aborted, then this routine is
16654 * used to resume the disconnect that was deferred
16655 *
16656 * Return: None
16657 */
16658void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16659{
16660 switch (adapter->defer_disconnect) {
16661 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16662 adapter->defer_disconnect = 0;
16663 wlan_hdd_disconnect(adapter,
16664 adapter->cfg80211_disconnect_reason);
16665 break;
16666 case DEFER_DISCONNECT_TRY_DISCONNECT:
16667 wlan_hdd_try_disconnect(adapter);
16668 adapter->defer_disconnect = 0;
16669 break;
16670 default:
16671 hdd_info("Invalid source to defer:%d. Hence not handling it",
16672 adapter->defer_disconnect);
16673 break;
16674 }
16675}
16676
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016677#define CNT_DIFF(cur, prev) \
16678 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16679#define MAX_COUNT 0xffffffff
16680static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16681 struct scan_chan_info *chan,
16682 struct scan_chan_info *info, uint32_t cmd_flag)
16683{
16684 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16685 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16686 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16687
16688 mutex_lock(&hdd_ctx->chan_info_lock);
16689
16690 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16691 qdf_mem_zero(chan, sizeof(*chan));
16692
16693 chan->freq = info->freq;
16694 chan->noise_floor = info->noise_floor;
16695 chan->clock_freq = info->clock_freq;
16696 chan->cmd_flag = info->cmd_flag;
16697 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16698
16699 chan->rx_clear_count =
16700 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16701
16702 chan->tx_frame_count =
16703 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16704
16705 mutex_unlock(&hdd_ctx->chan_info_lock);
16706
16707}
16708#undef CNT_DIFF
16709#undef MAX_COUNT
16710
16711/**
16712 * wlan_hdd_chan_info_cb() - channel info callback
16713 * @chan_info: struct scan_chan_info
16714 *
16715 * Store channel info into HDD context
16716 *
16717 * Return: None.
16718 */
16719static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16720{
16721 hdd_context_t *hdd_ctx;
16722 struct scan_chan_info *chan;
16723 uint8_t idx;
16724
16725 ENTER();
16726
16727 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16728 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16729 hdd_err("hdd_ctx is invalid");
16730 return;
16731 }
16732
16733 if (!hdd_ctx->chan_info) {
16734 hdd_err("chan_info is NULL");
16735 return;
16736 }
16737
16738 chan = hdd_ctx->chan_info;
16739 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16740 if (chan[idx].freq == info->freq) {
16741 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16742 info->cmd_flag);
16743 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16744 chan[idx].cmd_flag, chan[idx].freq,
16745 chan[idx].noise_floor,
16746 chan[idx].cycle_count, chan[idx].rx_clear_count,
16747 chan[idx].clock_freq, chan[idx].cmd_flag,
16748 chan[idx].tx_frame_count, idx);
16749 if (chan[idx].freq == 0)
16750 break;
16751
16752 }
16753 }
16754
16755 EXIT();
16756}
16757
16758/**
16759 * wlan_hdd_init_chan_info() - init chan info in hdd context
16760 * @hdd_ctx: HDD context pointer
16761 *
16762 * Return: none
16763 */
16764void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16765{
16766 uint8_t num_2g, num_5g, index = 0;
16767
16768 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16769 hdd_info("SNR monitoring is disabled");
16770 return;
16771 }
16772
16773 hdd_ctx->chan_info =
16774 qdf_mem_malloc(sizeof(struct scan_chan_info)
16775 * QDF_MAX_NUM_CHAN);
16776 if (hdd_ctx->chan_info == NULL) {
16777 hdd_err("Failed to malloc for chan info");
16778 return;
16779 }
16780 mutex_init(&hdd_ctx->chan_info_lock);
16781
16782 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16783 for (; index < num_2g; index++) {
16784 hdd_ctx->chan_info[index].freq =
16785 hdd_channels_2_4_ghz[index].center_freq;
16786 }
16787
16788 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16789 for (; (index - num_2g) < num_5g; index++) {
16790 if (cds_is_dsrc_channel(
16791 hdd_channels_5_ghz[index - num_2g].center_freq))
16792 continue;
16793 hdd_ctx->chan_info[index].freq =
16794 hdd_channels_5_ghz[index - num_2g].center_freq;
16795 }
16796 sme_set_chan_info_callback(hdd_ctx->hHal,
16797 &wlan_hdd_chan_info_cb);
16798}
16799
16800/**
16801 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16802 * @hdd_ctx: hdd context pointer
16803 *
16804 * Return: none
16805 */
16806void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16807{
16808 struct scan_chan_info *chan;
16809
16810 chan = hdd_ctx->chan_info;
16811 hdd_ctx->chan_info = NULL;
16812 if (chan)
16813 qdf_mem_free(chan);
16814}
16815
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016816/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016817 * struct cfg80211_ops - cfg80211_ops
16818 *
16819 * @add_virtual_intf: Add virtual interface
16820 * @del_virtual_intf: Delete virtual interface
16821 * @change_virtual_intf: Change virtual interface
16822 * @change_station: Change station
16823 * @add_beacon: Add beacon in sap mode
16824 * @del_beacon: Delete beacon in sap mode
16825 * @set_beacon: Set beacon in sap mode
16826 * @start_ap: Start ap
16827 * @change_beacon: Change beacon
16828 * @stop_ap: Stop ap
16829 * @change_bss: Change bss
16830 * @add_key: Add key
16831 * @get_key: Get key
16832 * @del_key: Delete key
16833 * @set_default_key: Set default key
16834 * @set_channel: Set channel
16835 * @scan: Scan
16836 * @connect: Connect
16837 * @disconnect: Disconnect
16838 * @join_ibss = Join ibss
16839 * @leave_ibss = Leave ibss
16840 * @set_wiphy_params = Set wiphy params
16841 * @set_tx_power = Set tx power
16842 * @get_tx_power = get tx power
16843 * @remain_on_channel = Remain on channel
16844 * @cancel_remain_on_channel = Cancel remain on channel
16845 * @mgmt_tx = Tx management frame
16846 * @mgmt_tx_cancel_wait = Cancel management tx wait
16847 * @set_default_mgmt_key = Set default management key
16848 * @set_txq_params = Set tx queue parameters
16849 * @get_station = Get station
16850 * @set_power_mgmt = Set power management
16851 * @del_station = Delete station
16852 * @add_station = Add station
16853 * @set_pmksa = Set pmksa
16854 * @del_pmksa = Delete pmksa
16855 * @flush_pmksa = Flush pmksa
16856 * @update_ft_ies = Update FT IEs
16857 * @tdls_mgmt = Tdls management
16858 * @tdls_oper = Tdls operation
16859 * @set_rekey_data = Set rekey data
16860 * @sched_scan_start = Scheduled scan start
16861 * @sched_scan_stop = Scheduled scan stop
16862 * @resume = Resume wlan
16863 * @suspend = Suspend wlan
16864 * @set_mac_acl = Set mac acl
16865 * @testmode_cmd = Test mode command
16866 * @set_ap_chanwidth = Set AP channel bandwidth
16867 * @dump_survey = Dump survey
16868 * @key_mgmt_set_pmk = Set pmk key management
16869 */
16870static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16871 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16872 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16873 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16874 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016875 .start_ap = wlan_hdd_cfg80211_start_ap,
16876 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16877 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016878 .change_bss = wlan_hdd_cfg80211_change_bss,
16879 .add_key = wlan_hdd_cfg80211_add_key,
16880 .get_key = wlan_hdd_cfg80211_get_key,
16881 .del_key = wlan_hdd_cfg80211_del_key,
16882 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16883 .scan = wlan_hdd_cfg80211_scan,
16884 .connect = wlan_hdd_cfg80211_connect,
16885 .disconnect = wlan_hdd_cfg80211_disconnect,
16886 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16887 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16888 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16889 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16890 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16891 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16892 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16893 .mgmt_tx = wlan_hdd_mgmt_tx,
16894 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16895 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16896 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016897 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016898 .get_station = wlan_hdd_cfg80211_get_station,
16899 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16900 .del_station = wlan_hdd_cfg80211_del_station,
16901 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016902 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16903 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16904 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016905#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016906 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16907#endif
16908#ifdef FEATURE_WLAN_TDLS
16909 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16910 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16911#endif
16912#ifdef WLAN_FEATURE_GTK_OFFLOAD
16913 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16914#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16915#ifdef FEATURE_WLAN_SCAN_PNO
16916 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16917 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16918#endif /*FEATURE_WLAN_SCAN_PNO */
16919 .resume = wlan_hdd_cfg80211_resume_wlan,
16920 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16921 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16922#ifdef WLAN_NL80211_TESTMODE
16923 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16924#endif
16925#ifdef QCA_HT_2040_COEX
16926 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16927#endif
16928 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016929#ifdef CHANNEL_SWITCH_SUPPORTED
16930 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16931#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016932 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016933#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16934 defined(CFG80211_ABORT_SCAN)
16935 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16936#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016937};