blob: 044a42423c5da0d95350622270e968dc7f02191e [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
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304339 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004340 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4341 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4342 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004343 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4345 GFP_KERNEL);
4346
4347 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004348 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 return -EINVAL;
4350 }
4351
4352 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4353 ETH_ALEN, bssid) ||
4354 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4355 req_rsn_len, req_rsn_ie) ||
4356 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4357 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004358 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 goto nla_put_failure;
4360 }
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 if (roam_info_ptr->synchAuthStatus ==
4363 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004364 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004365 if (nla_put_u8(skb,
4366 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4367 hdd_err("nla put fail");
4368 goto nla_put_failure;
4369 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004370 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4371 /* if FT or CCKM connection: dont send replay counter */
4372 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4373 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4374 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4375 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4376 nla_put(skb,
4377 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4378 SIR_REPLAY_CTR_LEN,
4379 roam_info_ptr->replay_ctr)) {
4380 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004381 hdd_err("failed to send replay counter.");
4382 goto nla_put_failure;
4383 }
4384 if (nla_put(skb,
4385 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4386 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4387 nla_put(skb,
4388 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4389 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4390 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 goto nla_put_failure;
4392 }
4393 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004394 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4396 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004397 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 goto nla_put_failure;
4399 }
4400 }
4401
Jeff Johnson020db452016-06-29 14:37:26 -07004402 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004403 roam_info_ptr->subnet_change_status);
4404
4405 /*
4406 * Add subnet change status if subnet has changed
4407 * 0 = unchanged
4408 * 1 = changed
4409 * 2 = unknown
4410 */
4411 if (roam_info_ptr->subnet_change_status) {
4412 if (nla_put_u8(skb,
4413 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4414 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004415 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004416 goto nla_put_failure;
4417 }
4418 }
4419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004420 cfg80211_vendor_event(skb, GFP_KERNEL);
4421 return 0;
4422
4423nla_put_failure:
4424 kfree_skb(skb);
4425 return -EINVAL;
4426}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004427#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428
4429static const struct nla_policy
4430wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4431
4432 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4433 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4434 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304435 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304436 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4437 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004438 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4439 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4440 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4441 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4442 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304443 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444};
4445
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304447 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4448 *
4449 * @adapter: Pointer to HDD adapter
4450 * @ie_data: Pointer to Scan IEs buffer
4451 * @ie_len: Length of Scan IEs
4452 *
4453 * Return: 0 on success; error number otherwise
4454 */
4455static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4456 uint8_t *ie_data, uint8_t ie_len)
4457{
4458 hdd_scaninfo_t *scan_info = NULL;
4459 scan_info = &adapter->scan_info;
4460
4461 if (scan_info->default_scan_ies) {
4462 qdf_mem_free(scan_info->default_scan_ies);
4463 scan_info->default_scan_ies = NULL;
4464 }
4465
4466 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4467 if (!scan_info->default_scan_ies)
4468 return -ENOMEM;
4469
4470 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4471 scan_info->default_scan_ies_len = ie_len;
4472 return 0;
4473}
4474
4475/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4477 * vendor command
4478 *
4479 * @wiphy: wiphy device pointer
4480 * @wdev: wireless device pointer
4481 * @data: Vendor command data buffer
4482 * @data_len: Buffer length
4483 *
4484 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4485 *
4486 * Return: Error code.
4487 */
4488static int
4489__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4490 struct wireless_dev *wdev,
4491 const void *data,
4492 int data_len)
4493{
4494 struct net_device *dev = wdev->netdev;
4495 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4496 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4497 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4498 int ret_val = 0;
4499 u32 modulated_dtim;
4500 u16 stats_avg_factor;
4501 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304502 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004503 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004504 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304505 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304506 int attr_len;
4507 int access_policy = 0;
4508 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4509 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304510 uint16_t scan_ie_len = 0;
4511 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304512 struct sir_set_tx_rx_aggregation_size request;
4513 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004514 uint8_t retry, delay;
4515 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304516 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304517
Jeff Johnson1f61b612016-02-12 16:28:33 -08004518 ENTER_DEV(dev);
4519
Anurag Chouhan6d760662016-02-20 16:05:43 +05304520 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 hdd_err("Command not allowed in FTM mode");
4522 return -EPERM;
4523 }
4524
4525 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304526 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528
4529 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4530 data, data_len,
4531 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004532 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 return -EINVAL;
4534 }
4535
Krunal Sonie3531942016-04-12 17:43:53 -07004536 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4537 ftm_capab = nla_get_u32(tb[
4538 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4539 hdd_ctx->config->fine_time_meas_cap =
4540 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4541 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304542 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004543 hdd_ctx->config->fine_time_meas_cap);
4544 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4545 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4546 hdd_ctx->config->fine_time_meas_cap);
4547 }
4548
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004549 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4550 modulated_dtim = nla_get_u32(
4551 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4552
4553 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4554 adapter->sessionId,
4555 modulated_dtim);
4556
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304557 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 ret_val = -EPERM;
4559 }
4560
Kapil Gupta6213c012016-09-02 19:39:09 +05304561 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4562 qpower = nla_get_u8(
4563 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4564 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4565 ret_val = -EINVAL;
4566 }
4567
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4569 stats_avg_factor = nla_get_u16(
4570 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4571 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4572 adapter->sessionId,
4573 stats_avg_factor);
4574
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304575 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 ret_val = -EPERM;
4577 }
4578
4579
4580 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4581 guard_time = nla_get_u32(
4582 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4583 status = sme_configure_guard_time(hdd_ctx->hHal,
4584 adapter->sessionId,
4585 guard_time);
4586
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304587 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 ret_val = -EPERM;
4589 }
4590
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304591 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4592 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4593 attr_len = nla_len(
4594 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4595 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4596 hdd_info("Invalid value. attr_len %d",
4597 attr_len);
4598 return -EINVAL;
4599 }
4600
4601 nla_memcpy(&vendor_ie,
4602 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4603 attr_len);
4604 vendor_ie_present = true;
4605 hdd_info("Access policy vendor ie present.attr_len %d",
4606 attr_len);
4607 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4608 &vendor_ie[0], attr_len);
4609 }
4610
4611 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4612 access_policy = (int) nla_get_u32(
4613 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4614 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4615 (access_policy >
4616 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4617 hdd_info("Invalid value. access_policy %d",
4618 access_policy);
4619 return -EINVAL;
4620 }
4621 access_policy_present = true;
4622 hdd_info("Access policy present. access_policy %d",
4623 access_policy);
4624 }
4625
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004626 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4627 retry = nla_get_u8(tb[
4628 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4629 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4630 CFG_NON_AGG_RETRY_MAX : retry;
4631 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4632 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4633 retry, PDEV_CMD);
4634 }
4635
4636 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4637 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4638 retry = retry > CFG_AGG_RETRY_MAX ?
4639 CFG_AGG_RETRY_MAX : retry;
4640
4641 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4642 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4643 CFG_AGG_RETRY_MIN : retry;
4644 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4645 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4646 retry, PDEV_CMD);
4647 }
4648
4649 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4650 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4651 retry = retry > CFG_MGMT_RETRY_MAX ?
4652 CFG_MGMT_RETRY_MAX : retry;
4653 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4654 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4655 retry, PDEV_CMD);
4656 }
4657
4658 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4659 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4660 retry = retry > CFG_CTRL_RETRY_MAX ?
4661 CFG_CTRL_RETRY_MAX : retry;
4662 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4663 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4664 retry, PDEV_CMD);
4665 }
4666
4667 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4668 delay = nla_get_u8(tb[
4669 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4670 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4671 CFG_PROPAGATION_DELAY_MAX : delay;
4672 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4673 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4674 delay, PDEV_CMD);
4675 }
4676
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304677 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4678 tx_fail_count = nla_get_u32(
4679 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4680 if (tx_fail_count) {
4681 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4682 adapter->sessionId, tx_fail_count);
4683 if (QDF_STATUS_SUCCESS != status) {
4684 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4685 status);
4686 return -EINVAL;
4687 }
4688 }
4689 }
4690
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304691 if (vendor_ie_present && access_policy_present) {
4692 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4693 access_policy =
4694 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304695 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304696 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304697 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304698
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304699 hdd_info("calling sme_update_access_policy_vendor_ie");
4700 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4701 adapter->sessionId, &vendor_ie[0],
4702 access_policy);
4703 if (QDF_STATUS_SUCCESS != status) {
4704 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304705 return -EINVAL;
4706 }
4707 }
4708
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304709 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4710 set_value = nla_get_u8(
4711 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4712 hdd_info("set_value: %d", set_value);
4713 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4714 }
4715
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304716 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4717 scan_ie_len = nla_len(
4718 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4719 hdd_info("Received default scan IE of len %d session %d device mode %d",
4720 scan_ie_len, adapter->sessionId,
4721 adapter->device_mode);
4722 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4723 scan_ie = (uint8_t *) nla_data(tb
4724 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304725
4726 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4727 scan_ie_len))
4728 hdd_err("Failed to save default scan IEs");
4729
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304730 if (adapter->device_mode == QDF_STA_MODE) {
4731 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4732 adapter->sessionId, scan_ie,
4733 scan_ie_len);
4734 if (QDF_STATUS_SUCCESS != status)
4735 ret_val = -EPERM;
4736 }
4737 } else
4738 ret_val = -EPERM;
4739 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304740
4741 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4742 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4743 /* if one is specified, both must be specified */
4744 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4745 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4746 hdd_err("Both TX and RX MPDU Aggregation required");
4747 return -EINVAL;
4748 }
4749
4750 request.tx_aggregation_size = nla_get_u8(
4751 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4752 request.rx_aggregation_size = nla_get_u8(
4753 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4754 request.vdev_id = adapter->sessionId;
4755
4756 if (request.tx_aggregation_size >=
4757 CFG_TX_AGGREGATION_SIZE_MIN &&
4758 request.tx_aggregation_size <=
4759 CFG_TX_AGGREGATION_SIZE_MAX &&
4760 request.rx_aggregation_size >=
4761 CFG_RX_AGGREGATION_SIZE_MIN &&
4762 request.rx_aggregation_size <=
4763 CFG_RX_AGGREGATION_SIZE_MAX) {
4764 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4765 if (qdf_status != QDF_STATUS_SUCCESS) {
4766 hdd_err("failed to set aggr sizes err %d",
4767 qdf_status);
4768 ret_val = -EPERM;
4769 }
4770 } else {
4771 hdd_err("TX %d RX %d MPDU aggr size not in range",
4772 request.tx_aggregation_size,
4773 request.rx_aggregation_size);
4774 ret_val = -EINVAL;
4775 }
4776 }
4777
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304778 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4779 uint8_t ignore_assoc_disallowed;
4780
4781 ignore_assoc_disallowed
4782 = nla_get_u8(tb[
4783 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4784 hdd_info("Set ignore_assoc_disallowed value - %d",
4785 ignore_assoc_disallowed);
4786 if ((ignore_assoc_disallowed <
4787 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4788 (ignore_assoc_disallowed >
4789 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4790 return -EPERM;
4791
4792 sme_update_session_param(hdd_ctx->hHal,
4793 adapter->sessionId,
4794 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4795 ignore_assoc_disallowed);
4796 }
4797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 return ret_val;
4799}
4800
4801/**
4802 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4803 * vendor command
4804 *
4805 * @wiphy: wiphy device pointer
4806 * @wdev: wireless device pointer
4807 * @data: Vendor command data buffer
4808 * @data_len: Buffer length
4809 *
4810 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4811 *
4812 * Return: EOK or other error codes.
4813 */
4814static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4815 struct wireless_dev *wdev,
4816 const void *data,
4817 int data_len)
4818{
4819 int ret;
4820
4821 cds_ssr_protect(__func__);
4822 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4823 data, data_len);
4824 cds_ssr_unprotect(__func__);
4825
4826 return ret;
4827}
4828
4829static const struct
4830nla_policy
4831qca_wlan_vendor_wifi_logger_start_policy
4832[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4833 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4834 = {.type = NLA_U32 },
4835 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4836 = {.type = NLA_U32 },
4837 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4838 = {.type = NLA_U32 },
4839};
4840
4841/**
4842 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4843 * or disable the collection of packet statistics from the firmware
4844 * @wiphy: WIPHY structure pointer
4845 * @wdev: Wireless device structure pointer
4846 * @data: Pointer to the data received
4847 * @data_len: Length of the data received
4848 *
4849 * This function enables or disables the collection of packet statistics from
4850 * the firmware
4851 *
4852 * Return: 0 on success and errno on failure
4853 */
4854static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4855 struct wireless_dev *wdev,
4856 const void *data,
4857 int data_len)
4858{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304859 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4861 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4862 struct sir_wifi_start_log start_log;
4863
Jeff Johnson1f61b612016-02-12 16:28:33 -08004864 ENTER_DEV(wdev->netdev);
4865
Anurag Chouhan6d760662016-02-20 16:05:43 +05304866 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 hdd_err("Command not allowed in FTM mode");
4868 return -EPERM;
4869 }
4870
4871 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304872 if (status)
4873 return status;
4874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875
4876 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4877 data, data_len,
4878 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004879 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 return -EINVAL;
4881 }
4882
4883 /* Parse and fetch ring id */
4884 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004885 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886 return -EINVAL;
4887 }
4888 start_log.ring_id = nla_get_u32(
4889 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004890 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891
4892 /* Parse and fetch verbose level */
4893 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004894 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 return -EINVAL;
4896 }
4897 start_log.verbose_level = nla_get_u32(
4898 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004899 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900
4901 /* Parse and fetch flag */
4902 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004903 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 return -EINVAL;
4905 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304906 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304908 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004909
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304910 /* size is buff size which can be set using iwpriv command*/
4911 start_log.size = 0;
4912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4914
4915 if (start_log.ring_id == RING_ID_WAKELOCK) {
4916 /* Start/stop wakelock events */
4917 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4918 cds_set_wakelock_logging(true);
4919 else
4920 cds_set_wakelock_logging(false);
4921 return 0;
4922 }
4923
4924 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304925 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004926 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 status);
4928 return -EINVAL;
4929 }
4930 return 0;
4931}
4932
4933/**
4934 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4935 * or disable the collection of packet statistics from the firmware
4936 * @wiphy: WIPHY structure pointer
4937 * @wdev: Wireless device structure pointer
4938 * @data: Pointer to the data received
4939 * @data_len: Length of the data received
4940 *
4941 * This function is used to enable or disable the collection of packet
4942 * statistics from the firmware
4943 *
4944 * Return: 0 on success and errno on failure
4945 */
4946static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4947 struct wireless_dev *wdev,
4948 const void *data,
4949 int data_len)
4950{
4951 int ret = 0;
4952
4953 cds_ssr_protect(__func__);
4954 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4955 wdev, data, data_len);
4956 cds_ssr_unprotect(__func__);
4957
4958 return ret;
4959}
4960
4961static const struct
4962nla_policy
4963qca_wlan_vendor_wifi_logger_get_ring_data_policy
4964[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4965 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4966 = {.type = NLA_U32 },
4967};
4968
4969/**
4970 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4971 * @wiphy: WIPHY structure pointer
4972 * @wdev: Wireless device structure pointer
4973 * @data: Pointer to the data received
4974 * @data_len: Length of the data received
4975 *
4976 * This function is used to flush or retrieve the per packet statistics from
4977 * the driver
4978 *
4979 * Return: 0 on success and errno on failure
4980 */
4981static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4982 struct wireless_dev *wdev,
4983 const void *data,
4984 int data_len)
4985{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304986 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987 uint32_t ring_id;
4988 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4989 struct nlattr *tb
4990 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4991
Jeff Johnson1f61b612016-02-12 16:28:33 -08004992 ENTER_DEV(wdev->netdev);
4993
Anurag Chouhan6d760662016-02-20 16:05:43 +05304994 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004995 hdd_err("Command not allowed in FTM mode");
4996 return -EPERM;
4997 }
4998
4999 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305000 if (status)
5001 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002
5003 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5004 data, data_len,
5005 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005006 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 return -EINVAL;
5008 }
5009
5010 /* Parse and fetch ring id */
5011 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005012 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013 return -EINVAL;
5014 }
5015
5016 ring_id = nla_get_u32(
5017 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5018
5019 if (ring_id == RING_ID_PER_PACKET_STATS) {
5020 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07005021 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305022 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5023 /*
5024 * As part of DRIVER ring ID, flush both driver and fw logs.
5025 * For other Ring ID's driver doesn't have any rings to flush
5026 */
5027 hdd_notice("Bug report triggered by framework");
5028
5029 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5030 WLAN_LOG_INDICATOR_FRAMEWORK,
5031 WLAN_LOG_REASON_CODE_UNUSED,
5032 true, false);
5033 if (QDF_STATUS_SUCCESS != status) {
5034 hdd_err("Failed to trigger bug report");
5035 return -EINVAL;
5036 }
5037 } else {
5038 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5039 WLAN_LOG_INDICATOR_FRAMEWORK,
5040 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042 return 0;
5043}
5044
5045/**
5046 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5047 * @wiphy: WIPHY structure pointer
5048 * @wdev: Wireless device structure pointer
5049 * @data: Pointer to the data received
5050 * @data_len: Length of the data received
5051 *
5052 * This function is used to flush or retrieve the per packet statistics from
5053 * the driver
5054 *
5055 * Return: 0 on success and errno on failure
5056 */
5057static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5058 struct wireless_dev *wdev,
5059 const void *data,
5060 int data_len)
5061{
5062 int ret = 0;
5063
5064 cds_ssr_protect(__func__);
5065 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5066 wdev, data, data_len);
5067 cds_ssr_unprotect(__func__);
5068
5069 return ret;
5070}
5071
5072#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5073/**
5074 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5075 * @hdd_ctx: HDD context
5076 * @request_id: [input] request id
5077 * @pattern_id: [output] pattern id
5078 *
5079 * This function loops through request id to pattern id array
5080 * if the slot is available, store the request id and return pattern id
5081 * if entry exists, return the pattern id
5082 *
5083 * Return: 0 on success and errno on failure
5084 */
5085static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5086 uint32_t request_id,
5087 uint8_t *pattern_id)
5088{
5089 uint32_t i;
5090
5091 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5092 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5093 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5094 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5095 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5096 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5097 return 0;
5098 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5099 request_id) {
5100 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5101 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5102 return 0;
5103 }
5104 }
5105 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5106 return -EINVAL;
5107}
5108
5109/**
5110 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5111 * @hdd_ctx: HDD context
5112 * @request_id: [input] request id
5113 * @pattern_id: [output] pattern id
5114 *
5115 * This function loops through request id to pattern id array
5116 * reset request id to 0 (slot available again) and
5117 * return pattern id
5118 *
5119 * Return: 0 on success and errno on failure
5120 */
5121static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5122 uint32_t request_id,
5123 uint8_t *pattern_id)
5124{
5125 uint32_t i;
5126
5127 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5128 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5129 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5130 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5131 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5132 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5133 return 0;
5134 }
5135 }
5136 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5137 return -EINVAL;
5138}
5139
5140
5141/*
5142 * define short names for the global vendor params
5143 * used by __wlan_hdd_cfg80211_offloaded_packets()
5144 */
5145#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5146#define PARAM_REQUEST_ID \
5147 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5148#define PARAM_CONTROL \
5149 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5150#define PARAM_IP_PACKET \
5151 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5152#define PARAM_SRC_MAC_ADDR \
5153 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5154#define PARAM_DST_MAC_ADDR \
5155 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5156#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5157
5158/**
5159 * wlan_hdd_add_tx_ptrn() - add tx pattern
5160 * @adapter: adapter pointer
5161 * @hdd_ctx: hdd context
5162 * @tb: nl attributes
5163 *
5164 * This function reads the NL attributes and forms a AddTxPtrn message
5165 * posts it to SME.
5166 *
5167 */
5168static int
5169wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5170 struct nlattr **tb)
5171{
5172 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305173 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174 uint32_t request_id, ret, len;
5175 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305176 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177 uint16_t eth_type = htons(ETH_P_IP);
5178
5179 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005180 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 return -ENOTSUPP;
5182 }
5183
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305184 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005186 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187 return -ENOMEM;
5188 }
5189
5190 /* Parse and fetch request Id */
5191 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005192 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005193 goto fail;
5194 }
5195
5196 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5197 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005198 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 return -EINVAL;
5200 }
Jeff Johnson77848112016-06-29 14:52:06 -07005201 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202
5203 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005204 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 goto fail;
5206 }
5207 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005208 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 goto fail;
5212 }
5213
5214 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005215 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 goto fail;
5217 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005218 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305219 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005220 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005221 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222
Anurag Chouhanc5548422016-02-24 18:33:27 +05305223 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005224 &adapter->macAddressCurrent)) {
5225 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 goto fail;
5227 }
5228
5229 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005230 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 goto fail;
5232 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305233 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005234 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 MAC_ADDR_ARRAY(dst_addr.bytes));
5236
5237 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 goto fail;
5240 }
5241 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005242 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
5244 if (add_req->ucPtrnSize < 0 ||
5245 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5246 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005247 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248 add_req->ucPtrnSize);
5249 goto fail;
5250 }
5251
5252 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305253 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305254 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305255 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305256 QDF_MAC_ADDR_SIZE);
5257 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305258 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 len += 2;
5260
5261 /*
5262 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5263 * ------------------------------------------------------------
5264 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5265 * ------------------------------------------------------------
5266 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305267 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268 nla_data(tb[PARAM_IP_PACKET]),
5269 add_req->ucPtrnSize);
5270 add_req->ucPtrnSize += len;
5271
5272 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5273 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005274 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 goto fail;
5276 }
5277 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005278 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005279
5280 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305281 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005282 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283 goto fail;
5284 }
5285
5286 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305287 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005288 return 0;
5289
5290fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305291 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 return -EINVAL;
5293}
5294
5295/**
5296 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5297 * @adapter: adapter pointer
5298 * @hdd_ctx: hdd context
5299 * @tb: nl attributes
5300 *
5301 * This function reads the NL attributes and forms a DelTxPtrn message
5302 * posts it to SME.
5303 *
5304 */
5305static int
5306wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5307 struct nlattr **tb)
5308{
5309 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305310 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005311 uint32_t request_id, ret;
5312 uint8_t pattern_id = 0;
5313
5314 /* Parse and fetch request Id */
5315 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005316 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 return -EINVAL;
5318 }
5319 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5320 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005321 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 return -EINVAL;
5323 }
5324
5325 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5326 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005327 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 return -EINVAL;
5329 }
5330
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305331 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005333 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 return -ENOMEM;
5335 }
5336
Anurag Chouhanc5548422016-02-24 18:33:27 +05305337 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005338 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005340 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341 request_id, del_req->ucPtrnId);
5342
5343 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305344 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005345 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 goto fail;
5347 }
5348
5349 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305350 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 return 0;
5352
5353fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305354 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355 return -EINVAL;
5356}
5357
5358
5359/**
5360 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5361 * @wiphy: Pointer to wireless phy
5362 * @wdev: Pointer to wireless device
5363 * @data: Pointer to data
5364 * @data_len: Data length
5365 *
5366 * Return: 0 on success, negative errno on failure
5367 */
5368static int
5369__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5370 struct wireless_dev *wdev,
5371 const void *data,
5372 int data_len)
5373{
5374 struct net_device *dev = wdev->netdev;
5375 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5376 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5377 struct nlattr *tb[PARAM_MAX + 1];
5378 uint8_t control;
5379 int ret;
5380 static const struct nla_policy policy[PARAM_MAX + 1] = {
5381 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5382 [PARAM_CONTROL] = { .type = NLA_U32 },
5383 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305384 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305386 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 [PARAM_PERIOD] = { .type = NLA_U32 },
5388 };
5389
Jeff Johnson1f61b612016-02-12 16:28:33 -08005390 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391
Anurag Chouhan6d760662016-02-20 16:05:43 +05305392 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005393 hdd_err("Command not allowed in FTM mode");
5394 return -EPERM;
5395 }
5396
5397 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305398 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005399 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400
5401 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005402 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403 return -ENOTSUPP;
5404 }
5405
5406 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005407 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408 return -EINVAL;
5409 }
5410
5411 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005412 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 return -EINVAL;
5414 }
5415 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005416 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417
5418 if (control == WLAN_START_OFFLOADED_PACKETS)
5419 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005420 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005422
5423 hdd_err("Invalid control: %d", control);
5424
5425 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426}
5427
5428/*
5429 * done with short names for the global vendor params
5430 * used by __wlan_hdd_cfg80211_offloaded_packets()
5431 */
5432#undef PARAM_MAX
5433#undef PARAM_REQUEST_ID
5434#undef PARAM_CONTROL
5435#undef PARAM_IP_PACKET
5436#undef PARAM_SRC_MAC_ADDR
5437#undef PARAM_DST_MAC_ADDR
5438#undef PARAM_PERIOD
5439
5440/**
5441 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5442 * @wiphy: wiphy structure pointer
5443 * @wdev: Wireless device structure pointer
5444 * @data: Pointer to the data received
5445 * @data_len: Length of @data
5446 *
5447 * Return: 0 on success; errno on failure
5448 */
5449static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5450 struct wireless_dev *wdev,
5451 const void *data,
5452 int data_len)
5453{
5454 int ret = 0;
5455
5456 cds_ssr_protect(__func__);
5457 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5458 wdev, data, data_len);
5459 cds_ssr_unprotect(__func__);
5460
5461 return ret;
5462}
5463#endif
5464
5465/*
5466 * define short names for the global vendor params
5467 * used by __wlan_hdd_cfg80211_monitor_rssi()
5468 */
5469#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5470#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5471#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5472#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5473#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5474
5475/**
5476 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5477 * @wiphy: Pointer to wireless phy
5478 * @wdev: Pointer to wireless device
5479 * @data: Pointer to data
5480 * @data_len: Data length
5481 *
5482 * Return: 0 on success, negative errno on failure
5483 */
5484static int
5485__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5486 struct wireless_dev *wdev,
5487 const void *data,
5488 int data_len)
5489{
5490 struct net_device *dev = wdev->netdev;
5491 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5492 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5493 struct nlattr *tb[PARAM_MAX + 1];
5494 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305495 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 int ret;
5497 uint32_t control;
5498 static const struct nla_policy policy[PARAM_MAX + 1] = {
5499 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5500 [PARAM_CONTROL] = { .type = NLA_U32 },
5501 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5502 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5503 };
5504
Jeff Johnson1f61b612016-02-12 16:28:33 -08005505 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305507 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5508 hdd_err("invalid session id: %d", adapter->sessionId);
5509 return -EINVAL;
5510 }
5511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005512 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305513 if (ret)
5514 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515
5516 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005517 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 return -ENOTSUPP;
5519 }
5520
5521 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005522 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 return -EINVAL;
5524 }
5525
5526 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005527 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 return -EINVAL;
5529 }
5530
5531 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005532 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 return -EINVAL;
5534 }
5535
5536 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5537 req.session_id = adapter->sessionId;
5538 control = nla_get_u32(tb[PARAM_CONTROL]);
5539
5540 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5541 req.control = true;
5542 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005543 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 return -EINVAL;
5545 }
5546
5547 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005548 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 return -EINVAL;
5550 }
5551
5552 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5553 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5554
5555 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005556 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 req.min_rssi, req.max_rssi);
5558 return -EINVAL;
5559 }
Jeff Johnson77848112016-06-29 14:52:06 -07005560 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561 req.min_rssi, req.max_rssi);
5562
5563 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5564 req.control = false;
5565 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005566 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567 return -EINVAL;
5568 }
Jeff Johnson77848112016-06-29 14:52:06 -07005569 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 req.request_id, req.session_id, req.control);
5571
5572 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305573 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 return -EINVAL;
5576 }
5577
5578 return 0;
5579}
5580
5581/*
5582 * done with short names for the global vendor params
5583 * used by __wlan_hdd_cfg80211_monitor_rssi()
5584 */
5585#undef PARAM_MAX
5586#undef PARAM_CONTROL
5587#undef PARAM_REQUEST_ID
5588#undef PARAM_MAX_RSSI
5589#undef PARAM_MIN_RSSI
5590
5591/**
5592 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5593 * @wiphy: wiphy structure pointer
5594 * @wdev: Wireless device structure pointer
5595 * @data: Pointer to the data received
5596 * @data_len: Length of @data
5597 *
5598 * Return: 0 on success; errno on failure
5599 */
5600static int
5601wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5602 const void *data, int data_len)
5603{
5604 int ret;
5605
5606 cds_ssr_protect(__func__);
5607 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5608 cds_ssr_unprotect(__func__);
5609
5610 return ret;
5611}
5612
5613/**
5614 * hdd_rssi_threshold_breached() - rssi breached NL event
5615 * @hddctx: HDD context
5616 * @data: rssi breached event data
5617 *
5618 * This function reads the rssi breached event %data and fill in the skb with
5619 * NL attributes and send up the NL event.
5620 *
5621 * Return: none
5622 */
5623void hdd_rssi_threshold_breached(void *hddctx,
5624 struct rssi_breach_event *data)
5625{
5626 hdd_context_t *hdd_ctx = hddctx;
5627 struct sk_buff *skb;
5628
5629 ENTER();
5630
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305631 if (wlan_hdd_validate_context(hdd_ctx))
5632 return;
5633 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005634 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635 return;
5636 }
5637
5638 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5639 NULL,
5640 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5641 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5642 GFP_KERNEL);
5643
5644 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005645 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646 return;
5647 }
5648
Jeff Johnson77848112016-06-29 14:52:06 -07005649 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005651 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5653
5654 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5655 data->request_id) ||
5656 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5657 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5658 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5659 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005660 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661 goto fail;
5662 }
5663
5664 cfg80211_vendor_event(skb, GFP_KERNEL);
5665 return;
5666
5667fail:
5668 kfree_skb(skb);
5669 return;
5670}
5671
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305672static const struct nla_policy
5673ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5674 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5675};
5676
5677/**
5678 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5679 * @wiphy: Pointer to wireless phy
5680 * @wdev: Pointer to wireless device
5681 * @data: Pointer to data
5682 * @data_len: Length of @data
5683 *
5684 * Return: 0 on success, negative errno on failure
5685 */
5686static int
5687__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5688 struct wireless_dev *wdev,
5689 const void *data, int data_len)
5690{
5691 int status;
5692 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5693 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005694 struct net_device *dev = wdev->netdev;
5695 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305696
5697 ENTER_DEV(wdev->netdev);
5698
5699 status = wlan_hdd_validate_context(pHddCtx);
5700 if (0 != status)
5701 return status;
5702 if (!pHddCtx->config->fhostNSOffload) {
5703 hdd_err("ND Offload not supported");
5704 return -EINVAL;
5705 }
5706
5707 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5708 (struct nlattr *)data,
5709 data_len, ns_offload_set_policy)) {
5710 hdd_err("nla_parse failed");
5711 return -EINVAL;
5712 }
5713
5714 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5715 hdd_err("ND Offload flag attribute not present");
5716 return -EINVAL;
5717 }
5718
5719 pHddCtx->ns_offload_enable =
5720 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5721
Dustin Brownd8279d22016-09-07 14:52:57 -07005722 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305723 if (pHddCtx->ns_offload_enable)
5724 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5725 else
5726 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005727
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305728 return 0;
5729}
5730
5731/**
5732 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5733 * @wiphy: pointer to wireless wiphy structure.
5734 * @wdev: pointer to wireless_dev structure.
5735 * @data: Pointer to the data to be passed via vendor interface
5736 * @data_len:Length of the data to be passed
5737 *
5738 * Return: Return the Success or Failure code.
5739 */
5740static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5741 struct wireless_dev *wdev,
5742 const void *data, int data_len)
5743{
5744 int ret;
5745
5746 cds_ssr_protect(__func__);
5747 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5748 cds_ssr_unprotect(__func__);
5749
5750 return ret;
5751}
5752
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5754 * @wiphy: Pointer to wireless phy
5755 * @wdev: Pointer to wireless device
5756 * @data: Pointer to data
5757 * @data_len: Data length
5758 *
5759 * This function return the preferred frequency list generated by the policy
5760 * manager.
5761 *
5762 * Return: success or failure code
5763 */
5764static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5765 struct wireless_dev
5766 *wdev, const void *data,
5767 int data_len)
5768{
5769 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5770 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305771 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305772 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005773 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305774 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005775 enum cds_con_mode intf_mode;
5776 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5777 struct sk_buff *reply_skb;
5778
Jeff Johnson1f61b612016-02-12 16:28:33 -08005779 ENTER_DEV(wdev->netdev);
5780
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005781 ret = wlan_hdd_validate_context(hdd_ctx);
5782 if (ret)
5783 return -EINVAL;
5784
5785 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5786 data, data_len, NULL)) {
5787 hdd_err("Invalid ATTR");
5788 return -EINVAL;
5789 }
5790
5791 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5792 hdd_err("attr interface type failed");
5793 return -EINVAL;
5794 }
5795
5796 intf_mode = nla_get_u32(tb
5797 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5798
5799 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5800 hdd_err("Invalid interface type");
5801 return -EINVAL;
5802 }
5803
5804 hdd_debug("Userspace requested pref freq list");
5805
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305806 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5807 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305808 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 hdd_err("Get pcl failed");
5810 return -EINVAL;
5811 }
5812
5813 /* convert channel number to frequency */
5814 for (i = 0; i < pcl_len; i++) {
5815 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5816 freq_list[i] =
5817 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005818 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819 else
5820 freq_list[i] =
5821 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005822 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005823 }
5824
5825 /* send the freq_list back to supplicant */
5826 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5827 sizeof(u32) *
5828 pcl_len +
5829 NLMSG_HDRLEN);
5830
5831 if (!reply_skb) {
5832 hdd_err("Allocate reply_skb failed");
5833 return -EINVAL;
5834 }
5835
5836 if (nla_put_u32(reply_skb,
5837 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5838 intf_mode) ||
5839 nla_put(reply_skb,
5840 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5841 sizeof(uint32_t) * pcl_len,
5842 freq_list)) {
5843 hdd_err("nla put fail");
5844 kfree_skb(reply_skb);
5845 return -EINVAL;
5846 }
5847
5848 return cfg80211_vendor_cmd_reply(reply_skb);
5849}
5850
5851/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5852 * @wiphy: Pointer to wireless phy
5853 * @wdev: Pointer to wireless device
5854 * @data: Pointer to data
5855 * @data_len: Data length
5856 *
5857 * This function return the preferred frequency list generated by the policy
5858 * manager.
5859 *
5860 * Return: success or failure code
5861 */
5862static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5863 struct wireless_dev
5864 *wdev, const void *data,
5865 int data_len)
5866{
5867 int ret = 0;
5868
5869 cds_ssr_protect(__func__);
5870 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5871 data, data_len);
5872 cds_ssr_unprotect(__func__);
5873
5874 return ret;
5875}
5876
5877/**
5878 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5879 * @wiphy: Pointer to wireless phy
5880 * @wdev: Pointer to wireless device
5881 * @data: Pointer to data
5882 * @data_len: Data length
5883 *
5884 * Return: 0 on success, negative errno on failure
5885 */
5886static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5887 struct wireless_dev *wdev,
5888 const void *data,
5889 int data_len)
5890{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305891 struct net_device *ndev = wdev->netdev;
5892 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5894 int ret = 0;
5895 enum cds_con_mode intf_mode;
5896 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5897 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898
Jeff Johnson1f61b612016-02-12 16:28:33 -08005899 ENTER_DEV(ndev);
5900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005901 ret = wlan_hdd_validate_context(hdd_ctx);
5902 if (ret)
5903 return ret;
5904
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5906 data, data_len, NULL)) {
5907 hdd_err("Invalid ATTR");
5908 return -EINVAL;
5909 }
5910
5911 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5912 hdd_err("attr interface type failed");
5913 return -EINVAL;
5914 }
5915
5916 intf_mode = nla_get_u32(tb
5917 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5918
5919 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5920 hdd_err("Invalid interface type");
5921 return -EINVAL;
5922 }
5923
5924 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5925 hdd_err("attr probable freq failed");
5926 return -EINVAL;
5927 }
5928
5929 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5930 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5931
5932 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005933 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934 channel_hint, HW_MODE_20_MHZ)) {
5935 hdd_err("Set channel hint failed due to concurrency check");
5936 return -EINVAL;
5937 }
5938
Krunal Soni09e55032016-06-07 10:06:55 -07005939 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5940 hdd_warn("Remain On Channel Pending");
5941
Krunal Soni3091bcc2016-06-23 12:28:21 -07005942 ret = qdf_reset_connection_update();
5943 if (!QDF_IS_STATUS_SUCCESS(ret))
5944 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945
Krunal Soni3091bcc2016-06-23 12:28:21 -07005946 ret = cds_current_connections_update(adapter->sessionId,
5947 channel_hint,
5948 SIR_UPDATE_REASON_SET_OPER_CHAN);
5949 if (QDF_STATUS_E_FAILURE == ret) {
5950 /* return in the failure case */
5951 hdd_err("ERROR: connections update failed!!");
5952 return -EINVAL;
5953 }
5954
5955 if (QDF_STATUS_SUCCESS == ret) {
5956 /*
5957 * Success is the only case for which we expect hw mode
5958 * change to take place, hence we need to wait.
5959 * For any other return value it should be a pass
5960 * through
5961 */
5962 ret = qdf_wait_for_connection_update();
5963 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5964 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005965 return -EINVAL;
5966 }
5967
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005968 }
5969
5970 return 0;
5971}
5972
5973/**
5974 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5975 * @wiphy: Pointer to wireless phy
5976 * @wdev: Pointer to wireless device
5977 * @data: Pointer to data
5978 * @data_len: Data length
5979 *
5980 * Return: 0 on success, negative errno on failure
5981 */
5982static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5983 struct wireless_dev *wdev,
5984 const void *data,
5985 int data_len)
5986{
5987 int ret = 0;
5988
5989 cds_ssr_protect(__func__);
5990 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5991 data, data_len);
5992 cds_ssr_unprotect(__func__);
5993
5994 return ret;
5995}
5996
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305997static const struct
5998nla_policy
5999qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6000 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6001};
6002
6003/**
6004 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6005 * @wiphy: WIPHY structure pointer
6006 * @wdev: Wireless device structure pointer
6007 * @data: Pointer to the data received
6008 * @data_len: Length of the data received
6009 *
6010 * This function is used to get link properties like nss, rate flags and
6011 * operating frequency for the active connection with the given peer.
6012 *
6013 * Return: 0 on success and errno on failure
6014 */
6015static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6016 struct wireless_dev *wdev,
6017 const void *data,
6018 int data_len)
6019{
6020 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6021 struct net_device *dev = wdev->netdev;
6022 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6023 hdd_station_ctx_t *hdd_sta_ctx;
6024 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306025 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306026 uint32_t sta_id;
6027 struct sk_buff *reply_skb;
6028 uint32_t rate_flags = 0;
6029 uint8_t nss;
6030 uint8_t final_rate_flags = 0;
6031 uint32_t freq;
6032
Jeff Johnson1f61b612016-02-12 16:28:33 -08006033 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306034
Anurag Chouhan6d760662016-02-20 16:05:43 +05306035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306036 hdd_err("Command not allowed in FTM mode");
6037 return -EPERM;
6038 }
6039
6040 if (0 != wlan_hdd_validate_context(hdd_ctx))
6041 return -EINVAL;
6042
6043 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6044 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006045 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306046 return -EINVAL;
6047 }
6048
6049 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006050 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306051 adapter->device_mode);
6052 return -EINVAL;
6053 }
6054
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306055 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306056 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006057 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306058 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6059
Krunal Sonib4326f22016-03-10 13:05:51 -08006060 if (adapter->device_mode == QDF_STA_MODE ||
6061 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306062 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6063 if ((hdd_sta_ctx->conn_info.connState !=
6064 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306065 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306066 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006067 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306068 MAC_ADDR_ARRAY(peer_mac));
6069 return -EINVAL;
6070 }
6071
6072 nss = hdd_sta_ctx->conn_info.nss;
6073 freq = cds_chan_to_freq(
6074 hdd_sta_ctx->conn_info.operationChannel);
6075 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006076 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6077 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306078
6079 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6080 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306081 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306082 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306083 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306084 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306085 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306086 break;
6087 }
6088
6089 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006090 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306091 MAC_ADDR_ARRAY(peer_mac));
6092 return -EINVAL;
6093 }
6094
6095 nss = adapter->aStaInfo[sta_id].nss;
6096 freq = cds_chan_to_freq(
6097 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6098 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6099 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006100 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306101 MAC_ADDR_ARRAY(peer_mac));
6102 return -EINVAL;
6103 }
6104
6105 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6106 if (rate_flags & eHAL_TX_RATE_VHT80) {
6107 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006108#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306109 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006110#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306111 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6112 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006113#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306114 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006115#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306116 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6117 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6118 } else if (rate_flags &
6119 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6120 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006121#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306122 if (rate_flags & eHAL_TX_RATE_HT40)
6123 final_rate_flags |=
6124 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006125#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306126 }
6127
6128 if (rate_flags & eHAL_TX_RATE_SGI) {
6129 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6130 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6131 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6132 }
6133 }
6134
6135 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6136 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6137
6138 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006139 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306140 return -EINVAL;
6141 }
6142
6143 if (nla_put_u8(reply_skb,
6144 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6145 nss) ||
6146 nla_put_u8(reply_skb,
6147 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6148 final_rate_flags) ||
6149 nla_put_u32(reply_skb,
6150 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6151 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006152 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306153 kfree_skb(reply_skb);
6154 return -EINVAL;
6155 }
6156
6157 return cfg80211_vendor_cmd_reply(reply_skb);
6158}
6159
6160/**
6161 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6162 * properties.
6163 * @wiphy: WIPHY structure pointer
6164 * @wdev: Wireless device structure pointer
6165 * @data: Pointer to the data received
6166 * @data_len: Length of the data received
6167 *
6168 * This function is used to get link properties like nss, rate flags and
6169 * operating frequency for the active connection with the given peer.
6170 *
6171 * Return: 0 on success and errno on failure
6172 */
6173static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6174 struct wireless_dev *wdev,
6175 const void *data,
6176 int data_len)
6177{
6178 int ret = 0;
6179
6180 cds_ssr_protect(__func__);
6181 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6182 wdev, data, data_len);
6183 cds_ssr_unprotect(__func__);
6184
6185 return ret;
6186}
6187
Peng Xu278d0122015-09-24 16:34:17 -07006188static const struct
6189nla_policy
6190qca_wlan_vendor_ota_test_policy
6191[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6192 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6193};
6194
6195/**
6196 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6197 * @wiphy: Pointer to wireless phy
6198 * @wdev: Pointer to wireless device
6199 * @data: Pointer to data
6200 * @data_len: Data length
6201 *
6202 * Return: 0 on success, negative errno on failure
6203 */
6204static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6205 struct wireless_dev *wdev,
6206 const void *data,
6207 int data_len)
6208{
6209 struct net_device *dev = wdev->netdev;
6210 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6211 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6212 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6213 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6214 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306215 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006216 uint32_t current_roam_state;
6217
Jeff Johnson1f61b612016-02-12 16:28:33 -08006218 ENTER_DEV(dev);
6219
Anurag Chouhan6d760662016-02-20 16:05:43 +05306220 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006221 hdd_err("Command not allowed in FTM mode");
6222 return -EPERM;
6223 }
6224
6225 if (0 != wlan_hdd_validate_context(hdd_ctx))
6226 return -EINVAL;
6227
6228 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6229 data, data_len,
6230 qca_wlan_vendor_ota_test_policy)) {
6231 hdd_err("invalid attr");
6232 return -EINVAL;
6233 }
6234
6235 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6236 hdd_err("attr ota test failed");
6237 return -EINVAL;
6238 }
6239
6240 ota_enable = nla_get_u8(
6241 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6242
6243 hdd_info(" OTA test enable = %d", ota_enable);
6244 if (ota_enable != 1) {
6245 hdd_err("Invalid value, only enable test mode is supported!");
6246 return -EINVAL;
6247 }
6248
6249 current_roam_state =
6250 sme_get_current_roam_state(hal, adapter->sessionId);
6251 status = sme_stop_roaming(hal, adapter->sessionId,
6252 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306253 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006254 hdd_err("Enable/Disable roaming failed");
6255 return -EINVAL;
6256 }
6257
6258 status = sme_ps_enable_disable(hal, adapter->sessionId,
6259 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306260 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006261 hdd_err("Enable/Disable power save failed");
6262 /* restore previous roaming setting */
6263 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6264 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6265 status = sme_start_roaming(hal, adapter->sessionId,
6266 eCsrHddIssued);
6267 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6268 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6269 status = sme_stop_roaming(hal, adapter->sessionId,
6270 eCsrHddIssued);
6271
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306272 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006273 hdd_err("Restoring roaming state failed");
6274
6275 return -EINVAL;
6276 }
6277
6278
6279 return 0;
6280}
6281
6282/**
6283 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6284 * @wiphy: Pointer to wireless phy
6285 * @wdev: Pointer to wireless device
6286 * @data: Pointer to data
6287 * @data_len: Data length
6288 *
6289 * Return: 0 on success, negative errno on failure
6290 */
6291static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6292 struct wireless_dev *wdev,
6293 const void *data,
6294 int data_len)
6295{
6296 int ret = 0;
6297
6298 cds_ssr_protect(__func__);
6299 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6300 cds_ssr_unprotect(__func__);
6301
6302 return ret;
6303}
6304
Peng Xu4d67c8f2015-10-16 16:02:26 -07006305/**
6306 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6307 * @wiphy: Pointer to wireless phy
6308 * @wdev: Pointer to wireless device
6309 * @data: Pointer to data
6310 * @data_len: Data length
6311 *
6312 * Return: 0 on success, negative errno on failure
6313 */
6314static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6315 struct wireless_dev *wdev,
6316 const void *data,
6317 int data_len)
6318{
6319 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6320 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006321 hdd_adapter_t *adapter;
6322 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006323 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6324 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006325 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006326
Jeff Johnson1f61b612016-02-12 16:28:33 -08006327 ENTER_DEV(dev);
6328
Peng Xu4d67c8f2015-10-16 16:02:26 -07006329 ret = wlan_hdd_validate_context(hdd_ctx);
6330 if (ret)
6331 return ret;
6332
6333 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6334
6335 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6336 data, data_len, NULL)) {
6337 hdd_err("Invalid ATTR");
6338 return -EINVAL;
6339 }
6340
6341 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6342 hdd_err("attr tx power scale failed");
6343 return -EINVAL;
6344 }
6345
6346 scale_value = nla_get_u8(tb
6347 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6348
6349 if (scale_value > MAX_TXPOWER_SCALE) {
6350 hdd_err("Invalid tx power scale level");
6351 return -EINVAL;
6352 }
6353
Peng Xu62c8c432016-05-09 15:23:02 -07006354 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006355
Peng Xu62c8c432016-05-09 15:23:02 -07006356 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006357 hdd_err("Set tx power scale failed");
6358 return -EINVAL;
6359 }
6360
6361 return 0;
6362}
6363
6364/**
6365 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6366 * @wiphy: Pointer to wireless phy
6367 * @wdev: Pointer to wireless device
6368 * @data: Pointer to data
6369 * @data_len: Data length
6370 *
6371 * Return: 0 on success, negative errno on failure
6372 */
6373static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6374 struct wireless_dev *wdev,
6375 const void *data,
6376 int data_len)
6377{
Peng Xu62c8c432016-05-09 15:23:02 -07006378 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006379
6380 cds_ssr_protect(__func__);
6381 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6382 data, data_len);
6383 cds_ssr_unprotect(__func__);
6384
6385 return ret;
6386}
6387
6388/**
6389 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6390 * @wiphy: Pointer to wireless phy
6391 * @wdev: Pointer to wireless device
6392 * @data: Pointer to data
6393 * @data_len: Data length
6394 *
6395 * Return: 0 on success, negative errno on failure
6396 */
6397static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6398 struct wireless_dev *wdev,
6399 const void *data,
6400 int data_len)
6401{
6402 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6403 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006404 hdd_adapter_t *adapter;
6405 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006406 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6407 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006408 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006409
Jeff Johnson1f61b612016-02-12 16:28:33 -08006410 ENTER_DEV(dev);
6411
Peng Xu4d67c8f2015-10-16 16:02:26 -07006412 ret = wlan_hdd_validate_context(hdd_ctx);
6413 if (ret)
6414 return ret;
6415
6416 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6417
6418 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6419 data, data_len, NULL)) {
6420 hdd_err("Invalid ATTR");
6421 return -EINVAL;
6422 }
6423
6424 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6425 hdd_err("attr tx power decrease db value failed");
6426 return -EINVAL;
6427 }
6428
6429 scale_value = nla_get_u8(tb
6430 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6431
Peng Xu62c8c432016-05-09 15:23:02 -07006432 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6433 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006434
Peng Xu62c8c432016-05-09 15:23:02 -07006435 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006436 hdd_err("Set tx power decrease db failed");
6437 return -EINVAL;
6438 }
6439
6440 return 0;
6441}
6442
6443/**
6444 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6445 * @wiphy: Pointer to wireless phy
6446 * @wdev: Pointer to wireless device
6447 * @data: Pointer to data
6448 * @data_len: Data length
6449 *
6450 * Return: 0 on success, negative errno on failure
6451 */
6452static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6453 struct wireless_dev *wdev,
6454 const void *data,
6455 int data_len)
6456{
Peng Xu62c8c432016-05-09 15:23:02 -07006457 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006458
6459 cds_ssr_protect(__func__);
6460 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6461 data, data_len);
6462 cds_ssr_unprotect(__func__);
6463
6464 return ret;
6465}
Peng Xu8fdaa492016-06-22 10:20:47 -07006466
6467/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306468 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6469 * @wiphy: Pointer to wireless phy
6470 * @wdev: Pointer to wireless device
6471 * @data: Pointer to data
6472 * @data_len: Data length
6473 *
6474 * Processes the conditional channel switch request and invokes the helper
6475 * APIs to process the channel switch request.
6476 *
6477 * Return: 0 on success, negative errno on failure
6478 */
6479static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6480 struct wireless_dev *wdev,
6481 const void *data,
6482 int data_len)
6483{
6484 int ret;
6485 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6486 struct net_device *dev = wdev->netdev;
6487 hdd_adapter_t *adapter;
6488 struct nlattr
6489 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6490 uint32_t freq_len, i;
6491 uint32_t *freq;
6492 uint8_t chans[QDF_MAX_NUM_CHAN];
6493
6494 ENTER_DEV(dev);
6495
6496 ret = wlan_hdd_validate_context(hdd_ctx);
6497 if (ret)
6498 return ret;
6499
6500 if (!hdd_ctx->config->enableDFSMasterCap) {
6501 hdd_err("DFS master capability is not present in the driver");
6502 return -EINVAL;
6503 }
6504
6505 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6506 hdd_err("Command not allowed in FTM mode");
6507 return -EPERM;
6508 }
6509
6510 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6511 if (adapter->device_mode != QDF_SAP_MODE) {
6512 hdd_err("Invalid device mode %d", adapter->device_mode);
6513 return -EINVAL;
6514 }
6515
6516 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6517 data, data_len, NULL)) {
6518 hdd_err("Invalid ATTR");
6519 return -EINVAL;
6520 }
6521
6522 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6523 hdd_err("Frequency list is missing");
6524 return -EINVAL;
6525 }
6526
6527 freq_len = nla_len(
6528 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6529 sizeof(uint32_t);
6530
6531 if (freq_len > QDF_MAX_NUM_CHAN) {
6532 hdd_err("insufficient space to hold channels");
6533 return -ENOMEM;
6534 }
6535
6536 hdd_debug("freq_len=%d", freq_len);
6537
6538 freq = nla_data(
6539 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6540
6541
6542 for (i = 0; i < freq_len; i++) {
6543 if (freq[i] == 0)
6544 chans[i] = 0;
6545 else
6546 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6547
6548 hdd_debug("freq[%d]=%d", i, freq[i]);
6549 }
6550
6551 /*
6552 * The input frequency list from user space is designed to be a
6553 * priority based frequency list. This is only to accommodate any
6554 * future request. But, current requirement is only to perform CAC
6555 * on a single channel. So, the first entry from the list is picked.
6556 *
6557 * If channel is zero, any channel in the available outdoor regulatory
6558 * domain will be selected.
6559 */
6560 ret = wlan_hdd_request_pre_cac(chans[0]);
6561 if (ret) {
6562 hdd_err("pre cac request failed with reason:%d", ret);
6563 return ret;
6564 }
6565
6566 return 0;
6567}
6568
6569/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006570 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6571 * @wiphy: Pointer to wireless phy
6572 * @wdev: Pointer to wireless device
6573 * @data: Pointer to data
6574 * @data_len: Data length
6575 *
6576 * This function is to process the p2p listen offload start vendor
6577 * command. It parses the input parameters and invoke WMA API to
6578 * send the command to firmware.
6579 *
6580 * Return: 0 on success, negative errno on failure
6581 */
6582static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6583 struct wireless_dev *wdev,
6584 const void *data,
6585 int data_len)
6586{
6587 int ret;
6588 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6589 struct net_device *dev = wdev->netdev;
6590 hdd_adapter_t *adapter;
6591 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6592 struct sir_p2p_lo_start params;
6593 QDF_STATUS status;
6594
6595 ENTER_DEV(dev);
6596
6597 ret = wlan_hdd_validate_context(hdd_ctx);
6598 if (ret)
6599 return ret;
6600
6601 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6602 hdd_err("Command not allowed in FTM mode");
6603 return -EPERM;
6604 }
6605
6606 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6607 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6608 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6609 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6610 hdd_err("Invalid device mode %d", adapter->device_mode);
6611 return -EINVAL;
6612 }
6613
6614 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6615 data, data_len, NULL)) {
6616 hdd_err("Invalid ATTR");
6617 return -EINVAL;
6618 }
6619
6620 memset(&params, 0, sizeof(params));
6621
6622 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6623 params.ctl_flags = 1; /* set to default value */
6624 else
6625 params.ctl_flags = nla_get_u32(tb
6626 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6627
6628 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6629 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6630 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6631 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6632 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6633 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6634 hdd_err("Attribute parsing failed");
6635 return -EINVAL;
6636 }
6637
6638 params.vdev_id = adapter->sessionId;
6639 params.freq = nla_get_u32(tb
6640 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6641 if ((params.freq != 2412) && (params.freq != 2437) &&
6642 (params.freq != 2462)) {
6643 hdd_err("Invalid listening channel: %d", params.freq);
6644 return -EINVAL;
6645 }
6646
6647 params.period = nla_get_u32(tb
6648 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6649 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6650 hdd_err("Invalid period: %d", params.period);
6651 return -EINVAL;
6652 }
6653
6654 params.interval = nla_get_u32(tb
6655 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6656 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6657 hdd_err("Invalid interval: %d", params.interval);
6658 return -EINVAL;
6659 }
6660
6661 params.count = nla_get_u32(tb
6662 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006663 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006664 hdd_err("Invalid count: %d", params.count);
6665 return -EINVAL;
6666 }
6667
6668 params.device_types = nla_data(tb
6669 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6670 if (params.device_types == NULL) {
6671 hdd_err("Invalid device types");
6672 return -EINVAL;
6673 }
6674
6675 params.dev_types_len = nla_len(tb
6676 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6677 if (params.dev_types_len < 8) {
6678 hdd_err("Invalid device type length: %d", params.dev_types_len);
6679 return -EINVAL;
6680 }
6681
6682 params.probe_resp_tmplt = nla_data(tb
6683 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6684 if (params.probe_resp_tmplt == NULL) {
6685 hdd_err("Invalid probe response template");
6686 return -EINVAL;
6687 }
6688
6689 params.probe_resp_len = nla_len(tb
6690 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6691 if (params.probe_resp_len == 0) {
6692 hdd_err("Invalid probe resp template length: %d",
6693 params.probe_resp_len);
6694 return -EINVAL;
6695 }
6696
6697 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6698 params.freq, params.period, params.interval, params.count);
6699
6700 status = wma_p2p_lo_start(&params);
6701
6702 if (!QDF_IS_STATUS_SUCCESS(status)) {
6703 hdd_err("P2P LO start failed");
6704 return -EINVAL;
6705 }
6706
6707 return 0;
6708}
6709
6710
6711/**
6712 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6713 * @wiphy: Pointer to wireless phy
6714 * @wdev: Pointer to wireless device
6715 * @data: Pointer to data
6716 * @data_len: Data length
6717 *
6718 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6719 * to process p2p listen offload start vendor command.
6720 *
6721 * Return: 0 on success, negative errno on failure
6722 */
6723static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6724 struct wireless_dev *wdev,
6725 const void *data,
6726 int data_len)
6727{
6728 int ret = 0;
6729
6730 cds_ssr_protect(__func__);
6731 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6732 data, data_len);
6733 cds_ssr_unprotect(__func__);
6734
6735 return ret;
6736}
6737
6738/**
6739 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6740 * @wiphy: Pointer to wireless phy
6741 * @wdev: Pointer to wireless device
6742 * @data: Pointer to data
6743 * @data_len: Data length
6744 *
6745 * This function is to process the p2p listen offload stop vendor
6746 * command. It invokes WMA API to send command to firmware.
6747 *
6748 * Return: 0 on success, negative errno on failure
6749 */
6750static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6751 struct wireless_dev *wdev,
6752 const void *data,
6753 int data_len)
6754{
6755 QDF_STATUS status;
6756 hdd_adapter_t *adapter;
6757 struct net_device *dev = wdev->netdev;
6758
6759 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6760 hdd_err("Command not allowed in FTM mode");
6761 return -EPERM;
6762 }
6763
6764 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6765 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6766 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6767 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6768 hdd_err("Invalid device mode");
6769 return -EINVAL;
6770 }
6771
6772 status = wma_p2p_lo_stop(adapter->sessionId);
6773
6774 if (!QDF_IS_STATUS_SUCCESS(status)) {
6775 hdd_err("P2P LO stop failed");
6776 return -EINVAL;
6777 }
6778
6779 return 0;
6780}
6781
6782/**
6783 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6784 * @wiphy: Pointer to wireless phy
6785 * @wdev: Pointer to wireless device
6786 * @data: Pointer to data
6787 * @data_len: Data length
6788 *
6789 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6790 * to process p2p listen offload stop vendor command.
6791 *
6792 * Return: 0 on success, negative errno on failure
6793 */
6794static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6795 struct wireless_dev *wdev,
6796 const void *data,
6797 int data_len)
6798{
6799 int ret = 0;
6800
6801 cds_ssr_protect(__func__);
6802 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6803 data, data_len);
6804 cds_ssr_unprotect(__func__);
6805
6806 return ret;
6807}
6808
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306809/**
6810 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6811 * @wiphy: Pointer to wireless phy
6812 * @wdev: Pointer to wireless device
6813 * @data: Pointer to data
6814 * @data_len: Data length
6815 *
6816 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6817 * to process the conditional channel switch request.
6818 *
6819 * Return: 0 on success, negative errno on failure
6820 */
6821static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6822 struct wireless_dev *wdev,
6823 const void *data,
6824 int data_len)
6825{
6826 int ret;
6827
6828 cds_ssr_protect(__func__);
6829 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6830 data, data_len);
6831 cds_ssr_unprotect(__func__);
6832
6833 return ret;
6834}
6835
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306836/*
6837 * define short names for the global vendor params
6838 * used by __wlan_hdd_cfg80211_bpf_offload()
6839 */
6840#define BPF_INVALID \
6841 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6842#define BPF_SET_RESET \
6843 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6844#define BPF_VERSION \
6845 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6846#define BPF_FILTER_ID \
6847 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6848#define BPF_PACKET_SIZE \
6849 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6850#define BPF_CURRENT_OFFSET \
6851 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6852#define BPF_PROGRAM \
6853 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6854#define BPF_MAX \
6855 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006856
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306857static const struct nla_policy
6858wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6859 [BPF_SET_RESET] = {.type = NLA_U32},
6860 [BPF_VERSION] = {.type = NLA_U32},
6861 [BPF_FILTER_ID] = {.type = NLA_U32},
6862 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6863 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6864 [BPF_PROGRAM] = {.type = NLA_U8},
6865};
6866
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006867struct bpf_offload_priv {
6868 struct sir_bpf_get_offload bpf_get_offload;
6869};
6870
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306871/**
6872 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006873 * @context: opaque context originally passed to SME. HDD always passes
6874 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306875 * @bpf_get_offload: struct for get offload
6876 *
6877 * This function receives the response/data from the lower layer and
6878 * checks to see if the thread is still waiting then post the results to
6879 * upper layer, if the request has timed out then ignore.
6880 *
6881 * Return: None
6882 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006883static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006884 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306885{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006886 struct hdd_request *request;
6887 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306888
6889 ENTER();
6890
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006891 request = hdd_request_get(context);
6892 if (!request) {
6893 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306894 return;
6895 }
6896
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006897 priv = hdd_request_priv(request);
6898 priv->bpf_get_offload = *data;
6899 hdd_request_complete(request);
6900 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306901}
6902
6903/**
6904 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6905 * @hdd_context: hdd_context
6906 * @bpf_get_offload: struct for get offload
6907 *
6908 * Return: 0 on success, error number otherwise.
6909 */
6910static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6911 struct sir_bpf_get_offload *bpf_get_offload)
6912{
6913 struct sk_buff *skb;
6914 uint32_t nl_buf_len;
6915
6916 ENTER();
6917
6918 nl_buf_len = NLMSG_HDRLEN;
6919 nl_buf_len +=
6920 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6921 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6922
6923 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6924 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006925 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306926 return -ENOMEM;
6927 }
6928
Jeff Johnson77848112016-06-29 14:52:06 -07006929 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306930 bpf_get_offload->bpf_version,
6931 bpf_get_offload->max_bytes_for_bpf_inst);
6932
6933 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6934 bpf_get_offload->max_bytes_for_bpf_inst) ||
6935 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006936 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306937 goto nla_put_failure;
6938 }
6939
6940 cfg80211_vendor_cmd_reply(skb);
6941 EXIT();
6942 return 0;
6943
6944nla_put_failure:
6945 kfree_skb(skb);
6946 return -EINVAL;
6947}
6948
6949/**
6950 * hdd_get_bpf_offload - Get BPF offload Capabilities
6951 * @hdd_ctx: Hdd context
6952 *
6953 * Return: 0 on success, errno on failure
6954 */
6955static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6956{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306957 QDF_STATUS status;
6958 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006959 void *cookie;
6960 struct hdd_request *request;
6961 struct bpf_offload_priv *priv;
6962 static const struct hdd_request_params params = {
6963 .priv_size = sizeof(*priv),
6964 .timeout_ms = WLAN_WAIT_TIME_BPF,
6965 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306966
6967 ENTER();
6968
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006969 request = hdd_request_alloc(&params);
6970 if (!request) {
6971 hdd_err("Unable to allocate request");
6972 return -EINVAL;
6973 }
6974 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306975
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006976 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6977 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006978 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306979 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006980 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006981 ret = qdf_status_to_os_return(status);
6982 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006984 ret = hdd_request_wait_for_response(request);
6985 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006986 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006987 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306988 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006989 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306990 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006991 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306992 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006993 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306994
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006995cleanup:
6996 /*
6997 * either we never sent a request to SME, we sent a request to
6998 * SME and timed out, or we sent a request to SME, received a
6999 * response from SME, and posted the response to userspace.
7000 * regardless we are done with the request.
7001 */
7002 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307003 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007004
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307005 return ret;
7006}
7007
7008/**
7009 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7010 * @hdd_ctx: Hdd context
7011 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307012 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307013 *
7014 * Return: 0 on success; errno on failure
7015 */
7016static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7017 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307018 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307019{
7020 struct sir_bpf_set_offload *bpf_set_offload;
7021 QDF_STATUS status;
7022 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307023 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307024
7025 ENTER();
7026
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307027 if (adapter->device_mode == QDF_STA_MODE ||
7028 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7029 if (!hdd_conn_is_connected(
7030 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7031 hdd_err("Not in Connected state!");
7032 return -ENOTSUPP;
7033 }
7034 }
7035
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307036 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7037 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007038 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307039 return -ENOMEM;
7040 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307041
7042 /* Parse and fetch bpf packet size */
7043 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007044 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307045 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307046 goto fail;
7047 }
7048 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7049
7050 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007051 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307052 goto post_sme;
7053 }
7054
7055 /* Parse and fetch bpf program */
7056 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007057 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307058 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307059 goto fail;
7060 }
7061
7062 prog_len = nla_len(tb[BPF_PROGRAM]);
7063 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307064
7065 if (bpf_set_offload->program == NULL) {
7066 hdd_err("qdf_mem_malloc failed for bpf offload program");
7067 ret = -ENOMEM;
7068 goto fail;
7069 }
7070
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307071 bpf_set_offload->current_length = prog_len;
7072 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307073 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307074
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307075 hdd_info("BPF set instructions");
7076 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7077 bpf_set_offload->program, prog_len);
7078
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307079 /* Parse and fetch filter Id */
7080 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007081 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307082 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307083 goto fail;
7084 }
7085 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7086
7087 /* Parse and fetch current offset */
7088 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007089 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307090 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307091 goto fail;
7092 }
7093 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7094
7095post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007096 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 +05307097 bpf_set_offload->session_id,
7098 bpf_set_offload->version,
7099 bpf_set_offload->filter_id,
7100 bpf_set_offload->total_length,
7101 bpf_set_offload->current_length,
7102 bpf_set_offload->current_offset);
7103
7104 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7105 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007106 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307107 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108 goto fail;
7109 }
7110 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307111
7112fail:
7113 if (bpf_set_offload->current_length)
7114 qdf_mem_free(bpf_set_offload->program);
7115 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307116 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307117}
7118
7119/**
7120 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7121 * @wiphy: wiphy structure pointer
7122 * @wdev: Wireless device structure pointer
7123 * @data: Pointer to the data received
7124 * @data_len: Length of @data
7125 *
7126 * Return: 0 on success; errno on failure
7127 */
7128static int
7129__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7130 struct wireless_dev *wdev,
7131 const void *data, int data_len)
7132{
7133 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7134 struct net_device *dev = wdev->netdev;
7135 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7136 struct nlattr *tb[BPF_MAX + 1];
7137 int ret_val, packet_filter_subcmd;
7138
7139 ENTER();
7140
7141 ret_val = wlan_hdd_validate_context(hdd_ctx);
7142 if (ret_val)
7143 return ret_val;
7144
7145 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007146 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307147 return -EINVAL;
7148 }
7149
7150 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007151 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307152 return -ENOTSUPP;
7153 }
7154
7155 if (nla_parse(tb, BPF_MAX, data, data_len,
7156 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007157 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307158 return -EINVAL;
7159 }
7160
7161 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007162 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307163 return -EINVAL;
7164 }
7165
7166 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7167
7168 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7169 return hdd_get_bpf_offload(hdd_ctx);
7170 else
7171 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307172 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307173}
7174
7175/**
7176 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7177 * @wiphy: wiphy structure pointer
7178 * @wdev: Wireless device structure pointer
7179 * @data: Pointer to the data received
7180 * @data_len: Length of @data
7181 *
7182 * Return: 0 on success; errno on failure
7183 */
7184
7185static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7186 struct wireless_dev *wdev,
7187 const void *data, int data_len)
7188{
7189 int ret;
7190
7191 cds_ssr_protect(__func__);
7192 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7193 cds_ssr_unprotect(__func__);
7194
7195 return ret;
7196}
7197
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307198/**
7199 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7200 * @pre_cac_adapter: AP adapter used for pre cac
7201 * @status: Status (true or false)
7202 * @handle: Global handle
7203 *
7204 * Sets the status of pre cac i.e., whether the pre cac is active or not
7205 *
7206 * Return: Zero on success, non-zero on failure
7207 */
7208static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7209 bool status, tHalHandle handle)
7210{
7211 QDF_STATUS ret;
7212
7213 ret = wlan_sap_set_pre_cac_status(
7214 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7215 if (QDF_IS_STATUS_ERROR(ret))
7216 return -EINVAL;
7217
7218 return 0;
7219}
7220
7221/**
7222 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7223 * @ap_adapter: AP adapter
7224 * @chan_before_pre_cac: Channel
7225 *
7226 * Saves the channel which the AP was beaconing on before moving to the pre
7227 * cac channel. If radar is detected on the pre cac channel, this saved
7228 * channel will be used for AP operations.
7229 *
7230 * Return: Zero on success, non-zero on failure
7231 */
7232static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7233 uint8_t chan_before_pre_cac)
7234{
7235 QDF_STATUS ret;
7236
7237 ret = wlan_sap_set_chan_before_pre_cac(
7238 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7239 if (QDF_IS_STATUS_ERROR(ret))
7240 return -EINVAL;
7241
7242 return 0;
7243}
7244
7245/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307246 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7247 * are in nol list from provided channel list
7248 * @adapter: AP adapter
7249 * @channel_count: channel count
7250 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307251 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307252 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307253 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307254static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7255 uint32_t *channel_count,
7256 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307257{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307258 uint8_t i, j;
7259 uint32_t nol_len = 0;
7260 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7261 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7262 uint32_t chan_count;
7263 bool found;
7264 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307265
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307266 if (!hdd_ctx) {
7267 hdd_err("hdd ctx not found");
7268 *channel_count = 0;
7269 return;
7270 }
7271
7272 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7273 hdd_err("invalid channel count %d", *channel_count);
7274 return;
7275 }
7276
7277 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7278 if (nol_len == 0)
7279 return;
7280
7281 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7282 chan_count = *channel_count;
7283 qdf_mem_zero(channel_list, chan_count);
7284 *channel_count = 0;
7285
7286 for (i = 0 ; i < chan_count; i++) {
7287 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7288 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7289 continue;
7290 found = false;
7291 for (j = 0; j < nol_len; j++) {
7292 if (tmp_chan_list[i] == nol[j]) {
7293 found = true;
7294 hdd_notice("skipped channel %d due to nol",
7295 nol[j]);
7296 break;
7297 }
7298 }
7299 if (!found) {
7300 channel_list[*channel_count] = tmp_chan_list[i];
7301 *channel_count = *channel_count + 1;
7302 }
7303 }
7304}
7305
7306int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7307 uint32_t *channel_count,
7308 uint8_t *channel_list)
7309{
7310 tsap_Config_t *sap_config;
7311
7312 sap_config = &adapter->sessionCtx.ap.sapConfig;
7313
7314 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7315 sap_config->acs_cfg.ch_list_count);
7316 *channel_count = sap_config->acs_cfg.ch_list_count;
7317 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7318
7319 if (*channel_count == 0) {
7320 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307321 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307322 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307323
7324 return 0;
7325}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307326
7327/**
7328 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7329 * @hdd_ctx: HDD context
7330 * @ap_adapter: AP adapter
7331 * @channel: Channel requested by userspace
7332 * @pre_cac_chan: Pointer to the pre CAC channel
7333 *
7334 * Validates the channel provided by userspace. If user provided channel 0,
7335 * a valid outdoor channel must be selected from the regulatory channel.
7336 *
7337 * Return: Zero on success and non zero value on error
7338 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007339static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7340 hdd_adapter_t *ap_adapter,
7341 uint8_t channel,
7342 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307343{
7344 uint32_t i, j;
7345 QDF_STATUS status;
7346 int ret;
7347 uint8_t nol[QDF_MAX_NUM_CHAN];
7348 uint32_t nol_len = 0, weight_len = 0;
7349 bool found;
7350 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7351 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7352 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7353
7354 if (0 == channel) {
7355 /* Channel is not obtained from PCL because PCL may not have
7356 * the entire channel list. For example: if SAP is up on
7357 * channel 6 and PCL is queried for the next SAP interface,
7358 * if SCC is preferred, the PCL will contain only the channel
7359 * 6. But, we are in need of a DFS channel. So, going with the
7360 * first channel from the valid channel list.
7361 */
7362 status = cds_get_valid_chans(channel_list, &len);
7363 if (QDF_IS_STATUS_ERROR(status)) {
7364 hdd_err("Failed to get channel list");
7365 return -EINVAL;
7366 }
7367 cds_update_with_safe_channel_list(channel_list, &len,
7368 pcl_weights, weight_len);
7369 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7370 for (i = 0; i < len; i++) {
7371 found = false;
7372 for (j = 0; j < nol_len; j++) {
7373 if (channel_list[i] == nol[j]) {
7374 found = true;
7375 break;
7376 }
7377 }
7378 if (found)
7379 continue;
7380 if (CDS_IS_DFS_CH(channel_list[i])) {
7381 *pre_cac_chan = channel_list[i];
7382 break;
7383 }
7384 }
7385 if (*pre_cac_chan == 0) {
7386 hdd_err("unable to find outdoor channel");
7387 return -EINVAL;
7388 }
7389 } else {
7390 /* Only when driver selects a channel, check is done for
7391 * unnsafe and NOL channels. When user provides a fixed channel
7392 * the user is expected to take care of this.
7393 */
7394 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7395 !CDS_IS_DFS_CH(channel)) {
7396 hdd_err("Invalid channel for pre cac:%d", channel);
7397 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307398 }
Jeff Johnson68755312017-02-10 11:46:55 -08007399
7400 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307401 }
7402 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7403 return 0;
7404}
7405
7406/**
7407 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7408 * @channel: Channel option provided by userspace
7409 *
7410 * Sets the driver to the required hardware mode and start an adapater for
7411 * pre CAC which will mimic an AP.
7412 *
7413 * Return: Zero on success, non-zero value on error
7414 */
7415int wlan_hdd_request_pre_cac(uint8_t channel)
7416{
Krunal Sonib37bb352016-12-20 14:12:21 -08007417 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307418 hdd_context_t *hdd_ctx;
7419 int ret;
7420 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7421 hdd_ap_ctx_t *hdd_ap_ctx;
7422 QDF_STATUS status;
7423 struct wiphy *wiphy;
7424 struct net_device *dev;
7425 struct cfg80211_chan_def chandef;
7426 enum nl80211_channel_type channel_type;
7427 uint32_t freq;
7428 struct ieee80211_channel *chan;
7429 tHalHandle handle;
7430 bool val;
7431
7432 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7433 if (0 != wlan_hdd_validate_context(hdd_ctx))
7434 return -EINVAL;
7435
7436 if (cds_get_connection_count() > 1) {
7437 hdd_err("pre cac not allowed in concurrency");
7438 return -EINVAL;
7439 }
7440
7441 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7442 if (!ap_adapter) {
7443 hdd_err("unable to get SAP adapter");
7444 return -EINVAL;
7445 }
7446
7447 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7448 if (!handle) {
7449 hdd_err("Invalid handle");
7450 return -EINVAL;
7451 }
7452
7453 val = wlan_sap_is_pre_cac_active(handle);
7454 if (val) {
7455 hdd_err("pre cac is already in progress");
7456 return -EINVAL;
7457 }
7458
7459 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7460 if (!hdd_ap_ctx) {
7461 hdd_err("SAP context is NULL");
7462 return -EINVAL;
7463 }
7464
7465 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7466 hdd_err("SAP is already on DFS channel:%d",
7467 hdd_ap_ctx->operatingChannel);
7468 return -EINVAL;
7469 }
7470
7471 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7472 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7473 hdd_ap_ctx->operatingChannel);
7474 return -EINVAL;
7475 }
7476
Krunal Sonib37bb352016-12-20 14:12:21 -08007477 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7478 if (!mac_addr) {
7479 hdd_err("can't add virtual intf: Not getting valid mac addr");
7480 return -EINVAL;
7481 }
7482
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307483 hdd_info("channel:%d", channel);
7484
7485 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7486 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007487 if (ret != 0) {
7488 hdd_err("can't validate pre-cac channel");
7489 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307490 }
7491
7492 hdd_debug("starting pre cac SAP adapter");
7493
7494 /* Starting a SAP adapter:
7495 * Instead of opening an adapter, we could just do a SME open session
7496 * for AP type. But, start BSS would still need an adapter.
7497 * So, this option is not taken.
7498 *
7499 * hdd open adapter is going to register this precac interface with
7500 * user space. This interface though exposed to user space will be in
7501 * DOWN state. Consideration was done to avoid this registration to the
7502 * user space. But, as part of SAP operations multiple events are sent
7503 * to user space. Some of these events received from unregistered
7504 * interface was causing crashes. So, retaining the registration.
7505 *
7506 * So, this interface would remain registered and will remain in DOWN
7507 * state for the CAC duration. We will add notes in the feature
7508 * announcement to not use this temporary interface for any activity
7509 * from user space.
7510 */
7511 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007512 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307513 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307514 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007515 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307516 }
7517
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307518 /*
7519 * This interface is internally created by the driver. So, no interface
7520 * up comes for this interface from user space and hence starting
7521 * the adapter internally.
7522 */
7523 if (hdd_start_adapter(pre_cac_adapter)) {
7524 hdd_err("error starting the pre cac adapter");
7525 goto close_pre_cac_adapter;
7526 }
7527
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307528 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7529
7530 wiphy = hdd_ctx->wiphy;
7531 dev = pre_cac_adapter->dev;
7532
7533 /* Since this is only a dummy interface lets us use the IEs from the
7534 * other active SAP interface. In regular scenarios, these IEs would
7535 * come from the user space entity
7536 */
7537 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7538 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7539 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7540 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307541 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307542 }
7543 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7544 ap_adapter->sessionCtx.ap.beacon,
7545 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7546 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7547 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7548 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7549 ap_adapter->sessionCtx.ap.sapConfig.authType;
7550
7551 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7552 * to operate on the same bandwidth as that of the 2.4GHz operations.
7553 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7554 */
7555 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7556 case CH_WIDTH_20MHZ:
7557 channel_type = NL80211_CHAN_HT20;
7558 break;
7559 case CH_WIDTH_40MHZ:
7560 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7561 ap_adapter->sessionCtx.ap.sapConfig.channel)
7562 channel_type = NL80211_CHAN_HT40PLUS;
7563 else
7564 channel_type = NL80211_CHAN_HT40MINUS;
7565 break;
7566 default:
7567 channel_type = NL80211_CHAN_NO_HT;
7568 break;
7569 }
7570
7571 freq = cds_chan_to_freq(pre_cac_chan);
7572 chan = __ieee80211_get_channel(wiphy, freq);
7573 if (!chan) {
7574 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307575 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307576 }
7577
7578 cfg80211_chandef_create(&chandef, chan, channel_type);
7579
7580 hdd_debug("orig width:%d channel_type:%d freq:%d",
7581 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7582 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007583 /*
7584 * Doing update after opening and starting pre-cac adapter will make
7585 * sure that driver won't do hardware mode change if there are any
7586 * initial hick-ups or issues in pre-cac adapter's configuration.
7587 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7588 * connection update should result in DBS mode
7589 */
7590 status = cds_update_and_wait_for_connection_update(
7591 ap_adapter->sessionId,
7592 pre_cac_chan,
7593 SIR_UPDATE_REASON_PRE_CAC);
7594 if (QDF_IS_STATUS_ERROR(status)) {
7595 hdd_err("error in moving to DBS mode");
7596 goto stop_close_pre_cac_adapter;
7597 }
7598
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307599
7600 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7601 if (0 != ret) {
7602 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307603 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307604 }
7605
7606 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7607 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007608 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307609 if (QDF_IS_STATUS_ERROR(status)) {
7610 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307611 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307612 }
7613
7614 /*
7615 * The pre cac status is set here. But, it would not be reset explicitly
7616 * anywhere, since after the pre cac success/failure, the pre cac
7617 * adapter itself would be removed.
7618 */
7619 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7620 if (0 != ret) {
7621 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307622 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307623 }
7624
7625 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7626 hdd_ap_ctx->operatingChannel);
7627 if (0 != ret) {
7628 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307629 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307630 }
7631
7632 ap_adapter->pre_cac_chan = pre_cac_chan;
7633
7634 return 0;
7635
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307636stop_close_pre_cac_adapter:
7637 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307638 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7639 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307640close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307641 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007642release_intf_addr_and_return_failure:
7643 /*
7644 * Release the interface address as the adapter
7645 * failed to start, if you don't release then next
7646 * adapter which is trying to come wouldn't get valid
7647 * mac address. Remember we have limited pool of mac addresses
7648 */
7649 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307650 return -EINVAL;
7651}
7652
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307653static const struct nla_policy
7654wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7655 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7656};
7657
Agrawal Ashish65634612016-08-18 13:24:32 +05307658static const struct nla_policy
7659wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7660 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7661 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7662};
7663
7664/**
7665 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7666 * @wiphy: Pointer to wireless phy
7667 * @wdev: Pointer to wireless device
7668 * @data: Pointer to data
7669 * @data_len: Length of @data
7670 *
7671 * This function parses the incoming NL vendor command data attributes and
7672 * updates the SAP context about channel_hint and DFS mode.
7673 * If channel_hint is set, SAP will choose that channel
7674 * as operating channel.
7675 *
7676 * If DFS mode is enabled, driver will include DFS channels
7677 * in ACS else driver will skip DFS channels.
7678 *
7679 * Return: 0 on success, negative errno on failure
7680 */
7681static int
7682__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7683 struct wireless_dev *wdev,
7684 const void *data, int data_len)
7685{
7686 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7687 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7688 int ret;
7689 struct acs_dfs_policy *acs_policy;
7690 int mode = DFS_MODE_NONE;
7691 int channel_hint = 0;
7692
7693 ENTER_DEV(wdev->netdev);
7694
7695 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7696 hdd_err("Command not allowed in FTM mode");
7697 return -EINVAL;
7698 }
7699
7700 ret = wlan_hdd_validate_context(hdd_ctx);
7701 if (0 != ret)
7702 return ret;
7703
7704 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7705 data, data_len,
7706 wlan_hdd_set_acs_dfs_config_policy)) {
7707 hdd_err("invalid attr");
7708 return -EINVAL;
7709 }
7710
7711 acs_policy = &hdd_ctx->acs_policy;
7712 /*
7713 * SCM sends this attribute to restrict SAP from choosing
7714 * DFS channels from ACS.
7715 */
7716 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7717 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7718
7719 if (!IS_DFS_MODE_VALID(mode)) {
7720 hdd_err("attr acs dfs mode is not valid");
7721 return -EINVAL;
7722 }
7723 acs_policy->acs_dfs_mode = mode;
7724
7725 /*
7726 * SCM sends this attribute to provide an active channel,
7727 * to skip redundant ACS between drivers, and save driver start up time
7728 */
7729 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7730 channel_hint = nla_get_u8(
7731 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7732
7733 if (!IS_CHANNEL_VALID(channel_hint)) {
7734 hdd_err("acs channel is not valid");
7735 return -EINVAL;
7736 }
7737 acs_policy->acs_channel = channel_hint;
7738
7739 return 0;
7740}
7741
7742/**
7743 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7744 * @wiphy: wiphy structure pointer
7745 * @wdev: Wireless device structure pointer
7746 * @data: Pointer to the data received
7747 * @data_len: Length of @data
7748 *
7749 * This function parses the incoming NL vendor command data attributes and
7750 * updates the SAP context about channel_hint and DFS mode.
7751 *
7752 * Return: 0 on success; errno on failure
7753 */
7754static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7755 struct wireless_dev *wdev,
7756 const void *data, int data_len)
7757{
7758 int ret;
7759
7760 cds_ssr_protect(__func__);
7761 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7762 cds_ssr_unprotect(__func__);
7763
7764 return ret;
7765}
7766
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307767/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307768 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7769 * @mode : cfg80211 dfs mode
7770 *
7771 * Return: return csr sta roam dfs mode else return NONE
7772 */
7773static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7774 enum dfs_mode mode)
7775{
7776 switch (mode) {
7777 case DFS_MODE_ENABLE:
7778 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7779 break;
7780 case DFS_MODE_DISABLE:
7781 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7782 break;
7783 case DFS_MODE_DEPRIORITIZE:
7784 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7785 break;
7786 default:
7787 hdd_err("STA Roam policy dfs mode is NONE");
7788 return CSR_STA_ROAM_POLICY_NONE;
7789 }
7790}
7791
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307792/*
7793 * hdd_get_sap_operating_band: Get current operating channel
7794 * for sap.
7795 * @hdd_ctx: hdd context
7796 *
7797 * Return : Corresponding band for SAP operating channel
7798 */
7799uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7800{
7801 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7802 QDF_STATUS status;
7803 hdd_adapter_t *adapter;
7804 uint8_t operating_channel = 0;
7805 uint8_t sap_operating_band = 0;
7806 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7807 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7808 adapter = adapter_node->pAdapter;
7809
7810 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7811 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7812 &next);
7813 adapter_node = next;
7814 continue;
7815 }
7816 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7817 if (IS_24G_CH(operating_channel))
7818 sap_operating_band = eCSR_BAND_24;
7819 else if (IS_5G_CH(operating_channel))
7820 sap_operating_band = eCSR_BAND_5G;
7821 else
7822 sap_operating_band = eCSR_BAND_ALL;
7823 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7824 &next);
bings373b99b2017-01-23 10:35:08 +08007825 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307826 }
7827 return sap_operating_band;
7828}
7829
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307830static const struct nla_policy
7831wlan_hdd_set_sta_roam_config_policy[
7832QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7833 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7834 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7835};
7836
7837/**
7838 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7839 * for station connection or roaming.
7840 * @wiphy: Pointer to wireless phy
7841 * @wdev: Pointer to wireless device
7842 * @data: Pointer to data
7843 * @data_len: Length of @data
7844 *
7845 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7846 * channels needs to be skipped in scanning or not.
7847 * If dfs_mode is disabled, driver will not scan DFS channels.
7848 * If skip_unsafe_channels is set, driver will skip unsafe channels
7849 * in Scanning.
7850 *
7851 * Return: 0 on success, negative errno on failure
7852 */
7853static int
7854__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7855 struct wireless_dev *wdev,
7856 const void *data, int data_len)
7857{
7858 struct net_device *dev = wdev->netdev;
7859 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7860 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7861 struct nlattr *tb[
7862 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7863 int ret;
7864 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7865 enum dfs_mode mode = DFS_MODE_NONE;
7866 bool skip_unsafe_channels = false;
7867 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307868 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307869
7870 ENTER_DEV(dev);
7871
7872 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7873 hdd_err("Command not allowed in FTM mode");
7874 return -EINVAL;
7875 }
7876
7877 ret = wlan_hdd_validate_context(hdd_ctx);
7878 if (0 != ret)
7879 return ret;
7880 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7881 data, data_len,
7882 wlan_hdd_set_sta_roam_config_policy)) {
7883 hdd_err("invalid attr");
7884 return -EINVAL;
7885 }
7886 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7887 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7888 if (!IS_DFS_MODE_VALID(mode)) {
7889 hdd_err("attr sta roam dfs mode policy is not valid");
7890 return -EINVAL;
7891 }
7892
7893 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7894
7895 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7896 skip_unsafe_channels = nla_get_u8(
7897 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307898 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307899 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307900 skip_unsafe_channels, adapter->sessionId,
7901 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307902
7903 if (!QDF_IS_STATUS_SUCCESS(status)) {
7904 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7905 return -EINVAL;
7906 }
7907 return 0;
7908}
7909
7910/**
7911 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7912 * connection and roaming for station.
7913 * @wiphy: wiphy structure pointer
7914 * @wdev: Wireless device structure pointer
7915 * @data: Pointer to the data received
7916 * @data_len: Length of @data
7917 *
7918 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7919 * channels needs to be skipped in scanning or not.
7920 * If dfs_mode is disabled, driver will not scan DFS channels.
7921 * If skip_unsafe_channels is set, driver will skip unsafe channels
7922 * in Scanning.
7923 * Return: 0 on success; errno on failure
7924 */
7925static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7926 struct wireless_dev *wdev,
7927 const void *data, int data_len)
7928{
7929 int ret;
7930
7931 cds_ssr_protect(__func__);
7932 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7933 cds_ssr_unprotect(__func__);
7934
7935 return ret;
7936}
7937
Agrawal Ashish467dde42016-09-08 18:44:22 +05307938#ifdef FEATURE_WLAN_CH_AVOID
7939/**
7940 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7941 * is on unsafe channel.
7942 * @wiphy: wiphy structure pointer
7943 * @wdev: Wireless device structure pointer
7944 * @data: Pointer to the data received
7945 * @data_len: Length of @data
7946 *
7947 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7948 * on any of unsafe channels.
7949 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7950 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7951 *
7952 * Return: 0 on success; errno on failure
7953 */
7954static int
7955__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7956 struct wireless_dev *wdev,
7957 const void *data, int data_len)
7958{
7959 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7960 int ret;
7961 uint16_t unsafe_channel_count;
7962 int unsafe_channel_index;
7963 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7964
7965 ENTER_DEV(wdev->netdev);
7966
7967 if (!qdf_ctx) {
7968 cds_err("qdf_ctx is NULL");
7969 return -EINVAL;
7970 }
7971
7972 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7973 hdd_err("Command not allowed in FTM mode");
7974 return -EINVAL;
7975 }
7976
7977 ret = wlan_hdd_validate_context(hdd_ctx);
7978 if (0 != ret)
7979 return ret;
7980 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7981 &(hdd_ctx->unsafe_channel_count),
7982 sizeof(hdd_ctx->unsafe_channel_list));
7983
7984 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7985 (uint16_t)NUM_CHANNELS);
7986 for (unsafe_channel_index = 0;
7987 unsafe_channel_index < unsafe_channel_count;
7988 unsafe_channel_index++) {
7989 hdd_info("Channel %d is not safe",
7990 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7991 }
7992 hdd_unsafe_channel_restart_sap(hdd_ctx);
7993 return 0;
7994}
7995
7996/**
7997 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7998 * is on unsafe channel.
7999 * @wiphy: wiphy structure pointer
8000 * @wdev: Wireless device structure pointer
8001 * @data: Pointer to the data received
8002 * @data_len: Length of @data
8003 *
8004 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8005 * on any of unsafe channels.
8006 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8007 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8008 *
8009 * Return: 0 on success; errno on failure
8010 */
8011static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8012 struct wireless_dev *wdev,
8013 const void *data, int data_len)
8014{
8015 int ret;
8016
8017 cds_ssr_protect(__func__);
8018 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8019 cds_ssr_unprotect(__func__);
8020
8021 return ret;
8022}
8023
8024#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308025/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308026 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8027 * SAP is on unsafe channel.
8028 * @wiphy: wiphy structure pointer
8029 * @wdev: Wireless device structure pointer
8030 * @data: Pointer to the data received
8031 * @data_len: Length of @data
8032 *
8033 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8034 * driver.
8035 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8036 * will initiate restart of sap.
8037 *
8038 * Return: 0 on success; errno on failure
8039 */
8040static int
8041__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8042 struct wireless_dev *wdev,
8043 const void *data, int data_len)
8044{
8045 struct net_device *ndev = wdev->netdev;
8046 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8047 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8048 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8049 uint8_t config_channel = 0;
8050 hdd_ap_ctx_t *ap_ctx;
8051 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308052 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308053
8054 ENTER();
8055
8056 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008057 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308058 return -EINVAL;
8059 }
8060
8061 ret = wlan_hdd_validate_context(hdd_ctx);
8062 if (0 != ret)
8063 return -EINVAL;
8064
8065 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8066 data, data_len,
8067 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008068 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308069 return -EINVAL;
8070 }
8071
8072 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8073 if (!test_bit(SOFTAP_BSS_STARTED,
8074 &hostapd_adapter->event_flags)) {
8075 hdd_err("SAP is not started yet. Restart sap will be invalid");
8076 return -EINVAL;
8077 }
8078
8079 config_channel =
8080 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8081
8082 if (!((IS_24G_CH(config_channel)) ||
8083 (IS_5G_CH(config_channel)))) {
8084 hdd_err("Channel %d is not valid to restart SAP",
8085 config_channel);
8086 return -ENOTSUPP;
8087 }
8088
8089 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8090 ap_ctx->sapConfig.channel = config_channel;
8091 ap_ctx->sapConfig.ch_params.ch_width =
8092 ap_ctx->sapConfig.ch_width_orig;
8093
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008094 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308095 ap_ctx->sapConfig.sec_ch,
8096 &ap_ctx->sapConfig.ch_params);
8097
8098 cds_restart_sap(hostapd_adapter);
8099 }
8100
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308101 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8102 uint32_t freq_len, i;
8103 uint32_t *freq;
8104 uint8_t chans[QDF_MAX_NUM_CHAN];
8105
8106 hdd_debug("setting mandatory freq/chan list");
8107
8108 freq_len = nla_len(
8109 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8110 sizeof(uint32_t);
8111
8112 if (freq_len > QDF_MAX_NUM_CHAN) {
8113 hdd_err("insufficient space to hold channels");
8114 return -ENOMEM;
8115 }
8116
8117 freq = nla_data(
8118 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8119
8120 hdd_debug("freq_len=%d", freq_len);
8121
8122 for (i = 0; i < freq_len; i++) {
8123 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8124 hdd_debug("freq[%d]=%d", i, freq[i]);
8125 }
8126
8127 status = cds_set_sap_mandatory_channels(chans, freq_len);
8128 if (QDF_IS_STATUS_ERROR(status))
8129 return -EINVAL;
8130 }
8131
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308132 return 0;
8133}
8134
8135/**
8136 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8137 * @wiphy: wiphy structure pointer
8138 * @wdev: Wireless device structure pointer
8139 * @data: Pointer to the data received
8140 * @data_len: Length of @data
8141 *
8142 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8143 * driver.
8144 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8145 * will initiate restart of sap.
8146 *
8147 * Return: 0 on success; errno on failure
8148 */
8149static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8150 struct wireless_dev *wdev,
8151 const void *data, int data_len)
8152{
8153 int ret;
8154
8155 cds_ssr_protect(__func__);
8156 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8157 wdev, data, data_len);
8158 cds_ssr_unprotect(__func__);
8159
8160 return ret;
8161}
8162
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308163#undef BPF_INVALID
8164#undef BPF_SET_RESET
8165#undef BPF_VERSION
8166#undef BPF_ID
8167#undef BPF_PACKET_SIZE
8168#undef BPF_CURRENT_OFFSET
8169#undef BPF_PROGRAM
8170#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308171
8172/**
8173 * define short names for the global vendor params
8174 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8175 */
8176#define PARAM_TOTAL_CMD_EVENT_WAKE \
8177 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8178#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8179 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8180#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8181 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8182#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8183 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8184#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8185 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8186#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8187 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8188#define PARAM_TOTAL_RX_DATA_WAKE \
8189 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8190#define PARAM_RX_UNICAST_CNT \
8191 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8192#define PARAM_RX_MULTICAST_CNT \
8193 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8194#define PARAM_RX_BROADCAST_CNT \
8195 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8196#define PARAM_ICMP_PKT \
8197 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8198#define PARAM_ICMP6_PKT \
8199 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8200#define PARAM_ICMP6_RA \
8201 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8202#define PARAM_ICMP6_NA \
8203 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8204#define PARAM_ICMP6_NS \
8205 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8206#define PARAM_ICMP4_RX_MULTICAST_CNT \
8207 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8208#define PARAM_ICMP6_RX_MULTICAST_CNT \
8209 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8210#define PARAM_OTHER_RX_MULTICAST_CNT \
8211 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308212#define PARAM_RSSI_BREACH_CNT \
8213 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8214#define PARAM_LOW_RSSI_CNT \
8215 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8216#define PARAM_GSCAN_CNT \
8217 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8218#define PARAM_PNO_COMPLETE_CNT \
8219 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8220#define PARAM_PNO_MATCH_CNT \
8221 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8222
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308223
8224
8225/**
8226 * hdd_send_wakelock_stats() - API to send wakelock stats
8227 * @ctx: context to be passed to callback
8228 * @data: data passed to callback
8229 *
8230 * This function is used to send wake lock stats to HAL layer
8231 *
8232 * Return: 0 on success, error number otherwise.
8233 */
8234static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8235 const struct sir_wake_lock_stats *data)
8236{
8237 struct sk_buff *skb;
8238 uint32_t nl_buf_len;
8239 uint32_t total_rx_data_wake, rx_multicast_cnt;
8240 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308241 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308242
8243 ENTER();
8244
8245 nl_buf_len = NLMSG_HDRLEN;
8246 nl_buf_len +=
8247 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8248 (NLMSG_HDRLEN + sizeof(uint32_t));
8249
8250 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8251
8252 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008253 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308254 return -ENOMEM;
8255 }
8256
Jeff Johnson64943bd2016-08-23 13:14:06 -07008257 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308258 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008259 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008261 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308262 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008263 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308264 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008265 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308266 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008267 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308268 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008269 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308270 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008271 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8272 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308273 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308274 hdd_info("wow_rssi_breach_wake_up_count %d",
8275 data->wow_rssi_breach_wake_up_count);
8276 hdd_info("wow_low_rssi_wake_up_count %d",
8277 data->wow_low_rssi_wake_up_count);
8278 hdd_info("wow_gscan_wake_up_count %d",
8279 data->wow_gscan_wake_up_count);
8280 hdd_info("wow_pno_complete_wake_up_count %d",
8281 data->wow_pno_complete_wake_up_count);
8282 hdd_info("wow_pno_match_wake_up_count %d",
8283 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308284
8285 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308286 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308288 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308289 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308290
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308291 rx_multicast_cnt =
8292 data->wow_ipv4_mcast_wake_up_count +
8293 ipv6_rx_multicast_addr_cnt;
8294
8295 total_rx_data_wake =
8296 data->wow_ucast_wake_up_count +
8297 data->wow_bcast_wake_up_count +
8298 rx_multicast_cnt;
8299
8300 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8301 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8302 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8303 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8304 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8305 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8306 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8307 total_rx_data_wake) ||
8308 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8309 data->wow_ucast_wake_up_count) ||
8310 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8311 rx_multicast_cnt) ||
8312 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8313 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308314 nla_put_u32(skb, PARAM_ICMP_PKT,
8315 data->wow_icmpv4_count) ||
8316 nla_put_u32(skb, PARAM_ICMP6_PKT,
8317 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308318 nla_put_u32(skb, PARAM_ICMP6_RA,
8319 data->wow_ipv6_mcast_ra_stats) ||
8320 nla_put_u32(skb, PARAM_ICMP6_NA,
8321 data->wow_ipv6_mcast_na_stats) ||
8322 nla_put_u32(skb, PARAM_ICMP6_NS,
8323 data->wow_ipv6_mcast_ns_stats) ||
8324 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8325 data->wow_ipv4_mcast_wake_up_count) ||
8326 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8327 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308328 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8329 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8330 data->wow_rssi_breach_wake_up_count) ||
8331 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8332 data->wow_low_rssi_wake_up_count) ||
8333 nla_put_u32(skb, PARAM_GSCAN_CNT,
8334 data->wow_gscan_wake_up_count) ||
8335 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8336 data->wow_pno_complete_wake_up_count) ||
8337 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8338 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008339 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308340 goto nla_put_failure;
8341 }
8342
8343 cfg80211_vendor_cmd_reply(skb);
8344
8345 EXIT();
8346 return 0;
8347
8348nla_put_failure:
8349 kfree_skb(skb);
8350 return -EINVAL;
8351}
8352
8353/**
8354 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8355 * @wiphy: wiphy pointer
8356 * @wdev: pointer to struct wireless_dev
8357 * @data: pointer to incoming NL vendor data
8358 * @data_len: length of @data
8359 *
8360 * This function parses the incoming NL vendor command data attributes and
8361 * invokes the SME Api and blocks on a completion variable.
8362 * WMA copies required data and invokes callback
8363 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8364 *
8365 * Return: 0 on success; error number otherwise.
8366 */
8367static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8368 struct wireless_dev *wdev,
8369 const void *data,
8370 int data_len)
8371{
8372 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8373 int status, ret;
8374 struct sir_wake_lock_stats wake_lock_stats;
8375 QDF_STATUS qdf_status;
8376
8377 ENTER();
8378
8379 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008380 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308381 return -EINVAL;
8382 }
8383
8384 status = wlan_hdd_validate_context(hdd_ctx);
8385 if (0 != status)
8386 return -EINVAL;
8387
8388 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8389 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008390 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308391 return -EINVAL;
8392 }
8393
8394 ret = hdd_send_wakelock_stats(hdd_ctx,
8395 &wake_lock_stats);
8396 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008397 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308398
8399 EXIT();
8400 return ret;
8401}
8402
8403/**
8404 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8405 * @wiphy: wiphy pointer
8406 * @wdev: pointer to struct wireless_dev
8407 * @data: pointer to incoming NL vendor data
8408 * @data_len: length of @data
8409 *
8410 * This function parses the incoming NL vendor command data attributes and
8411 * invokes the SME Api and blocks on a completion variable.
8412 * WMA copies required data and invokes callback
8413 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8414 *
8415 * Return: 0 on success; error number otherwise.
8416 */
8417static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8418 struct wireless_dev *wdev,
8419 const void *data, int data_len)
8420{
8421 int ret;
8422
8423 cds_ssr_protect(__func__);
8424 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8425 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008426 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308427
8428 return ret;
8429}
8430
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308431/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308432 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8433 * @wiphy: wiphy structure pointer
8434 * @wdev: Wireless device structure pointer
8435 * @data: Pointer to the data received
8436 * @data_len: Length of @data
8437 *
8438 * This function reads wmi max bus size and fill in the skb with
8439 * NL attributes and send up the NL event.
8440 * Return: 0 on success; errno on failure
8441 */
8442static int
8443__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8444 struct wireless_dev *wdev,
8445 const void *data, int data_len)
8446{
8447 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8448 int ret_val;
8449 struct sk_buff *skb;
8450 uint32_t nl_buf_len;
8451
8452 ENTER();
8453
8454 ret_val = wlan_hdd_validate_context(hdd_ctx);
8455 if (ret_val)
8456 return ret_val;
8457
8458 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8459 hdd_err("Command not allowed in FTM mode");
8460 return -EINVAL;
8461 }
8462
8463 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8464
8465 nl_buf_len = NLMSG_HDRLEN;
8466 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8467
8468 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8469 if (!skb) {
8470 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8471 return -ENOMEM;
8472 }
8473
8474 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8475 hdd_ctx->wmi_max_len)) {
8476 hdd_err("nla put failure");
8477 goto nla_put_failure;
8478 }
8479
8480 cfg80211_vendor_cmd_reply(skb);
8481
8482 EXIT();
8483
8484 return 0;
8485
8486nla_put_failure:
8487 kfree_skb(skb);
8488 return -EINVAL;
8489}
8490
8491/**
8492 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8493 * @wiphy: wiphy structure pointer
8494 * @wdev: Wireless device structure pointer
8495 * @data: Pointer to the data received
8496 * @data_len: Length of @data
8497 *
8498 * Return: 0 on success; errno on failure
8499 */
8500static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8501 struct wireless_dev *wdev,
8502 const void *data, int data_len)
8503{
8504 int ret;
8505
8506 cds_ssr_protect(__func__);
8507 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8508 cds_ssr_unprotect(__func__);
8509
8510 return ret;
8511}
8512
8513/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308514 *__wlan_hdd_cfg80211_setband() - set band
8515 * @wiphy: Pointer to wireless phy
8516 * @wdev: Pointer to wireless device
8517 * @data: Pointer to data
8518 * @data_len: Length of @data
8519 *
8520 * Return: 0 on success, negative errno on failure
8521 */
8522static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8523 struct wireless_dev *wdev,
8524 const void *data, int data_len)
8525{
8526 struct net_device *dev = wdev->netdev;
8527 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8528 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8529 int ret;
8530 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8531 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8532
8533 ENTER();
8534
8535 ret = wlan_hdd_validate_context(hdd_ctx);
8536 if (ret)
8537 return ret;
8538
8539 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8540 hdd_err(FL("Invalid ATTR"));
8541 return -EINVAL;
8542 }
8543
8544 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8545 hdd_err(FL("attr SETBAND_VALUE failed"));
8546 return -EINVAL;
8547 }
8548
8549 ret = hdd_set_band(dev,
8550 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8551
8552 EXIT();
8553 return ret;
8554}
8555
8556/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308557 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8558 * @adapter: hdd adapter
8559 * @channel: channel number
8560 *
8561 * return: QDF status based on success or failure
8562 */
8563static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8564 int channel, int chan_bw)
8565{
8566 if (QDF_STATUS_SUCCESS !=
8567 wlan_hdd_validate_operation_channel(adapter, channel))
8568 return QDF_STATUS_E_FAILURE;
8569 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8570 channel,
8571 PHY_SINGLE_CHANNEL_CENTERED))) {
8572 hdd_notice("channel %d is in nol", channel);
8573 return -EINVAL;
8574 }
8575
8576 if ((wlansap_is_channel_leaking_in_nol(
8577 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8578 channel, chan_bw))) {
8579 hdd_notice("channel %d is leaking in nol", channel);
8580 return -EINVAL;
8581 }
8582
8583 return 0;
8584
8585}
8586
Kapil Gupta8878ad92017-02-13 11:56:04 +05308587static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8588 tsap_Config_t *sap_config,
8589 struct hdd_vendor_chan_info *channel_list)
8590{
8591 sap_config->channel = channel_list->pri_ch;
8592
8593 sap_config->ch_params.center_freq_seg0 =
8594 channel_list->vht_seg0_center_ch;
8595 sap_config->ch_params.center_freq_seg1 =
8596 channel_list->vht_seg1_center_ch;
8597
8598 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8599 sap_config->ch_params.ch_width = channel_list->chan_width;
8600 if (sap_config->channel >= 36)
8601 sap_config->ch_width_orig =
8602 hdd_ctx->config->vhtChannelWidth;
8603 else
8604 sap_config->ch_width_orig =
8605 hdd_ctx->config->nChannelBondingMode24GHz ?
8606 eHT_CHANNEL_WIDTH_40MHZ :
8607 eHT_CHANNEL_WIDTH_20MHZ;
8608
8609 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8610 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8611 sap_config->acs_cfg.vht_seg0_center_ch =
8612 channel_list->vht_seg0_center_ch;
8613 sap_config->acs_cfg.vht_seg1_center_ch =
8614 channel_list->vht_seg1_center_ch;
8615 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8616}
8617
8618static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8619 uint8_t channel_cnt,
8620 struct hdd_vendor_chan_info *channel_list)
8621{
8622 tsap_Config_t *sap_config;
8623 hdd_ap_ctx_t *hdd_ap_ctx;
8624 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8625 QDF_STATUS status = QDF_STATUS_SUCCESS;
8626
8627 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8628 sap_config = &adapter->sessionCtx.ap.sapConfig;
8629
8630 if (QDF_TIMER_STATE_RUNNING ==
8631 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8632 ap.vendor_acs_timer)) {
8633 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8634 }
8635
8636 if (channel_list && channel_list->pri_ch == 0) {
8637 /* Check mode, set default channel */
8638 channel_list->pri_ch = 6;
8639 /*
8640 * sap_select_default_oper_chan(hdd_ctx->hHal,
8641 * sap_config->acs_cfg.hw_mode);
8642 */
8643 }
8644
8645 switch (reason) {
8646 /* SAP init case */
8647 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8648 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8649 /* Update Hostapd */
8650 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8651 break;
8652
8653 /* DFS detected on current channel */
8654 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8655 wlan_sap_update_next_channel(
8656 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8657 channel_list->pri_ch,
8658 channel_list->chan_width);
8659 status = sme_update_new_channel_event(
8660 WLAN_HDD_GET_HAL_CTX(adapter),
8661 adapter->sessionId);
8662 break;
8663
8664 /* LTE coex event on current channel */
8665 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8666 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8667 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8668 hdd_ap_ctx->sapConfig.ch_width_orig =
8669 channel_list->chan_width;
8670 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8671 break;
8672
8673 default:
8674 hdd_info("invalid reason for timer invoke");
8675 }
8676 qdf_mem_free(channel_list);
8677 EXIT();
8678 return status;
8679}
8680
8681/**
8682 * Define short name for vendor channel set config
8683 */
8684#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8685#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8686#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8687#define SET_CHAN_PRIMARY_CHANNEL \
8688 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8689#define SET_CHAN_SECONDARY_CHANNEL \
8690 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8691#define SET_CHAN_SEG0_CENTER_CHANNEL \
8692 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8693#define SET_CHAN_SEG1_CENTER_CHANNEL \
8694 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8695#define SET_CHAN_CHANNEL_WIDTH \
8696 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8697#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8698
8699/**
8700 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8701 * @channel_list: pointer to hdd_vendor_chan_info
8702 * @reason: channel change reason
8703 * @channel_cnt: channel count
8704 * @data: data
8705 * @data_len: data len
8706 *
8707 * Return: 0 on success, negative errno on failure
8708 */
8709static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8710 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8711 const void *data, int data_len)
8712{
8713 int rem, i = 0;
8714 struct nlattr *tb[SET_CHAN_MAX + 1];
8715 struct nlattr *tb2[SET_CHAN_MAX + 1];
8716 struct nlattr *curr_attr;
8717 struct hdd_vendor_chan_info *channel_list;
8718
8719 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8720 hdd_err("Invalid ATTR");
8721 return -EINVAL;
8722 }
8723
8724 if (tb[SET_CHAN_REASON])
8725 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8726
8727 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8728 *channel_cnt = nla_get_u8(tb[
8729 SET_CHAN_CHANNEL_COUNT]);
8730 hdd_info("channel count %d", *channel_cnt);
8731 }
8732
8733 if (!(*channel_cnt)) {
8734 hdd_err("channel count is %d", *channel_cnt);
8735 return -EINVAL;
8736 }
8737
8738 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8739 (*channel_cnt));
8740
8741 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8742 if (nla_parse(tb2,
8743 SET_CHAN_MAX,
8744 nla_data(curr_attr), nla_len(curr_attr),
8745 NULL)) {
8746 hdd_err("nla_parse failed");
8747 return -EINVAL;
8748 }
8749 /* Parse and Fetch allowed SSID list*/
8750 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8751 channel_list[i].pri_ch =
8752 nla_get_u8(
8753 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8754 }
8755 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8756 channel_list[i].ht_sec_ch =
8757 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8758 }
8759 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8760 channel_list[i].vht_seg0_center_ch =
8761 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8762 }
8763 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8764 channel_list[i].vht_seg1_center_ch =
8765 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8766 }
8767 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8768 channel_list[i].chan_width =
8769 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8770 }
8771 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8772 i, channel_list[i].pri_ch,
8773 channel_list[i].ht_sec_ch,
8774 channel_list[i].vht_seg0_center_ch,
8775 channel_list[i].vht_seg1_center_ch,
8776 channel_list[i].chan_width);
8777 i++;
8778 if (i > *channel_cnt)
8779 break;
8780 }
8781 *chan_list_ptr = channel_list;
8782
8783 return 0;
8784}
8785
8786/**
8787 * Undef short names for vendor set channel configuration
8788 */
8789#undef SET_CHAN_REASON
8790#undef SET_CHAN_CHANNEL_COUNT
8791#undef SET_CHAN_CHAN_LIST
8792#undef SET_CHAN_PRIMARY_CHANNEL
8793#undef SET_CHAN_SECONDARY_CHANNEL
8794#undef SET_CHAN_SEG0_CENTER_CHANNEL
8795#undef SET_CHAN_SEG1_CENTER_CHANNEL
8796#undef SET_CHAN_CHANNEL_WIDTH
8797#undef SET_CHAN_MAX
8798
8799/**
8800 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8801 * @wiphy: Pointer to wireless phy
8802 * @wdev: Pointer to wireless device
8803 * @data: Pointer to data
8804 * @data_len: Length of @data
8805 *
8806 * Return: 0 on success, negative errno on failure
8807 */
8808static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8809 struct wireless_dev *wdev,
8810 const void *data, int data_len)
8811{
8812 int ret_val;
8813 QDF_STATUS qdf_status;
8814 uint8_t channel_cnt = 0, reason = -1;
8815 struct hdd_vendor_chan_info *channel_list = NULL;
8816 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8817 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8818
8819 ENTER();
8820
8821 ret_val = wlan_hdd_validate_context(hdd_ctx);
8822 if (ret_val)
8823 return ret_val;
8824
8825 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8826 hdd_err("Command not allowed in FTM mode");
8827 return -EINVAL;
8828 }
8829
8830 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8831 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8832 else {
8833 hdd_err("already timeout happened for acs");
8834 return -EINVAL;
8835 }
8836
8837 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8838 &channel_cnt, data, data_len);
8839 if (ret_val)
8840 return ret_val;
8841
8842 /* Validate channel to be set */
8843 while (channel_cnt && channel_list) {
8844 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8845 channel_list->pri_ch,
8846 channel_list->chan_width);
8847 if (qdf_status == QDF_STATUS_SUCCESS)
8848 break;
8849 channel_cnt--;
8850 channel_list++;
8851 }
8852 if ((channel_cnt <= 0) || !channel_list) {
8853 hdd_err("no available channel/chanlist %p", channel_list);
8854 return -EINVAL;
8855 }
8856
8857 qdf_status = hdd_update_acs_channel(adapter, reason,
8858 channel_cnt, channel_list);
8859 return qdf_status_to_os_return(qdf_status);
8860}
8861
8862/**
8863 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8864 * @wiphy: Pointer to wireless phy
8865 * @wdev: Pointer to wireless device
8866 * @data: Pointer to data
8867 * @data_len: Length of @data
8868 *
8869 * Return: 0 on success, negative errno on failure
8870 */
8871static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8872 struct wireless_dev *wdev,
8873 const void *data, int data_len)
8874{
8875 int ret;
8876
8877 cds_ssr_protect(__func__);
8878 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8879 data_len);
8880 cds_ssr_protect(__func__);
8881
8882 return ret;
8883}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308884
8885/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308886 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8887 * @wiphy: wiphy structure pointer
8888 * @wdev: Wireless device structure pointer
8889 * @data: Pointer to the data received
8890 * @data_len: Length of @data
8891 *
8892 * Return: 0 on success; errno on failure
8893 */
8894static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8895 struct wireless_dev *wdev,
8896 const void *data, int data_len)
8897{
8898 int ret;
8899
8900 cds_ssr_protect(__func__);
8901 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8902 cds_ssr_unprotect(__func__);
8903
8904 return ret;
8905}
8906
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008907/**
8908 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8909 * @nl80211_value: Vendor command attribute value
8910 * @wmi_value: Pointer to return converted WMI return value
8911 *
8912 * Convert NL80211 vendor command value for SAR limit set to WMI value
8913 * Return: 0 on success, -1 on invalid value
8914 */
8915static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8916 u32 *wmi_value)
8917{
8918 int ret = 0;
8919
8920 switch (nl80211_value) {
8921 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8922 *wmi_value = WMI_SAR_FEATURE_OFF;
8923 break;
8924 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8925 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8926 break;
8927 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8928 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8929 break;
8930 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8931 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8932 break;
8933 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8934 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8935 break;
8936 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8937 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8938 break;
8939 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8940 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8941 break;
8942 default:
8943 ret = -1;
8944 }
8945 return ret;
8946}
8947
8948/**
8949 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8950 * @nl80211_value: Vendor command attribute value
8951 * @wmi_value: Pointer to return converted WMI return value
8952 *
8953 * Convert NL80211 vendor command value for SAR BAND to WMI value
8954 * Return: 0 on success, -1 on invalid value
8955 */
8956static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8957{
8958 int ret = 0;
8959
8960 switch (nl80211_value) {
8961 case NL80211_BAND_2GHZ:
8962 *wmi_value = WMI_SAR_2G_ID;
8963 break;
8964 case NL80211_BAND_5GHZ:
8965 *wmi_value = WMI_SAR_5G_ID;
8966 break;
8967 default:
8968 ret = -1;
8969 }
8970 return ret;
8971}
8972
8973/**
8974 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8975 * @nl80211_value: Vendor command attribute value
8976 * @wmi_value: Pointer to return converted WMI return value
8977 *
8978 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8979 * Return: 0 on success, -1 on invalid value
8980 */
8981static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8982 u32 *wmi_value)
8983{
8984 int ret = 0;
8985
8986 switch (nl80211_value) {
8987 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8988 *wmi_value = WMI_SAR_MOD_CCK;
8989 break;
8990 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8991 *wmi_value = WMI_SAR_MOD_OFDM;
8992 break;
8993 default:
8994 ret = -1;
8995 }
8996 return ret;
8997}
8998
8999
9000/**
9001 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9002 * @wiphy: Pointer to wireless phy
9003 * @wdev: Pointer to wireless device
9004 * @data: Pointer to data
9005 * @data_len: Length of @data
9006 *
9007 * This function is used to setup Specific Absorption Rate limit specs.
9008 *
9009 * Return: 0 on success, negative errno on failure
9010 */
9011static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9012 struct wireless_dev *wdev,
9013 const void *data, int data_len)
9014{
9015 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9016 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9017 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9018 *sar_spec_list;
9019 struct sar_limit_cmd_params sar_limit_cmd = {0};
9020 int ret = -EINVAL, i = 0, rem = 0;
9021
9022 ENTER();
9023
9024 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9025 hdd_err("Command not allowed in FTM mode");
9026 return -EPERM;
9027 }
9028
9029 if (wlan_hdd_validate_context(hdd_ctx))
9030 return -EINVAL;
9031
9032 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9033 data, data_len, NULL)) {
9034 hdd_err("Invalid SAR attributes");
9035 return -EINVAL;
9036 }
9037
9038 /* Vendor command manadates all SAR Specs in single call */
9039 sar_limit_cmd.commit_limits = 1;
9040 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9041 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9042 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9043 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9044 &sar_limit_cmd.sar_enable) < 0) {
9045 hdd_err("Invalid SAR Enable attr");
9046 goto fail;
9047 }
9048 }
9049 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9050
9051 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9052 sar_limit_cmd.num_limit_rows = nla_get_u32(
9053 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9054 hdd_info("attr sar num_limit_rows %d",
9055 sar_limit_cmd.num_limit_rows);
9056 }
9057 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9058 hdd_err("SAR Spec list exceed supported size");
9059 goto fail;
9060 }
9061 if (sar_limit_cmd.num_limit_rows == 0)
9062 goto send_sar_limits;
9063 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9064 struct sar_limit_cmd_row) *
9065 sar_limit_cmd.num_limit_rows);
9066 if (!sar_limit_cmd.sar_limit_row_list) {
9067 ret = -ENOMEM;
9068 goto fail;
9069 }
9070 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9071 hdd_err("Invalid SAR SPECs list");
9072 goto fail;
9073 }
9074
9075 nla_for_each_nested(sar_spec_list,
9076 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9077 if (i == sar_limit_cmd.num_limit_rows) {
9078 hdd_warn("SAR Cmd has excess SPECs in list");
9079 break;
9080 }
9081
9082 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9083 nla_data(sar_spec_list), nla_len(sar_spec_list),
9084 NULL)) {
9085 hdd_err("nla_parse failed for SAR Spec list");
9086 goto fail;
9087 }
9088 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9089 if (sar_spec[
9090 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9091 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9092 nla_get_u32(sar_spec[
9093 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9094 } else {
9095 hdd_err("SAR Spec does not have power limit value");
9096 goto fail;
9097 }
9098
9099 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9100 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9101 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9102 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9103 < 0) {
9104 hdd_err("Invalid SAR Band attr");
9105 goto fail;
9106 }
9107 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9108 WMI_SAR_BAND_ID_VALID_MASK;
9109 }
9110 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9111 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9112 nla_get_u32(sar_spec[
9113 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9114 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9115 WMI_SAR_CHAIN_ID_VALID_MASK;
9116 }
9117 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9118 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9119 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9120 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9121 < 0) {
9122 hdd_err("Invalid SAR Modulation attr");
9123 goto fail;
9124 }
9125 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9126 WMI_SAR_MOD_ID_VALID_MASK;
9127 }
9128 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9129 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9130 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9131 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9132 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9133 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9134 i++;
9135 }
9136
9137 if (i < sar_limit_cmd.num_limit_rows) {
9138 hdd_warn("SAR Cmd has less SPECs in list");
9139 sar_limit_cmd.num_limit_rows = i;
9140 }
9141
9142send_sar_limits:
9143 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9144 QDF_STATUS_SUCCESS)
9145 ret = 0;
9146fail:
9147 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9148 return ret;
9149}
9150
9151/**
9152 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9153 * @wiphy: Pointer to wireless phy
9154 * @wdev: Pointer to wireless device
9155 * @data: Pointer to data
9156 * @data_len: Length of @data
9157 *
9158 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9159 *
9160 * Return: 0 on success, negative errno on failure
9161 */
9162static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9163 struct wireless_dev *wdev,
9164 const void *data,
9165 int data_len)
9166{
9167 int ret;
9168
9169 cds_ssr_protect(__func__);
9170 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9171 data_len);
9172 cds_ssr_unprotect(__func__);
9173
9174 return ret;
9175}
9176
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309177static const struct
9178nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9179 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9180 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9181 .len = QDF_MAC_ADDR_SIZE},
9182};
9183
9184/**
9185 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9186 * @wiphy: Pointer to wireless phy
9187 * @wdev: Pointer to wireless device
9188 * @data: Pointer to data
9189 * @data_len: Length of @data
9190 *
9191 * This function is used to enable/disable roaming using vendor commands
9192 *
9193 * Return: 0 on success, negative errno on failure
9194 */
9195static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9196 struct wireless_dev *wdev,
9197 const void *data, int data_len)
9198{
9199 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9200 struct net_device *dev = wdev->netdev;
9201 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9202 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9203 uint32_t is_fast_roam_enabled;
9204 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309205 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309206
9207 ENTER_DEV(dev);
9208
9209 ret = wlan_hdd_validate_context(hdd_ctx);
9210 if (0 != ret)
9211 return ret;
9212
9213 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9214 hdd_err("Command not allowed in FTM mode");
9215 return -EINVAL;
9216 }
9217
9218 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9219 qca_wlan_vendor_attr);
9220 if (ret) {
9221 hdd_err("Invalid ATTR");
9222 return -EINVAL;
9223 }
9224
9225 /* Parse and fetch Enable flag */
9226 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9227 hdd_err("attr enable failed");
9228 return -EINVAL;
9229 }
9230
9231 is_fast_roam_enabled = nla_get_u32(
9232 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009233 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9234 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309235
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009236 if (!adapter->fast_roaming_allowed) {
9237 hdd_err("fast roaming not allowed on %s interface",
9238 adapter->dev->name);
9239 return -EINVAL;
9240 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309241 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309242 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009243 (is_fast_roam_enabled &&
9244 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309245 if (qdf_status != QDF_STATUS_SUCCESS)
9246 hdd_err("sme_config_fast_roaming failed with status=%d",
9247 qdf_status);
9248 ret = qdf_status_to_os_return(qdf_status);
9249
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309250 EXIT();
9251 return ret;
9252}
9253
9254/**
9255 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9256 * @wiphy: Pointer to wireless phy
9257 * @wdev: Pointer to wireless device
9258 * @data: Pointer to data
9259 * @data_len: Length of @data
9260 *
9261 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9262 *
9263 * Return: 0 on success, negative errno on failure
9264 */
9265static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9266 struct wireless_dev *wdev,
9267 const void *data, int data_len)
9268{
9269 int ret;
9270
9271 cds_ssr_protect(__func__);
9272 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9273 cds_ssr_unprotect(__func__);
9274
9275 return ret;
9276}
9277
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309278static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9279 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9280 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9281 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9282 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9283};
9284
9285/**
9286 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9287 * @wiphy: Pointer to wireless phy
9288 * @wdev: Pointer to wireless device
9289 * @data: Pointer to data
9290 * @data_len: Length of @data
9291 *
9292 * Return: 0 on success, negative errno on failure
9293 */
9294static int
9295__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9296 struct wireless_dev *wdev,
9297 const void *data,
9298 int data_len)
9299{
9300 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9301 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9302 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9303 struct nlattr *apth;
9304 int rem;
9305 int ret = 1;
9306 int print_idx = -1;
9307 int module_id = -1;
9308 int bit_mask = -1;
9309 int status;
9310
9311 ENTER();
9312
9313 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9314 hdd_err("Command not allowed in FTM mode");
9315 return -EINVAL;
9316 }
9317
9318 ret = wlan_hdd_validate_context(hdd_ctx);
9319 if (ret != 0)
9320 return -EINVAL;
9321
9322 print_idx = qdf_get_pidx();
9323 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9324 hdd_err("Invalid print controle object index");
9325 return -EINVAL;
9326 }
9327
9328 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9329 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9330 hdd_err("Invalid attr");
9331 return -EINVAL;
9332 }
9333
9334 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9335 hdd_err("attr trace level param failed");
9336 return -EINVAL;
9337 }
9338
9339 nla_for_each_nested(apth,
9340 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9341 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9342 nla_data(apth), nla_len(apth), NULL)) {
9343 hdd_err("Invalid attr");
9344 return -EINVAL;
9345 }
9346
9347 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9348 hdd_err("attr Module ID failed");
9349 return -EINVAL;
9350 }
9351 module_id = nla_get_u32
9352 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9353
9354 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9355 hdd_err("attr Verbose mask failed");
9356 return -EINVAL;
9357 }
9358 bit_mask = nla_get_u32
9359 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9360
9361 status = hdd_qdf_trace_enable(module_id, bit_mask);
9362
9363 if (status != 0)
9364 hdd_err("can not set verbose mask %d for the category %d",
9365 bit_mask, module_id);
9366 }
9367
9368 EXIT();
9369 return ret;
9370}
9371
9372/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309373 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9374 * @wiphy: Pointer to wireless phy
9375 * @wdev: Pointer to wireless device
9376 * @data: Pointer to data
9377 * @data_len: Length of @data
9378 *
9379 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9380 *
9381 * Return: 0 on success, negative errno on failure
9382 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309383
9384static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9385 struct wireless_dev *wdev,
9386 const void *data,
9387 int data_len)
9388{
9389 int ret;
9390
9391 cds_ssr_protect(__func__);
9392 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9393 cds_ssr_unprotect(__func__);
9394
9395 return ret;
9396}
9397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9399 {
9400 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9401 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9402 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309403 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009404 .doit = is_driver_dfs_capable
9405 },
9406
9407#ifdef WLAN_FEATURE_NAN
9408 {
9409 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9410 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9411 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9412 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9413 .doit = wlan_hdd_cfg80211_nan_request
9414 },
9415#endif
9416
9417#ifdef WLAN_FEATURE_STATS_EXT
9418 {
9419 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9420 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9421 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9422 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9423 .doit = wlan_hdd_cfg80211_stats_ext_request
9424 },
9425#endif
9426#ifdef FEATURE_WLAN_EXTSCAN
9427 {
9428 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9429 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9431 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9432 .doit = wlan_hdd_cfg80211_extscan_start
9433 },
9434 {
9435 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9436 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9437 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9438 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9439 .doit = wlan_hdd_cfg80211_extscan_stop
9440 },
9441 {
9442 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9443 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9444 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9445 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9446 },
9447 {
9448 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9449 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9450 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9451 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9452 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9453 },
9454 {
9455 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9456 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9457 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9458 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9459 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9460 },
9461 {
9462 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9463 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9464 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9465 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9466 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9467 },
9468 {
9469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9470 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9471 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9472 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9473 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9474 },
9475 {
9476 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9477 .info.subcmd =
9478 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9479 .flags =
9480 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9481 WIPHY_VENDOR_CMD_NEED_RUNNING,
9482 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9483 },
9484 {
9485 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9486 .info.subcmd =
9487 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9488 .flags =
9489 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9490 WIPHY_VENDOR_CMD_NEED_RUNNING,
9491 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9492 },
9493 {
9494 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9495 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9496 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9497 WIPHY_VENDOR_CMD_NEED_NETDEV |
9498 WIPHY_VENDOR_CMD_NEED_RUNNING,
9499 .doit = wlan_hdd_cfg80211_set_epno_list
9500 },
9501#endif /* FEATURE_WLAN_EXTSCAN */
9502
9503#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9504 {
9505 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9506 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9507 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9508 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9509 .doit = wlan_hdd_cfg80211_ll_stats_clear
9510 },
9511
9512 {
9513 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9514 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9515 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9516 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9517 .doit = wlan_hdd_cfg80211_ll_stats_set
9518 },
9519
9520 {
9521 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9522 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9523 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9524 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9525 .doit = wlan_hdd_cfg80211_ll_stats_get
9526 },
9527#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9528#ifdef FEATURE_WLAN_TDLS
9529 {
9530 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9531 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9532 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9533 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9534 .doit = wlan_hdd_cfg80211_exttdls_enable
9535 },
9536 {
9537 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9538 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9539 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9540 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9541 .doit = wlan_hdd_cfg80211_exttdls_disable
9542 },
9543 {
9544 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9545 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9546 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9547 .doit = wlan_hdd_cfg80211_exttdls_get_status
9548 },
9549#endif
9550 {
9551 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9552 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9553 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9554 .doit = wlan_hdd_cfg80211_get_supported_features
9555 },
9556 {
9557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9558 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9559 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9560 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9561 },
9562 {
9563 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9564 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9565 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309566 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009567 },
9568 {
9569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9572 WIPHY_VENDOR_CMD_NEED_NETDEV,
9573 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9574 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009575 {
9576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9577 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9578 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9579 WIPHY_VENDOR_CMD_NEED_NETDEV,
9580 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9581 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009582 {
9583 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309584 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9585 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9586 WIPHY_VENDOR_CMD_NEED_NETDEV |
9587 WIPHY_VENDOR_CMD_NEED_RUNNING,
9588 .doit = hdd_cfg80211_get_station_cmd
9589 },
9590 {
9591 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009592 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9593 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9594 WIPHY_VENDOR_CMD_NEED_NETDEV |
9595 WIPHY_VENDOR_CMD_NEED_RUNNING,
9596 .doit = wlan_hdd_cfg80211_do_acs
9597 },
9598
9599 {
9600 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9601 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9602 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9603 WIPHY_VENDOR_CMD_NEED_NETDEV,
9604 .doit = wlan_hdd_cfg80211_get_features
9605 },
9606#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9607 {
9608 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9609 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9610 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9611 WIPHY_VENDOR_CMD_NEED_NETDEV |
9612 WIPHY_VENDOR_CMD_NEED_RUNNING,
9613 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9614 },
9615#endif
9616#ifdef FEATURE_WLAN_EXTSCAN
9617 {
9618 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9619 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9620 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9621 WIPHY_VENDOR_CMD_NEED_NETDEV |
9622 WIPHY_VENDOR_CMD_NEED_RUNNING,
9623 .doit = wlan_hdd_cfg80211_set_passpoint_list
9624 },
9625 {
9626 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9627 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9628 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9629 WIPHY_VENDOR_CMD_NEED_NETDEV |
9630 WIPHY_VENDOR_CMD_NEED_RUNNING,
9631 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9632 },
9633 {
9634 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9635 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9636 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9637 WIPHY_VENDOR_CMD_NEED_NETDEV |
9638 WIPHY_VENDOR_CMD_NEED_RUNNING,
9639 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9640 },
9641 {
9642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9643 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9644 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9645 WIPHY_VENDOR_CMD_NEED_NETDEV |
9646 WIPHY_VENDOR_CMD_NEED_RUNNING,
9647 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9648 },
9649#endif /* FEATURE_WLAN_EXTSCAN */
9650 {
9651 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9652 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9653 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9654 WIPHY_VENDOR_CMD_NEED_NETDEV,
9655 .doit = wlan_hdd_cfg80211_get_wifi_info
9656 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009657#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009658 {
9659 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9660 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9661 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9662 WIPHY_VENDOR_CMD_NEED_NETDEV |
9663 WIPHY_VENDOR_CMD_NEED_RUNNING,
9664 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9665 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009666#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667 {
9668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9671 WIPHY_VENDOR_CMD_NEED_NETDEV,
9672 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9673 },
9674 {
9675 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9676 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9677 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9678 WIPHY_VENDOR_CMD_NEED_NETDEV,
9679 .doit = wlan_hdd_cfg80211_wifi_logger_start
9680 },
9681 {
9682 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9683 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9684 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9685 WIPHY_VENDOR_CMD_NEED_NETDEV,
9686 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9687 },
9688 {
9689 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9690 .info.subcmd =
9691 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9692 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9693 WIPHY_VENDOR_CMD_NEED_NETDEV |
9694 WIPHY_VENDOR_CMD_NEED_RUNNING,
9695 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9696 },
9697 {
9698 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9699 .info.subcmd =
9700 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9701 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9702 WIPHY_VENDOR_CMD_NEED_NETDEV |
9703 WIPHY_VENDOR_CMD_NEED_RUNNING,
9704 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9705 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009706#ifdef WLAN_FEATURE_TSF
9707 {
9708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9709 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9710 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9711 WIPHY_VENDOR_CMD_NEED_NETDEV |
9712 WIPHY_VENDOR_CMD_NEED_RUNNING,
9713 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9714 },
9715#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009716#ifdef FEATURE_WLAN_TDLS
9717 {
9718 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9719 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9720 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9721 WIPHY_VENDOR_CMD_NEED_NETDEV |
9722 WIPHY_VENDOR_CMD_NEED_RUNNING,
9723 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9724 },
9725#endif
9726#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9727 {
9728 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9729 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9730 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9731 WIPHY_VENDOR_CMD_NEED_NETDEV |
9732 WIPHY_VENDOR_CMD_NEED_RUNNING,
9733 .doit = wlan_hdd_cfg80211_offloaded_packets
9734 },
9735#endif
9736 {
9737 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9738 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9739 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9740 WIPHY_VENDOR_CMD_NEED_NETDEV |
9741 WIPHY_VENDOR_CMD_NEED_RUNNING,
9742 .doit = wlan_hdd_cfg80211_monitor_rssi
9743 },
9744 {
9745 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309746 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9747 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9748 WIPHY_VENDOR_CMD_NEED_NETDEV |
9749 WIPHY_VENDOR_CMD_NEED_RUNNING,
9750 .doit = wlan_hdd_cfg80211_set_ns_offload
9751 },
9752 {
9753 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009754 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9755 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9756 WIPHY_VENDOR_CMD_NEED_NETDEV |
9757 WIPHY_VENDOR_CMD_NEED_RUNNING,
9758 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9759 },
9760#ifdef WLAN_FEATURE_MEMDUMP
9761 {
9762 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9763 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9764 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9765 WIPHY_VENDOR_CMD_NEED_NETDEV |
9766 WIPHY_VENDOR_CMD_NEED_RUNNING,
9767 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9768 },
9769#endif /* WLAN_FEATURE_MEMDUMP */
9770 {
9771 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9772 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9773 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9774 WIPHY_VENDOR_CMD_NEED_NETDEV |
9775 WIPHY_VENDOR_CMD_NEED_RUNNING,
9776 .doit = wlan_hdd_cfg80211_vendor_scan
9777 },
9778
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309779 /* Vendor abort scan */
9780 {
9781 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9782 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9783 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9784 WIPHY_VENDOR_CMD_NEED_NETDEV |
9785 WIPHY_VENDOR_CMD_NEED_RUNNING,
9786 .doit = wlan_hdd_vendor_abort_scan
9787 },
9788
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009789 /* OCB commands */
9790 {
9791 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9792 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9793 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9794 WIPHY_VENDOR_CMD_NEED_NETDEV |
9795 WIPHY_VENDOR_CMD_NEED_RUNNING,
9796 .doit = wlan_hdd_cfg80211_ocb_set_config
9797 },
9798 {
9799 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9800 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9801 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9802 WIPHY_VENDOR_CMD_NEED_NETDEV |
9803 WIPHY_VENDOR_CMD_NEED_RUNNING,
9804 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9805 },
9806 {
9807 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9808 .info.subcmd =
9809 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
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_start_timing_advert
9814 },
9815 {
9816 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9817 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
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_stop_timing_advert
9822 },
9823 {
9824 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9825 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9826 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9827 WIPHY_VENDOR_CMD_NEED_NETDEV |
9828 WIPHY_VENDOR_CMD_NEED_RUNNING,
9829 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9830 },
9831 {
9832 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9833 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9834 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9835 WIPHY_VENDOR_CMD_NEED_NETDEV |
9836 WIPHY_VENDOR_CMD_NEED_RUNNING,
9837 .doit = wlan_hdd_cfg80211_dcc_get_stats
9838 },
9839 {
9840 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9841 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9842 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9843 WIPHY_VENDOR_CMD_NEED_NETDEV |
9844 WIPHY_VENDOR_CMD_NEED_RUNNING,
9845 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9846 },
9847 {
9848 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9849 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9850 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9851 WIPHY_VENDOR_CMD_NEED_NETDEV |
9852 WIPHY_VENDOR_CMD_NEED_RUNNING,
9853 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9854 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309855 {
9856 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9857 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9858 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9859 WIPHY_VENDOR_CMD_NEED_NETDEV |
9860 WIPHY_VENDOR_CMD_NEED_RUNNING,
9861 .doit = wlan_hdd_cfg80211_get_link_properties
9862 },
Peng Xu278d0122015-09-24 16:34:17 -07009863 {
Peng Xud2220962016-07-11 17:59:17 -07009864 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009865 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9866 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9867 WIPHY_VENDOR_CMD_NEED_NETDEV |
9868 WIPHY_VENDOR_CMD_NEED_RUNNING,
9869 .doit = wlan_hdd_cfg80211_set_ota_test
9870 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009871#ifdef FEATURE_LFR_SUBNET_DETECTION
9872 {
9873 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9874 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9875 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9876 WIPHY_VENDOR_CMD_NEED_NETDEV |
9877 WIPHY_VENDOR_CMD_NEED_RUNNING,
9878 .doit = wlan_hdd_cfg80211_set_gateway_params
9879 },
9880#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009881 {
Peng Xud2220962016-07-11 17:59:17 -07009882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009883 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9884 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9885 WIPHY_VENDOR_CMD_NEED_NETDEV |
9886 WIPHY_VENDOR_CMD_NEED_RUNNING,
9887 .doit = wlan_hdd_cfg80211_txpower_scale
9888 },
9889 {
9890 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9891 .info.subcmd =
9892 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9893 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9894 WIPHY_VENDOR_CMD_NEED_NETDEV |
9895 WIPHY_VENDOR_CMD_NEED_RUNNING,
9896 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9897 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309898 {
9899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9902 WIPHY_VENDOR_CMD_NEED_NETDEV |
9903 WIPHY_VENDOR_CMD_NEED_RUNNING,
9904 .doit = wlan_hdd_cfg80211_bpf_offload
9905 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309906 {
9907 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309908 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9910 WIPHY_VENDOR_CMD_NEED_NETDEV |
9911 WIPHY_VENDOR_CMD_NEED_RUNNING,
9912 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9913 },
9914 {
9915 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309916 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9917 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9918 WIPHY_VENDOR_CMD_NEED_NETDEV |
9919 WIPHY_VENDOR_CMD_NEED_RUNNING,
9920 .doit = wlan_hdd_cfg80211_sta_roam_policy
9921 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309922#ifdef FEATURE_WLAN_CH_AVOID
9923 {
9924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9927 WIPHY_VENDOR_CMD_NEED_NETDEV |
9928 WIPHY_VENDOR_CMD_NEED_RUNNING,
9929 .doit = wlan_hdd_cfg80211_avoid_freq
9930 },
9931#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309932 {
9933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309934 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9935 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9936 WIPHY_VENDOR_CMD_NEED_NETDEV |
9937 WIPHY_VENDOR_CMD_NEED_RUNNING,
9938 .doit = wlan_hdd_cfg80211_sap_configuration_set
9939 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009940 {
Peng Xu4225c152016-07-14 21:18:14 -07009941 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009942 .info.subcmd =
9943 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9944 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9945 WIPHY_VENDOR_CMD_NEED_NETDEV |
9946 WIPHY_VENDOR_CMD_NEED_RUNNING,
9947 .doit = wlan_hdd_cfg80211_p2p_lo_start
9948 },
9949 {
9950 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9951 .info.subcmd =
9952 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9953 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9954 WIPHY_VENDOR_CMD_NEED_NETDEV |
9955 WIPHY_VENDOR_CMD_NEED_RUNNING,
9956 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9957 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309958 {
9959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9960 .info.subcmd =
9961 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9962 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9963 WIPHY_VENDOR_CMD_NEED_NETDEV |
9964 WIPHY_VENDOR_CMD_NEED_RUNNING,
9965 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9966 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009967#ifdef WLAN_FEATURE_NAN_DATAPATH
9968 {
9969 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9970 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9971 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9972 WIPHY_VENDOR_CMD_NEED_NETDEV |
9973 WIPHY_VENDOR_CMD_NEED_RUNNING,
9974 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9975 },
9976#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309977 {
9978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9979 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9981 WIPHY_VENDOR_CMD_NEED_NETDEV |
9982 WIPHY_VENDOR_CMD_NEED_RUNNING,
9983 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9984 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309985 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309986 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9987 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9988 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9989 WIPHY_VENDOR_CMD_NEED_NETDEV |
9990 WIPHY_VENDOR_CMD_NEED_RUNNING,
9991 .doit = wlan_hdd_cfg80211_get_bus_size
9992 },
9993 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309994 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9995 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
9996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9997 WIPHY_VENDOR_CMD_NEED_NETDEV |
9998 WIPHY_VENDOR_CMD_NEED_RUNNING,
9999 .doit = wlan_hdd_cfg80211_update_vendor_channel
10000 },
10001 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010002 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10003 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10004 WIPHY_VENDOR_CMD_NEED_NETDEV |
10005 WIPHY_VENDOR_CMD_NEED_RUNNING,
10006 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010007 },
10008 {
10009 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10010 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10011 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10012 WIPHY_VENDOR_CMD_NEED_NETDEV |
10013 WIPHY_VENDOR_CMD_NEED_RUNNING,
10014 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010015 },
10016#ifdef WLAN_FEATURE_DISA
10017 {
10018 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10019 .info.subcmd =
10020 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10021 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10022 WIPHY_VENDOR_CMD_NEED_NETDEV |
10023 WIPHY_VENDOR_CMD_NEED_RUNNING,
10024 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10025 },
10026#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010027#ifdef FEATURE_WLAN_TDLS
10028 {
10029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10030 .info.subcmd =
10031 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10032 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10033 WIPHY_VENDOR_CMD_NEED_NETDEV |
10034 WIPHY_VENDOR_CMD_NEED_RUNNING,
10035 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010036 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010037#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010038 {
10039 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10040 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10041 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10042 WIPHY_VENDOR_CMD_NEED_RUNNING,
10043 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10044 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010045 {
10046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10049 WIPHY_VENDOR_CMD_NEED_NETDEV |
10050 WIPHY_VENDOR_CMD_NEED_RUNNING,
10051 .doit = wlan_hdd_cfg80211_set_trace_level
10052 },
10053
Paul Zhang3a210c52016-12-08 10:18:12 +080010054#ifdef WLAN_UMAC_CONVERGENCE
10055 COMMON_VENDOR_COMMANDS
10056#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010057};
10058
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010059#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10060 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10061 defined(FEATURE_WLAN_SCAN_PNO)
10062/**
10063 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10064 * @wiphy: pointer to wiphy
10065 * @config: pointer to config
10066 *
10067 * Return: None
10068 */
10069static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10070 struct hdd_config *config)
10071{
10072 if (config->configPNOScanSupport) {
10073 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10074 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10075 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10076 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10077 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10078 if (config->max_sched_scan_plan_interval)
10079 wiphy->max_sched_scan_plan_interval =
10080 config->max_sched_scan_plan_interval;
10081 if (config->max_sched_scan_plan_iterations)
10082 wiphy->max_sched_scan_plan_iterations =
10083 config->max_sched_scan_plan_iterations;
10084 }
10085}
10086#else
10087static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10088 struct hdd_config *config)
10089{
10090}
10091#endif
10092
10093
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010094/**
10095 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10096 * @priv_size: Size of the hdd context.
10097 *
10098 * Allocate wiphy context and hdd context.
10099 *
10100 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010102hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010103{
10104 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010105 hdd_context_t *hdd_ctx;
10106
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010107 ENTER();
10108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10110
10111 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010112 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010113 return NULL;
10114 }
10115
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010116 hdd_ctx = wiphy_priv(wiphy);
10117
10118 hdd_ctx->wiphy = wiphy;
10119
10120 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010121}
10122
10123/*
10124 * FUNCTION: wlan_hdd_cfg80211_update_band
10125 * This function is called from the supplicant through a
10126 * private ioctl to change the band value
10127 */
10128int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10129{
10130 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010131 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010132
10133 ENTER();
10134
Dustin Browna30892e2016-10-12 17:28:36 -070010135 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010137 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010138 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010139
10140 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10141 struct ieee80211_supported_band *band = wiphy->bands[i];
10142
10143 channelEnabledState =
10144 cds_get_channel_state(band->channels[j].
10145 hw_value);
10146
Dustin Browna30892e2016-10-12 17:28:36 -070010147 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148 /* 5G only */
10149#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10150 /* Enable Social channels for P2P */
10151 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10152 (band->channels[j].center_freq)
10153 && CHANNEL_STATE_ENABLE ==
10154 channelEnabledState)
10155 band->channels[j].flags &=
10156 ~IEEE80211_CHAN_DISABLED;
10157 else
10158#endif
10159 band->channels[j].flags |=
10160 IEEE80211_CHAN_DISABLED;
10161 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010162 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010163 eCSR_BAND_24 == eBand) {
10164 /* 2G only */
10165 band->channels[j].flags |=
10166 IEEE80211_CHAN_DISABLED;
10167 continue;
10168 }
10169
Amar Singhal6842e8f2016-02-23 16:30:32 -080010170 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171 band->channels[j].flags &=
10172 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010173 }
10174 }
10175 return 0;
10176}
10177
Peng Xuacfdda12017-02-06 16:15:38 -080010178#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010179/*
10180 * FUNCTION: wlan_hdd_cfg80211_init
10181 * This function is called by hdd_wlan_startup()
10182 * during initialization.
10183 * This function is used to initialize and register wiphy structure.
10184 */
10185int wlan_hdd_cfg80211_init(struct device *dev,
10186 struct wiphy *wiphy, struct hdd_config *pCfg)
10187{
10188 int i, j;
10189 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10190
10191 ENTER();
10192
10193 /* Now bind the underlying wlan device with wiphy */
10194 set_wiphy_dev(wiphy, dev);
10195
10196 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10199 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010200 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201#else
10202 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010203 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010204#endif
10205
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010206 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10207 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10208 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10209#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10210 | WIPHY_FLAG_4ADDR_STATION
10211#endif
10212 | WIPHY_FLAG_OFFCHAN_TX;
10213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10215 wiphy->wowlan = &wowlan_support_cfg80211_init;
10216#else
10217 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10218 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10219 wiphy->wowlan.pattern_min_len = 1;
10220 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10221#endif
10222
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010223 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224#ifdef FEATURE_WLAN_ESE
10225 || pCfg->isEseIniFeatureEnabled
10226#endif
10227 ) {
10228 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10229 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010230#ifdef FEATURE_WLAN_TDLS
10231 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10232 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10233#endif
10234
10235 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10236
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010237#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10238 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10239#endif
10240
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010241 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010242
10243#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010244 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010245#endif
10246
10247 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010248 * driver can still register regulatory callback and
10249 * it will get regulatory settings in wiphy->band[], but
10250 * driver need to determine what to do with both
10251 * regulatory settings
10252 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253
10254 wiphy->reg_notifier = hdd_reg_notifier;
10255
10256#if defined QCA_WIFI_FTM
10257}
10258#endif
10259
10260 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10261
10262 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10263
10264 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10265
Arun Khandavallifae92942016-08-01 13:31:08 +053010266 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10267 | BIT(NL80211_IFTYPE_ADHOC)
10268 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10269 | BIT(NL80211_IFTYPE_P2P_GO)
10270 | BIT(NL80211_IFTYPE_AP)
10271 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010272
Arun Khandavallifae92942016-08-01 13:31:08 +053010273 if (pCfg->advertiseConcurrentOperation) {
10274 if (pCfg->enableMCC) {
10275 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010276
Arun Khandavallifae92942016-08-01 13:31:08 +053010277 for (i = 0;
10278 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10279 i++) {
10280 if (!pCfg->allowMCCGODiffBI)
10281 wlan_hdd_iface_combination[i].
10282 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010283 }
10284 }
10285 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010286 ARRAY_SIZE(wlan_hdd_iface_combination);
10287 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010288 }
10289
10290 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010291 * on ini values
10292 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 if (!pCfg->ShortGI20MhzEnable) {
10294 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10295 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010296 }
10297
10298 if (!pCfg->ShortGI40MhzEnable) {
10299 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10300 }
10301
10302 if (!pCfg->nChannelBondingMode5GHz) {
10303 wlan_hdd_band_5_ghz.ht_cap.cap &=
10304 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10305 }
10306
Abhishek Singhf512bf32016-05-04 16:47:46 +053010307 /*
10308 * In case of static linked driver at the time of driver unload,
10309 * module exit doesn't happens. Module cleanup helps in cleaning
10310 * of static memory.
10311 * If driver load happens statically, at the time of driver unload,
10312 * wiphy flags don't get reset because of static memory.
10313 * It's better not to store channel in static memory.
10314 */
Dustin Browna30892e2016-10-12 17:28:36 -070010315 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10316 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010317 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010318 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010319 hdd_err("Not enough memory to allocate channels");
10320 return -ENOMEM;
10321 }
Dustin Browna30892e2016-10-12 17:28:36 -070010322 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010323 &hdd_channels_2_4_ghz[0],
10324 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010325 if ((hdd_is_5g_supported(pHddCtx)) &&
10326 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10327 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10328 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10329 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010330 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10331 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010332 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010333 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010334 hdd_err("Not enough memory to allocate channels");
10335 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010336 bands[NL80211_BAND_2GHZ]->channels);
10337 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010338 return -ENOMEM;
10339 }
Dustin Browna30892e2016-10-12 17:28:36 -070010340 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010341 &hdd_channels_5_ghz[0],
10342 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010343 }
10344
Dustin Browna30892e2016-10-12 17:28:36 -070010345 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010346
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010347 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010348 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010349
10350 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10351 struct ieee80211_supported_band *band = wiphy->bands[i];
10352
Dustin Browna30892e2016-10-12 17:28:36 -070010353 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 eCSR_BAND_5G == pCfg->nBandCapability) {
10355 /* 5G only */
10356#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10357 /* Enable social channels for P2P */
10358 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10359 (band->channels[j].center_freq))
10360 band->channels[j].flags &=
10361 ~IEEE80211_CHAN_DISABLED;
10362 else
10363#endif
10364 band->channels[j].flags |=
10365 IEEE80211_CHAN_DISABLED;
10366 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010367 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010368 eCSR_BAND_24 == pCfg->nBandCapability) {
10369 /* 2G only */
10370 band->channels[j].flags |=
10371 IEEE80211_CHAN_DISABLED;
10372 continue;
10373 }
10374 }
10375 }
10376 /*Initialise the supported cipher suite details */
10377 wiphy->cipher_suites = hdd_cipher_suites;
10378 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10379
10380 /*signal strength in mBm (100*dBm) */
10381 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10382 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10383
Anurag Chouhan6d760662016-02-20 16:05:43 +053010384 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010385 wiphy->n_vendor_commands =
10386 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10387 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10388
10389 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10390 wiphy->n_vendor_events =
10391 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10392 }
10393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010394 if (pCfg->enableDFSMasterCap) {
10395 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10396 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010397
10398 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10399
10400#ifdef QCA_HT_2040_COEX
10401 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10402#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010403 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010404
10405#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10406 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10407 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10408 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10409 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10410#endif
10411
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010412 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010413 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010414
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010415 EXIT();
10416 return 0;
10417}
10418
Abhishek Singhf512bf32016-05-04 16:47:46 +053010419/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010420 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10421 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010422 *
10423 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010424 * memory allocated in wlan_hdd_cfg80211_init also
10425 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010426 *
10427 * Return: void
10428 */
10429void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10430{
10431 int i;
10432
Dustin Browna30892e2016-10-12 17:28:36 -070010433 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010434 if (NULL != wiphy->bands[i] &&
10435 (NULL != wiphy->bands[i]->channels)) {
10436 qdf_mem_free(wiphy->bands[i]->channels);
10437 wiphy->bands[i]->channels = NULL;
10438 }
10439 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010440 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010441}
10442
Yingying Tang80e15f32016-09-27 18:23:01 +080010443/**
10444 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10445 * @hdd_ctx: HDD context
10446 *
10447 * this function will update capabilities for supported bands
10448 *
10449 * Return: void
10450 */
10451static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10452{
10453 uint32_t val32;
10454 uint16_t val16;
10455 tSirMacHTCapabilityInfo *ht_cap_info;
10456 QDF_STATUS status;
10457
10458 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10459 if (QDF_STATUS_SUCCESS != status) {
10460 hdd_err("could not get HT capability info");
10461 val32 = 0;
10462 }
10463 val16 = (uint16_t)val32;
10464 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10465
10466 if (ht_cap_info->txSTBC == true) {
10467 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10468 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10469 IEEE80211_HT_CAP_TX_STBC;
10470 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10471 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10472 IEEE80211_HT_CAP_TX_STBC;
10473 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010474
10475 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10476 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10477 vht_cap.vht_supported = 0;
10478 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10479 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10480 vht_cap.vht_supported = 0;
10481 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10482 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010483}
10484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010485/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010486 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010487 * initialization. In wlan_hdd_cfg80211_init, only the
10488 * default values will be initialized. The final initialization
10489 * of all required members can be done here.
10490 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010491void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010492{
Yingying Tang80e15f32016-09-27 18:23:01 +080010493 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10494
10495 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010496}
10497
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010498/**
10499 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10500 * @cfg: hdd cfg
10501 *
10502 * this function update 11n mode in hdd cfg
10503 *
10504 * Return: void
10505 */
10506void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10507{
10508 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10509 hdd_notice("support 11ac");
10510 } else {
10511 hdd_notice("not support 11ac");
10512 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10513 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10514 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10515 cfg->sap_p2p_11ac_override = 0;
10516 }
10517 }
10518}
10519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010520/* In this function we are registering wiphy. */
10521int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10522{
10523 ENTER();
10524 /* Register our wiphy dev with cfg80211 */
10525 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010526 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010527 return -EIO;
10528 }
10529
10530 EXIT();
10531 return 0;
10532}
10533
10534/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010535 * HDD function to update wiphy capability based on target offload status.
10536 *
10537 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10538 * capability even before downloading firmware to the target. In discrete
10539 * case, host will get know certain offload capability (say sched_scan
10540 * caps) only after downloading firmware to the target and target boots up.
10541 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10542 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010543 */
10544void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10545{
10546#ifdef FEATURE_WLAN_SCAN_PNO
10547 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10548 struct hdd_config *pCfg = pHddCtx->config;
10549
10550 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10551 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010552 * have PNO support.
10553 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010554 if (!pCfg->PnoOffload) {
10555 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10556 wiphy->max_sched_scan_ssids = 0;
10557 wiphy->max_match_sets = 0;
10558 wiphy->max_sched_scan_ie_len = 0;
10559 }
10560#endif
10561}
10562
10563/* This function registers for all frame which supplicant is interested in */
10564void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10565{
10566 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10567 /* Register for all P2P action, public action etc frames */
10568 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10569
10570 ENTER();
10571
Abhishek Singh7996eb72015-12-30 17:24:02 +053010572 /* Register frame indication call back */
10573 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10574
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010575 /* Register for p2p ack indication */
10576 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10577
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010578 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010579 * initialized. Once we will move to 2.6.37 kernel, in which we have
10580 * frame register ops, we will move this code as a part of that
10581 */
10582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010583 /* GAS Initial Request */
10584 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10585 (uint8_t *) GAS_INITIAL_REQ,
10586 GAS_INITIAL_REQ_SIZE);
10587
10588 /* GAS Initial Response */
10589 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10590 (uint8_t *) GAS_INITIAL_RSP,
10591 GAS_INITIAL_RSP_SIZE);
10592
10593 /* GAS Comeback Request */
10594 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10595 (uint8_t *) GAS_COMEBACK_REQ,
10596 GAS_COMEBACK_REQ_SIZE);
10597
10598 /* GAS Comeback Response */
10599 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10600 (uint8_t *) GAS_COMEBACK_RSP,
10601 GAS_COMEBACK_RSP_SIZE);
10602
10603 /* P2P Public Action */
10604 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10605 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10606 P2P_PUBLIC_ACTION_FRAME_SIZE);
10607
10608 /* P2P Action */
10609 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10610 (uint8_t *) P2P_ACTION_FRAME,
10611 P2P_ACTION_FRAME_SIZE);
10612
10613 /* WNM BSS Transition Request frame */
10614 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10615 (uint8_t *) WNM_BSS_ACTION_FRAME,
10616 WNM_BSS_ACTION_FRAME_SIZE);
10617
10618 /* WNM-Notification */
10619 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10620 (uint8_t *) WNM_NOTIFICATION_FRAME,
10621 WNM_NOTIFICATION_FRAME_SIZE);
10622}
10623
10624void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10625{
10626 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10627 /* Register for all P2P action, public action etc frames */
10628 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10629
10630 ENTER();
10631
10632 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010633 * initialized. Once we will move to 2.6.37 kernel, in which we have
10634 * frame register ops, we will move this code as a part of that
10635 */
10636
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010637 /* GAS Initial Request */
10638
10639 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10640 (uint8_t *) GAS_INITIAL_REQ,
10641 GAS_INITIAL_REQ_SIZE);
10642
10643 /* GAS Initial Response */
10644 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10645 (uint8_t *) GAS_INITIAL_RSP,
10646 GAS_INITIAL_RSP_SIZE);
10647
10648 /* GAS Comeback Request */
10649 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10650 (uint8_t *) GAS_COMEBACK_REQ,
10651 GAS_COMEBACK_REQ_SIZE);
10652
10653 /* GAS Comeback Response */
10654 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10655 (uint8_t *) GAS_COMEBACK_RSP,
10656 GAS_COMEBACK_RSP_SIZE);
10657
10658 /* P2P Public Action */
10659 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10660 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10661 P2P_PUBLIC_ACTION_FRAME_SIZE);
10662
10663 /* P2P Action */
10664 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10665 (uint8_t *) P2P_ACTION_FRAME,
10666 P2P_ACTION_FRAME_SIZE);
10667
10668 /* WNM-Notification */
10669 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10670 (uint8_t *) WNM_NOTIFICATION_FRAME,
10671 WNM_NOTIFICATION_FRAME_SIZE);
10672}
10673
10674#ifdef FEATURE_WLAN_WAPI
10675void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10676 const uint8_t *mac_addr, const uint8_t *key,
10677 int key_Len)
10678{
10679 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10680 tCsrRoamSetKey setKey;
10681 bool isConnected = true;
10682 int status = 0;
10683 uint32_t roamId = 0xFF;
10684 uint8_t *pKeyPtr = NULL;
10685 int n = 0;
10686
Jeff Johnson46b40792016-06-29 14:03:14 -070010687 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010688 hdd_device_mode_to_string(pAdapter->device_mode),
10689 pAdapter->device_mode);
10690
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010691 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010692 setKey.keyId = key_index; /* Store Key ID */
10693 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10694 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10695 setKey.paeRole = 0; /* the PAE role */
10696 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010697 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010698 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010699 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010700 }
10701 setKey.keyLength = key_Len;
10702 pKeyPtr = setKey.Key;
10703 memcpy(pKeyPtr, key, key_Len);
10704
Jeff Johnson46b40792016-06-29 14:03:14 -070010705 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010707 hdd_notice("WAPI KEY Data[%d]:%02x ",
10708 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010709
10710 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10711 if (isConnected) {
10712 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10713 pAdapter->sessionId, &setKey, &roamId);
10714 }
10715 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010716 hdd_err("sme_roam_set_key returned ERROR status= %d",
10717 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010718 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10719 }
10720}
10721#endif /* FEATURE_WLAN_WAPI */
10722
10723uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10724 uint8_t eid)
10725{
10726 int left = length;
10727 uint8_t *ptr = (uint8_t *)ies_ptr;
10728 uint8_t elem_id, elem_len;
10729
10730 while (left >= 2) {
10731 elem_id = ptr[0];
10732 elem_len = ptr[1];
10733 left -= 2;
10734 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010735 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010736 eid, elem_len, left);
10737 return NULL;
10738 }
10739 if (elem_id == eid) {
10740 return ptr;
10741 }
10742
10743 left -= elem_len;
10744 ptr += (elem_len + 2);
10745 }
10746 return NULL;
10747}
10748
10749/*
10750 * FUNCTION: wlan_hdd_validate_operation_channel
10751 * called by wlan_hdd_cfg80211_start_bss() and
10752 * wlan_hdd_set_channel()
10753 * This function validates whether given channel is part of valid
10754 * channel list.
10755 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010756QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757 int channel)
10758{
10759
10760 uint32_t num_ch = 0;
10761 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10762 u32 indx = 0;
10763 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10764 uint8_t fValidChannel = false, count = 0;
10765 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10766
10767 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10768
10769 if (hdd_pConfig_ini->sapAllowAllChannel) {
10770 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010771 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010772 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 fValidChannel = true;
10774 break;
10775 }
10776 }
10777 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010778 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010779 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010780 }
10781 } else {
10782 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10783 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010784 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010785 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010786 }
10787 for (indx = 0; indx < num_ch; indx++) {
10788 if (channel == valid_ch[indx]) {
10789 break;
10790 }
10791 }
10792
10793 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010794 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010795 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010796 }
10797 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010798 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799
10800}
10801
10802#ifdef DHCP_SERVER_OFFLOAD
10803static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10804{
10805 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10806 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10807 uint8_t numEntries = 0;
10808 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10809 uint8_t num;
10810 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010811 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010812 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010813 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010814 return;
10815 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10817 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10818 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10819 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10820 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10821 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010822 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010823 goto end;
10824 }
10825 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010826 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827 goto end;
10828 }
10829 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010830 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 goto end;
10832 }
10833 for (num = 0; num < numEntries; num++) {
10834 temp = srv_ip[num];
10835 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10836 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010837 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010838 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010839 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 goto end;
10841 }
Jeff Johnson77848112016-06-29 14:52:06 -070010842 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010844 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 return;
10846}
10847#endif /* DHCP_SERVER_OFFLOAD */
10848
10849static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10850 struct net_device *dev,
10851 struct bss_parameters *params)
10852{
10853 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10854 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10855 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010856 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857
10858 ENTER();
10859
Anurag Chouhan6d760662016-02-20 16:05:43 +053010860 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010861 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862 return -EINVAL;
10863 }
10864
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010865 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10866 hdd_err("invalid session id: %d", pAdapter->sessionId);
10867 return -EINVAL;
10868 }
10869
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010870 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010871 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10872 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010873 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010874 hdd_device_mode_to_string(pAdapter->device_mode),
10875 pAdapter->device_mode, params->ap_isolate);
10876
10877 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10878 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010879 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010881
Krunal Sonib4326f22016-03-10 13:05:51 -080010882 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10883 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 return -EOPNOTSUPP;
10885 }
10886
10887 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010888 * want to update this parameter
10889 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890 if (-1 != params->ap_isolate) {
10891 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10892 !!params->ap_isolate;
10893
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010894 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 pAdapter->sessionId,
10896 pAdapter->sessionCtx.
10897 ap.
10898 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010899 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900 ret = -EINVAL;
10901 }
10902 }
10903
10904 EXIT();
10905 return ret;
10906}
10907
Krunal Soni8c37e322016-02-03 16:08:37 -080010908/**
10909 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10910 * @ndev: pointer to net device provided by supplicant
10911 * @type: type of the interface, upper layer wanted to change
10912 *
10913 * Upper layer provides the new interface mode that needs to be changed
10914 * for given net device
10915 *
10916 * Return: success or failure in terms of integer value
10917 */
10918static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919 enum nl80211_iftype type)
10920{
Krunal Soni8c37e322016-02-03 16:08:37 -080010921 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10922 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10923 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010924 hdd_wext_state_t *wext;
10925 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010926 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010927
10928 ENTER();
10929
Krunal Soni8c37e322016-02-03 16:08:37 -080010930 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010931 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932 return 0;
10933 }
10934
10935 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010936 hdd_stop_adapter(hdd_ctx, adapter, true);
10937 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010938 wdev->iftype = type;
10939 /*Check for sub-string p2p to confirm its a p2p interface */
10940 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010941 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010942 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010943 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010944 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010945 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010946 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010947 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010949 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010951 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10952 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010953 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10954 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010955 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010956 adapter->scan_info.scanAddIE.length;
10957 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010958 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010959 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10960 wext->roamProfile.phyMode =
10961 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10962 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010963 EXIT();
10964 return status;
10965}
10966
10967static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10968 struct net_device *dev,
10969 struct bss_parameters *params)
10970{
10971 int ret;
10972
10973 cds_ssr_protect(__func__);
10974 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10975 cds_ssr_unprotect(__func__);
10976
10977 return ret;
10978}
10979
10980/* FUNCTION: wlan_hdd_change_country_code_cd
10981 * to wait for contry code completion
10982 */
10983void *wlan_hdd_change_country_code_cb(void *pAdapter)
10984{
10985 hdd_adapter_t *call_back_pAdapter = pAdapter;
10986 complete(&call_back_pAdapter->change_country_code);
10987 return NULL;
10988}
10989
Rajeev Kumar98edb772016-01-19 12:42:19 -080010990/**
10991 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10992 * @wiphy: Pointer to the wiphy structure
10993 * @ndev: Pointer to the net device
10994 * @type: Interface type
10995 * @flags: Flags for change interface
10996 * @params: Pointer to change interface parameters
10997 *
10998 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010999 */
11000static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11001 struct net_device *ndev,
11002 enum nl80211_iftype type,
11003 u32 *flags,
11004 struct vif_params *params)
11005{
11006 struct wireless_dev *wdev;
11007 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11008 hdd_context_t *pHddCtx;
11009 tCsrRoamProfile *pRoamProfile = NULL;
11010 eCsrRoamBssType LastBSSType;
11011 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011012 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013 int status;
11014
11015 ENTER();
11016
Anurag Chouhan6d760662016-02-20 16:05:43 +053011017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011018 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011019 return -EINVAL;
11020 }
11021
11022 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11023 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011024 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011025 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011027 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011028 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11029 pAdapter->sessionId, type));
11030
Jeff Johnson77848112016-06-29 14:52:06 -070011031 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011032 pAdapter->device_mode, type);
11033
Arun Khandavallifae92942016-08-01 13:31:08 +053011034 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11035 if (status) {
11036 hdd_err("Failed to start modules");
11037 return -EINVAL;
11038 }
11039
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011040 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011041 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11042 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011043 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 return -EINVAL;
11045 }
11046
11047 pConfig = pHddCtx->config;
11048 wdev = ndev->ieee80211_ptr;
11049
11050 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011051 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052
11053 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
11054
Krunal Sonib4326f22016-03-10 13:05:51 -080011055 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11056 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11057 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11058 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059 hdd_wext_state_t *pWextState =
11060 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11061
11062 pRoamProfile = &pWextState->roamProfile;
11063 LastBSSType = pRoamProfile->BSSType;
11064
11065 switch (type) {
11066 case NL80211_IFTYPE_STATION:
11067 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011068 case NL80211_IFTYPE_ADHOC:
11069 if (type == NL80211_IFTYPE_ADHOC) {
11070 wlan_hdd_tdls_exit(pAdapter);
11071 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011072 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011073 }
11074 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11075 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011076 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011077 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011078 if (hdd_start_adapter(pAdapter)) {
11079 hdd_err("Failed to start adapter :%d",
11080 pAdapter->device_mode);
11081 return -EINVAL;
11082 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084 case NL80211_IFTYPE_AP:
11085 case NL80211_IFTYPE_P2P_GO:
11086 {
Jeff Johnson77848112016-06-29 14:52:06 -070011087 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011088 (type ==
11089 NL80211_IFTYPE_AP) ? "SoftAP" :
11090 "P2pGo");
11091
11092 /* Cancel any remain on channel for GO mode */
11093 if (NL80211_IFTYPE_P2P_GO == type) {
11094 wlan_hdd_cancel_existing_remain_on_channel
11095 (pAdapter);
11096 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011097
Arun Khandavallifae92942016-08-01 13:31:08 +053011098 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 /* De-init the adapter */
11100 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11101 memset(&pAdapter->sessionCtx, 0,
11102 sizeof(pAdapter->sessionCtx));
11103 pAdapter->device_mode =
11104 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011105 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11106 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107
11108 /*
11109 * Fw will take care incase of concurrency
11110 */
11111
Krunal Sonib4326f22016-03-10 13:05:51 -080011112 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011113 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011114 /* To meet Android requirements create
11115 * a randomized MAC address of the
11116 * form 02:1A:11:Fx:xx:xx
11117 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118 get_random_bytes(&ndev->dev_addr[3], 3);
11119 ndev->dev_addr[0] = 0x02;
11120 ndev->dev_addr[1] = 0x1A;
11121 ndev->dev_addr[2] = 0x11;
11122 ndev->dev_addr[3] |= 0xF0;
11123 memcpy(pAdapter->macAddressCurrent.
11124 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011125 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011126 pr_info("wlan: Generated HotSpot BSSID "
11127 MAC_ADDRESS_STR "\n",
11128 MAC_ADDR_ARRAY(ndev->dev_addr));
11129 }
11130
11131 hdd_set_ap_ops(pAdapter->dev);
11132
Arun Khandavallifae92942016-08-01 13:31:08 +053011133 if (hdd_start_adapter(pAdapter)) {
11134 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011135 return -EINVAL;
11136 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011137 /* Interface type changed update in wiphy structure */
11138 if (wdev) {
11139 wdev->iftype = type;
11140 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011141 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 return -EINVAL;
11143 }
11144 goto done;
11145 }
11146
11147 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011148 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149 type);
11150 return -EOPNOTSUPP;
11151 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011152 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11153 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154 switch (type) {
11155 case NL80211_IFTYPE_STATION:
11156 case NL80211_IFTYPE_P2P_CLIENT:
11157 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011158 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11159 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011160 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011162 if (hdd_start_adapter(pAdapter)) {
11163 hdd_err("Failed to start adapter :%d",
11164 pAdapter->device_mode);
11165 return -EINVAL;
11166 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167 goto done;
11168
11169 case NL80211_IFTYPE_AP:
11170 case NL80211_IFTYPE_P2P_GO:
11171 wdev->iftype = type;
11172 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011173 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174 goto done;
11175
11176 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011177 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011178 type);
11179 return -EOPNOTSUPP;
11180 }
11181 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011182 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183 pAdapter->device_mode);
11184 return -EOPNOTSUPP;
11185 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186done:
11187 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011188 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011189
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011190 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011191
11192 EXIT();
11193 return 0;
11194}
11195
Rajeev Kumar98edb772016-01-19 12:42:19 -080011196/**
11197 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11198 * @wiphy: Pointer to the wiphy structure
11199 * @ndev: Pointer to the net device
11200 * @type: Interface type
11201 * @flags: Flags for change interface
11202 * @params: Pointer to change interface parameters
11203 *
11204 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 */
11206static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11207 struct net_device *ndev,
11208 enum nl80211_iftype type,
11209 u32 *flags,
11210 struct vif_params *params)
11211{
11212 int ret;
11213
11214 cds_ssr_protect(__func__);
11215 ret =
11216 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11217 cds_ssr_unprotect(__func__);
11218
11219 return ret;
11220}
11221
11222#ifdef FEATURE_WLAN_TDLS
11223static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11224 int index, uint8_t match)
11225{
11226 int i;
11227 for (i = 0; i < index; i++) {
11228 if (arr[i] == match)
11229 return true;
11230 }
11231 return false;
11232}
11233#endif
11234
11235/**
11236 * __wlan_hdd_change_station() - change station
11237 * @wiphy: Pointer to the wiphy structure
11238 * @dev: Pointer to the net device.
11239 * @mac: bssid
11240 * @params: Pointer to station parameters
11241 *
11242 * Return: 0 for success, error number on failure.
11243 */
11244#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11245static int __wlan_hdd_change_station(struct wiphy *wiphy,
11246 struct net_device *dev,
11247 const uint8_t *mac,
11248 struct station_parameters *params)
11249#else
11250static int __wlan_hdd_change_station(struct wiphy *wiphy,
11251 struct net_device *dev,
11252 uint8_t *mac,
11253 struct station_parameters *params)
11254#endif
11255{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011256 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11258 hdd_context_t *pHddCtx;
11259 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011260 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011261#ifdef FEATURE_WLAN_TDLS
11262 tCsrStaParams StaParams = { 0 };
11263 uint8_t isBufSta = 0;
11264 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011265 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011266#endif
11267 int ret;
11268
11269 ENTER();
11270
Anurag Chouhan6d760662016-02-20 16:05:43 +053011271 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011272 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273 return -EINVAL;
11274 }
11275
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011276 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011277 TRACE_CODE_HDD_CHANGE_STATION,
11278 pAdapter->sessionId, params->listen_interval));
11279
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011280 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11281 hdd_err("invalid session id: %d", pAdapter->sessionId);
11282 return -EINVAL;
11283 }
11284
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11286 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011287 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011288 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289
11290 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11291
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011292 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011293
Krunal Sonib4326f22016-03-10 13:05:51 -080011294 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11295 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011296 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11297 status =
11298 hdd_softap_change_sta_state(pAdapter,
11299 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011300 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011301
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011302 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011303 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304 return -EINVAL;
11305 }
11306 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011307 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11308 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011309#ifdef FEATURE_WLAN_TDLS
11310 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011311
11312 if (cds_is_sub_20_mhz_enabled()) {
11313 hdd_err("TDLS not allowed with sub 20 MHz");
11314 return -EINVAL;
11315 }
11316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 StaParams.capability = params->capability;
11318 StaParams.uapsd_queues = params->uapsd_queues;
11319 StaParams.max_sp = params->max_sp;
11320
11321 /* Convert (first channel , number of channels) tuple to
11322 * the total list of channels. This goes with the assumption
11323 * that if the first channel is < 14, then the next channels
11324 * are an incremental of 1 else an incremental of 4 till the number
11325 * of channels.
11326 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011327 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011328 if (0 != params->supported_channels_len) {
11329 int i = 0, j = 0, k = 0, no_of_channels = 0;
11330 int num_unique_channels;
11331 int next;
11332 for (i = 0;
11333 i < params->supported_channels_len
11334 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11335 int wifi_chan_index;
11336 if (!wlan_hdd_is_duplicate_channel
11337 (StaParams.supported_channels, j,
11338 params->supported_channels[i])) {
11339 StaParams.
11340 supported_channels[j] =
11341 params->
11342 supported_channels[i];
11343 } else {
11344 continue;
11345 }
11346 wifi_chan_index =
11347 ((StaParams.supported_channels[j] <=
11348 HDD_CHANNEL_14) ? 1 : 4);
11349 no_of_channels =
11350 params->supported_channels[i + 1];
11351
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011352 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 -080011353 StaParams.
11354 supported_channels[j],
11355 wifi_chan_index,
11356 no_of_channels);
11357 for (k = 1; k <= no_of_channels &&
11358 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11359 k++) {
11360 next =
11361 StaParams.
11362 supported_channels[j] +
11363 wifi_chan_index;
11364 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11365 StaParams.
11366 supported_channels[j
11367 +
11368 1]
11369 = next;
11370 } else {
11371 continue;
11372 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011373 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011374 j + 1,
11375 StaParams.
11376 supported_channels[j +
11377 1]);
11378 j += 1;
11379 }
11380 }
11381 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011382 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011383 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011384 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011385 StaParams.
11386 supported_channels[i]);
11387 }
11388 if (MAX_CHANNEL < num_unique_channels)
11389 num_unique_channels = MAX_CHANNEL;
11390 StaParams.supported_channels_len =
11391 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011392 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 StaParams.supported_channels_len);
11394 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011395 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 params->supported_oper_classes,
11397 params->supported_oper_classes_len);
11398 StaParams.supported_oper_classes_len =
11399 params->supported_oper_classes_len;
11400
11401 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011402 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403 params->ext_capab,
11404 sizeof(StaParams.extn_capability));
11405
11406 if (NULL != params->ht_capa) {
11407 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011408 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409 sizeof(tSirHTCap));
11410 }
11411
11412 StaParams.supported_rates_len =
11413 params->supported_rates_len;
11414
11415 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11416 * The supported_rates array , for all the structures propogating till Add Sta
11417 * to the firmware has to be modified , if the supplicant (ieee80211) is
11418 * modified to send more rates.
11419 */
11420
11421 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11422 */
11423 if (StaParams.supported_rates_len >
11424 SIR_MAC_MAX_SUPP_RATES)
11425 StaParams.supported_rates_len =
11426 SIR_MAC_MAX_SUPP_RATES;
11427
11428 if (0 != StaParams.supported_rates_len) {
11429 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011430 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011431 params->supported_rates,
11432 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011433 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011434 StaParams.supported_rates_len);
11435 for (i = 0; i < StaParams.supported_rates_len;
11436 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011437 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011438 StaParams.supported_rates[i]);
11439 }
11440
11441 if (NULL != params->vht_capa) {
11442 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011443 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011444 params->vht_capa,
11445 sizeof(tSirVHTCap));
11446 }
11447
11448 if (0 != params->ext_capab_len) {
11449 /*Define A Macro : TODO Sunil */
11450 if ((1 << 4) & StaParams.extn_capability[3]) {
11451 isBufSta = 1;
11452 }
11453 /* TDLS Channel Switching Support */
11454 if ((1 << 6) & StaParams.extn_capability[3]) {
11455 isOffChannelSupported = 1;
11456 }
11457 }
11458
Nitesh Shah99934ac2016-09-05 15:54:08 +053011459 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011460 (params->ht_capa || params->vht_capa ||
11461 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011462 is_qos_wmm_sta = true;
11463
11464 hdd_notice("%s: TDLS Peer is QOS capable"
11465 " is_qos_wmm_sta= %d HTcapPresent = %d",
11466 __func__, is_qos_wmm_sta,
11467 StaParams.htcap_present);
11468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011469 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011470 &StaParams,
11471 isBufSta,
11472 isOffChannelSupported,
11473 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011474 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011475 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476 return -EINVAL;
11477 }
11478
11479 status =
11480 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11481 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011482 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011483 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011484 return -EINVAL;
11485 }
11486 }
11487#endif
11488 }
11489 EXIT();
11490 return ret;
11491}
11492
11493/**
11494 * wlan_hdd_change_station() - cfg80211 change station handler function
11495 * @wiphy: Pointer to the wiphy structure
11496 * @dev: Pointer to the net device.
11497 * @mac: bssid
11498 * @params: Pointer to station parameters
11499 *
11500 * This is the cfg80211 change station handler function which invokes
11501 * the internal function @__wlan_hdd_change_station with
11502 * SSR protection.
11503 *
11504 * Return: 0 for success, error number on failure.
11505 */
11506#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11507static int wlan_hdd_change_station(struct wiphy *wiphy,
11508 struct net_device *dev,
11509 const u8 *mac,
11510 struct station_parameters *params)
11511#else
11512static int wlan_hdd_change_station(struct wiphy *wiphy,
11513 struct net_device *dev,
11514 u8 *mac,
11515 struct station_parameters *params)
11516#endif
11517{
11518 int ret;
11519
11520 cds_ssr_protect(__func__);
11521 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11522 cds_ssr_unprotect(__func__);
11523
11524 return ret;
11525}
11526
11527/*
11528 * FUNCTION: __wlan_hdd_cfg80211_add_key
11529 * This function is used to initialize the key information
11530 */
11531static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11532 struct net_device *ndev,
11533 u8 key_index, bool pairwise,
11534 const u8 *mac_addr,
11535 struct key_params *params)
11536{
11537 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11538 tCsrRoamSetKey setKey;
11539 int status;
11540 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011542 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543 hdd_context_t *pHddCtx;
11544 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11545
11546 ENTER();
11547
Anurag Chouhan6d760662016-02-20 16:05:43 +053011548 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011549 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011550 return -EINVAL;
11551 }
11552
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011553 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11554 hdd_err("invalid session id: %d", pAdapter->sessionId);
11555 return -EINVAL;
11556 }
11557
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011558 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011559 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11560 pAdapter->sessionId, params->key_len));
11561 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11562 status = wlan_hdd_validate_context(pHddCtx);
11563
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011564 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011566
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011567 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011568 hdd_device_mode_to_string(pAdapter->device_mode),
11569 pAdapter->device_mode);
11570
11571 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011572 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573
11574 return -EINVAL;
11575 }
11576
11577 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011578 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011579
11580 return -EINVAL;
11581 }
11582
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011583 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584
11585 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011586 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 setKey.keyId = key_index;
11588 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011589 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590
11591 switch (params->cipher) {
11592 case WLAN_CIPHER_SUITE_WEP40:
11593 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11594 break;
11595
11596 case WLAN_CIPHER_SUITE_WEP104:
11597 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11598 break;
11599
11600 case WLAN_CIPHER_SUITE_TKIP:
11601 {
11602 u8 *pKey = &setKey.Key[0];
11603 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11604
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011605 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011606
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011607 /* Supplicant sends the 32bytes key in this order
11608 *
11609 * |--------------|----------|----------|
11610 * | Tk1 |TX-MIC | RX Mic |
11611 * |--------------|----------|----------|
11612 * <---16bytes---><--8bytes--><--8bytes-->
11613 *
11614 * Sme expects the 32 bytes key to be in the below order
11615 *
11616 * |--------------|----------|----------|
11617 * | Tk1 |RX-MIC | TX Mic |
11618 * |--------------|----------|----------|
11619 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620 */
11621 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011622 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623
11624 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011625 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011626
11627 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011628 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011629
11630 break;
11631 }
11632
11633 case WLAN_CIPHER_SUITE_CCMP:
11634 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11635 break;
11636
11637#ifdef FEATURE_WLAN_WAPI
11638 case WLAN_CIPHER_SUITE_SMS4:
11639 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011640 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11642 mac_addr, params->key,
11643 params->key_len);
11644 return 0;
11645 }
11646#endif
11647
11648#ifdef FEATURE_WLAN_ESE
11649 case WLAN_CIPHER_SUITE_KRK:
11650 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11651 break;
11652#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11653 case WLAN_CIPHER_SUITE_BTK:
11654 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11655 break;
11656#endif
11657#endif
11658
11659#ifdef WLAN_FEATURE_11W
11660 case WLAN_CIPHER_SUITE_AES_CMAC:
11661 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11662 break;
11663#endif
11664
11665 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011666 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011667 return -EOPNOTSUPP;
11668 }
11669
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011670 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671
11672 if (!pairwise) {
11673 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011674 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011675 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011676 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 } else {
11678 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011679 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011681 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011683 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011684 /* if a key is already installed, block all subsequent ones */
11685 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011686 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 return 0;
11688 }
11689
11690 setKey.keyDirection = eSIR_TX_RX;
11691 /*Set the group key */
11692 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11693 pAdapter->sessionId, &setKey, &roamId);
11694
11695 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011696 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011697 return -EINVAL;
11698 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011699 /* Save the keys here and call sme_roam_set_key for setting
11700 * the PTK after peer joins the IBSS network
11701 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011702 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703 &setKey, sizeof(tCsrRoamSetKey));
11704
11705 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11706 return status;
11707 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011708 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11709 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011710 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11711 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011712 status = wlansap_set_key_sta(
11713 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011714 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011715 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011716 __LINE__, status);
11717 }
11718 }
11719
11720 /* Save the key in ap ctx for use on START_BASS and restart */
11721 if (pairwise ||
11722 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11723 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011724 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011725 sizeof(tCsrRoamSetKey));
11726 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011727 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011728 sizeof(tCsrRoamSetKey));
11729
Krunal Sonib4326f22016-03-10 13:05:51 -080011730 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11731 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011732 hdd_wext_state_t *pWextState =
11733 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11734 hdd_station_ctx_t *pHddStaCtx =
11735 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11736
11737 if (!pairwise) {
11738 /* set group key */
11739 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011740 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741 __func__, __LINE__);
11742 hdd_perform_roam_set_key_complete(pAdapter);
11743 }
11744 }
11745
11746 pWextState->roamProfile.Keys.KeyLength[key_index] =
11747 (u8) params->key_len;
11748
11749 pWextState->roamProfile.Keys.defaultIndex = key_index;
11750
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011751 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 KeyMaterial[key_index][0], params->key,
11753 params->key_len);
11754
11755 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11756
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011757 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011758 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11759 setKey.keyDirection);
11760
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011761 /* The supplicant may attempt to set the PTK once
11762 * pre-authentication is done. Save the key in the
11763 * UMAC and include it in the ADD BSS request
11764 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011765 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011767 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011768 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011770 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011771 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011772 return -EINVAL;
11773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011774
11775 /* issue set key request to SME */
11776 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11777 pAdapter->sessionId, &setKey, &roamId);
11778
11779 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011780 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011781 pHddStaCtx->roam_info.roamingState =
11782 HDD_ROAM_STATE_NONE;
11783 return -EINVAL;
11784 }
11785
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011786 /* in case of IBSS as there was no information
11787 * available about WEP keys during IBSS join, group
11788 * key intialized with NULL key, so re-initialize
11789 * group key with correct value
11790 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791 if ((eCSR_BSS_TYPE_START_IBSS ==
11792 pWextState->roamProfile.BSSType)
11793 &&
11794 !((IW_AUTH_KEY_MGMT_802_1X ==
11795 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11796 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11797 pHddStaCtx->conn_info.authType)
11798 )
11799 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11800 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11801 )
11802 ) {
11803 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011804 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011805
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011806 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11808 setKey.keyDirection);
11809
11810 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11811 pAdapter->sessionId, &setKey,
11812 &roamId);
11813
11814 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011815 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816 pHddStaCtx->roam_info.roamingState =
11817 HDD_ROAM_STATE_NONE;
11818 return -EINVAL;
11819 }
11820 }
11821 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011822 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 return 0;
11824}
11825
11826static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11827 struct net_device *ndev,
11828 u8 key_index, bool pairwise,
11829 const u8 *mac_addr,
11830 struct key_params *params)
11831{
11832 int ret;
11833 cds_ssr_protect(__func__);
11834 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11835 mac_addr, params);
11836 cds_ssr_unprotect(__func__);
11837
11838 return ret;
11839}
11840
11841/*
11842 * FUNCTION: __wlan_hdd_cfg80211_get_key
11843 * This function is used to get the key information
11844 */
11845static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11846 struct net_device *ndev,
11847 u8 key_index, bool pairwise,
11848 const u8 *mac_addr, void *cookie,
11849 void (*callback)(void *cookie,
11850 struct key_params *)
11851 )
11852{
11853 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11854 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11855 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11856 struct key_params params;
11857
11858 ENTER();
11859
Anurag Chouhan6d760662016-02-20 16:05:43 +053011860 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011861 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011862 return -EINVAL;
11863 }
11864
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011865 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011866 hdd_device_mode_to_string(pAdapter->device_mode),
11867 pAdapter->device_mode);
11868
11869 memset(&params, 0, sizeof(params));
11870
11871 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011872 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011873 key_index);
11874 return -EINVAL;
11875 }
11876
11877 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11878 case eCSR_ENCRYPT_TYPE_NONE:
11879 params.cipher = IW_AUTH_CIPHER_NONE;
11880 break;
11881
11882 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11883 case eCSR_ENCRYPT_TYPE_WEP40:
11884 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11885 break;
11886
11887 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11888 case eCSR_ENCRYPT_TYPE_WEP104:
11889 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11890 break;
11891
11892 case eCSR_ENCRYPT_TYPE_TKIP:
11893 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11894 break;
11895
11896 case eCSR_ENCRYPT_TYPE_AES:
11897 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11898 break;
11899
11900 default:
11901 params.cipher = IW_AUTH_CIPHER_NONE;
11902 break;
11903 }
11904
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011905 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011906 TRACE_CODE_HDD_CFG80211_GET_KEY,
11907 pAdapter->sessionId, params.cipher));
11908
11909 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11910 params.seq_len = 0;
11911 params.seq = NULL;
11912 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11913 callback(cookie, &params);
11914
11915 EXIT();
11916 return 0;
11917}
11918
11919static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11920 struct net_device *ndev,
11921 u8 key_index, bool pairwise,
11922 const u8 *mac_addr, void *cookie,
11923 void (*callback)(void *cookie,
11924 struct key_params *)
11925 )
11926{
11927 int ret;
11928
11929 cds_ssr_protect(__func__);
11930 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11931 mac_addr, cookie, callback);
11932 cds_ssr_unprotect(__func__);
11933
11934 return ret;
11935}
11936
11937/**
11938 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11939 * @wiphy: wiphy interface context
11940 * @ndev: pointer to net device
11941 * @key_index: Key index used in 802.11 frames
11942 * @unicast: true if it is unicast key
11943 * @multicast: true if it is multicast key
11944 *
11945 * This function is required for cfg80211_ops API.
11946 * It is used to delete the key information
11947 * Underlying hardware implementation does not have API to delete the
11948 * encryption key. It is automatically deleted when the peer is
11949 * removed. Hence this function currently does nothing.
11950 * Future implementation may interprete delete key operation to
11951 * replacing the key with a random junk value, effectively making it
11952 * useless.
11953 *
11954 * Return: status code, always 0.
11955 */
11956
11957static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11958 struct net_device *ndev,
11959 u8 key_index,
11960 bool pairwise, const u8 *mac_addr)
11961{
11962 EXIT();
11963 return 0;
11964}
11965
11966/**
11967 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11968 * @wiphy: Pointer to wiphy structure.
11969 * @dev: Pointer to net_device structure.
11970 * @key_index: key index
11971 * @pairwise: pairwise
11972 * @mac_addr: mac address
11973 *
11974 * This is the cfg80211 delete key handler function which invokes
11975 * the internal function @__wlan_hdd_cfg80211_del_key with
11976 * SSR protection.
11977 *
11978 * Return: 0 for success, error number on failure.
11979 */
11980static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11981 struct net_device *dev,
11982 u8 key_index,
11983 bool pairwise, const u8 *mac_addr)
11984{
11985 int ret;
11986
11987 cds_ssr_protect(__func__);
11988 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11989 pairwise, mac_addr);
11990 cds_ssr_unprotect(__func__);
11991
11992 return ret;
11993}
11994
11995/*
11996 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11997 * This function is used to set the default tx key index
11998 */
11999static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12000 struct net_device *ndev,
12001 u8 key_index,
12002 bool unicast, bool multicast)
12003{
12004 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12005 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12006 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12007 hdd_context_t *pHddCtx;
12008 int status;
12009
12010 ENTER();
12011
Anurag Chouhan6d760662016-02-20 16:05:43 +053012012 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012013 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012014 return -EINVAL;
12015 }
12016
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012017 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12018 hdd_err("invalid session id: %d", pAdapter->sessionId);
12019 return -EINVAL;
12020 }
12021
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012022 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012023 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12024 pAdapter->sessionId, key_index));
12025
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012026 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 hdd_device_mode_to_string(pAdapter->device_mode),
12028 pAdapter->device_mode, key_index);
12029
12030 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012031 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012032 return -EINVAL;
12033 }
12034
12035 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12036 status = wlan_hdd_validate_context(pHddCtx);
12037
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012038 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040
Krunal Sonib4326f22016-03-10 13:05:51 -080012041 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12042 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12044 pHddStaCtx->conn_info.ucEncryptionType) &&
12045 (eCSR_ENCRYPT_TYPE_AES !=
12046 pHddStaCtx->conn_info.ucEncryptionType)) {
12047 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012048 * then update the default key index
12049 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012050
12051 tCsrRoamSetKey setKey;
12052 uint32_t roamId = 0xFF;
12053 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12054
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012055 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056
12057 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012058 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012059 setKey.keyId = key_index;
12060 setKey.keyLength = Keys->KeyLength[key_index];
12061
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012062 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012063 &Keys->KeyMaterial[key_index][0],
12064 Keys->KeyLength[key_index]);
12065
12066 setKey.keyDirection = eSIR_TX_RX;
12067
Anurag Chouhanc5548422016-02-24 18:33:27 +053012068 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012069 &pHddStaCtx->conn_info.bssId);
12070
12071 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12072 pWextState->roamProfile.EncryptionType.
12073 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012074 /* In the case of dynamic wep
12075 * supplicant hardcodes DWEP type to
12076 * eCSR_ENCRYPT_TYPE_WEP104 even
12077 * though ap is configured for WEP-40
12078 * encryption. In this canse the key
12079 * length is 5 but the encryption type
12080 * is 104 hence checking the key
12081 * lenght(5) and encryption type(104)
12082 * and switching encryption type to 40
12083 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012084 pWextState->roamProfile.EncryptionType.
12085 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12086 pWextState->roamProfile.mcEncryptionType.
12087 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12088 }
12089
12090 setKey.encType =
12091 pWextState->roamProfile.EncryptionType.
12092 encryptionType[0];
12093
12094 /* Issue set key request */
12095 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12096 pAdapter->sessionId, &setKey,
12097 &roamId);
12098
12099 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012100 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012101 status);
12102 return -EINVAL;
12103 }
12104 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012105 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012106 /* In SoftAp mode setting key direction for default mode */
12107 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12108 pWextState->roamProfile.EncryptionType.encryptionType[0])
12109 && (eCSR_ENCRYPT_TYPE_AES !=
12110 pWextState->roamProfile.EncryptionType.
12111 encryptionType[0])) {
12112 /* Saving key direction for default key index to TX default */
12113 hdd_ap_ctx_t *pAPCtx =
12114 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12115 pAPCtx->wepKey[key_index].keyDirection =
12116 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012117 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012118 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012119 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012120 }
12121 }
12122
12123 EXIT();
12124 return status;
12125}
12126
12127static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12128 struct net_device *ndev,
12129 u8 key_index,
12130 bool unicast, bool multicast)
12131{
12132 int ret;
12133 cds_ssr_protect(__func__);
12134 ret =
12135 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12136 multicast);
12137 cds_ssr_unprotect(__func__);
12138
12139 return ret;
12140}
12141
Abhishek Singhc9941602016-08-09 16:06:22 +053012142/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012143 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12144 * interface that BSS might have been lost.
12145 * @pAdapter: adaptor
12146 * @bssid: bssid which might have been lost
12147 *
12148 * Return: bss which is unlinked from kernel cache
12149 */
12150struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12151 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152{
12153 struct net_device *dev = pAdapter->dev;
12154 struct wireless_dev *wdev = dev->ieee80211_ptr;
12155 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012156 struct cfg80211_bss *bss = NULL;
12157
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012158 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012159 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012160 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012161 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012162 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012163 hdd_info("cfg80211_unlink_bss called for BSSID "
12164 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012165 cfg80211_unlink_bss(wiphy, bss);
12166 }
12167 return bss;
12168}
12169
Abhishek Singhc9941602016-08-09 16:06:22 +053012170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012171/**
12172 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12173 * @pAdapter: Pointer to adapter
12174 * @bss_desc: Pointer to bss descriptor
12175 *
12176 * This function is used to inform the BSS details to nl80211 interface.
12177 *
12178 * Return: struct cfg80211_bss pointer
12179 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012180struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12181 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012182{
12183 /*
12184 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12185 * already exists in bss data base of cfg80211 for that particular BSS
12186 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12187 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12188 * As of now there is no possibility to get the mgmt(probe response)
12189 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12190 * and passing to cfg80211_inform_bss_frame.
12191 */
12192 struct net_device *dev = pAdapter->dev;
12193 struct wireless_dev *wdev = dev->ieee80211_ptr;
12194 struct wiphy *wiphy = wdev->wiphy;
12195 int chan_no = bss_desc->channelId;
12196#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12197 qcom_ie_age *qie_age = NULL;
12198 int ie_length =
12199 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12200#else
12201 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12202#endif
12203 const char *ie =
12204 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12205 unsigned int freq;
12206 struct ieee80211_channel *chan;
12207 struct ieee80211_mgmt *mgmt = NULL;
12208 struct cfg80211_bss *bss_status = NULL;
12209 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12210 int rssi = 0;
12211 hdd_context_t *pHddCtx;
12212 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012213 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012214 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012215
12216 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12217 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012218 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012219 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012221 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012222 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012224 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012225 return NULL;
12226 }
12227
12228 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12229
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012230 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012231 * Instead it wants a monotonic increasing value
12232 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012233 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012234 mgmt->u.probe_resp.timestamp =
12235 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012236
12237 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12238 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12239
12240#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12241 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12242 /* Assuming this is the last IE, copy at the end */
12243 ie_length -= sizeof(qcom_ie_age);
12244 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12245 qie_age->element_id = QCOM_VENDOR_IE_ID;
12246 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12247 qie_age->oui_1 = QCOM_OUI1;
12248 qie_age->oui_2 = QCOM_OUI2;
12249 qie_age->oui_3 = QCOM_OUI3;
12250 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012251 /*
12252 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12253 * all bss related timestamp is in units of ms. Due to this when scan
12254 * results are sent to lowi the scan age is high.To address this,
12255 * send age in units of 1/10 ms.
12256 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012257 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012258 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012259 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012260 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12261 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012262 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12263 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012264#endif
12265
12266 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12267 if (bss_desc->fProbeRsp) {
12268 mgmt->frame_control |=
12269 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12270 } else {
12271 mgmt->frame_control |=
12272 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12273 }
12274
12275 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012276 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012277 freq =
12278 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012279 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012281 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 freq =
12283 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012284 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012286 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012287 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 return NULL;
12289 }
12290
12291 chan = __ieee80211_get_channel(wiphy, freq);
12292 /* When the band is changed on the fly using the GUI, three things are done
12293 * 1. scan abort
12294 * 2. flush scan results from cache
12295 * 3. update the band with the new band user specified (refer to the
12296 * hdd_set_band_helper function) as part of the scan abort, message will be
12297 * queued to PE and we proceed with flushing and changinh the band.
12298 * PE will stop the scanning further and report back the results what ever
12299 * it had till now by calling the call back function.
12300 * if the time between update band and scandone call back is sufficient
12301 * enough the band change reflects in SME, SME validates the channels
12302 * and discards the channels correponding to previous band and calls back
12303 * with zero bss results. but if the time between band update and scan done
12304 * callback is very small then band change will not reflect in SME and SME
12305 * reports to HDD all the channels correponding to previous band.this is due
12306 * to race condition.but those channels are invalid to the new band and so
12307 * this function __ieee80211_get_channel will return NULL.Each time we
12308 * report scan result with this pointer null warning kernel trace is printed.
12309 * if the scan results contain large number of APs continuosly kernel
12310 * warning trace is printed and it will lead to apps watch dog bark.
12311 * So drop the bss and continue to next bss.
12312 */
12313 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012314 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12315 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012316 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012317 return NULL;
12318 }
12319
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012320 /* Based on .ini configuration, raw rssi can be reported for bss.
12321 * Raw rssi is typically used for estimating power.
12322 */
12323
12324 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12325 bss_desc->rssi;
12326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012328 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012330 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012332 (int)(rssi / 100),
12333 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334
12335 bss_status =
12336 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
12337 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012338 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012339 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340 return bss_status;
12341}
12342
12343/**
12344 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12345 * @pAdapter: Pointer to adapter
12346 * @pRoamInfo: Pointer to roam info
12347 *
12348 * This function is used to update the BSS data base of CFG8011
12349 *
12350 * Return: struct cfg80211_bss pointer
12351 */
12352struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12353 tCsrRoamInfo *pRoamInfo)
12354{
12355 tCsrRoamConnectedProfile roamProfile;
12356 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12357 struct cfg80211_bss *bss = NULL;
12358
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012359 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12360 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12361
12362 if (NULL != roamProfile.pBssDesc) {
12363 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12364 roamProfile.pBssDesc);
12365
12366 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012367 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012369 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012370 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012371 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373 return bss;
12374}
12375/**
12376 * wlan_hdd_cfg80211_update_bss() - update bss
12377 * @wiphy: Pointer to wiphy
12378 * @pAdapter: Pointer to adapter
12379 * @scan_time: scan request timestamp
12380 *
12381 * Return: zero if success, non-zero otherwise
12382 */
12383int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12384 hdd_adapter_t *pAdapter,
12385 uint32_t scan_time)
12386{
12387 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12388 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012389 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390 tScanResultHandle pResult;
12391 struct cfg80211_bss *bss_status = NULL;
12392 hdd_context_t *pHddCtx;
12393 int ret;
12394
12395 ENTER();
12396
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012397 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12398 hdd_err("invalid session id: %d", pAdapter->sessionId);
12399 return -EINVAL;
12400 }
12401
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012402 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12404 NO_SESSION, pAdapter->sessionId));
12405
12406 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12407 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012408 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012409 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012410
12411 /* start getting scan results and populate cgf80211 BSS database */
12412 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12413
12414 /* no scan results */
12415 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012416 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012417 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 }
12419
12420 pScanResult = sme_scan_result_get_first(hHal, pResult);
12421
12422 while (pScanResult) {
12423 /*
12424 * - cfg80211_inform_bss() is not updating ie field of bss
12425 * entry if entry already exists in bss data base of cfg80211
12426 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12427 * to update thebss entry instead of cfg80211_inform_bss,
12428 * But this call expects mgmt packet as input. As of now
12429 * there is no possibility to get the mgmt(probe response)
12430 * frame from PE, converting bss_desc to
12431 * ieee80211_mgmt(probe response) and passing to c
12432 * fg80211_inform_bss_frame.
12433 * - Update BSS only if beacon timestamp is later than
12434 * scan request timestamp.
12435 */
12436 if ((scan_time == 0) ||
12437 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012438 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439 bss_status =
12440 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12441 &pScanResult->BssDescriptor);
12442
12443 if (NULL == bss_status) {
12444 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12445 } else {
12446 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012447 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012448 bss_status);
12449 }
12450 } else {
12451 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12452 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12453 }
12454 pScanResult = sme_scan_result_get_next(hHal, pResult);
12455 }
12456
12457 sme_scan_result_purge(hHal, pResult);
12458 /*
12459 * For SAP mode, scan is invoked by hostapd during SAP start
12460 * if hostapd is restarted, we need to flush previous scan
12461 * result so that it will reflect environment change
12462 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012463 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12465 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12466#endif
12467 )
12468 sme_scan_flush_result(hHal);
12469
12470 EXIT();
12471 return 0;
12472}
12473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012474/**
12475 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12476 * @pAdapter: Pointer to adapter
12477 * @pRoamInfo: Pointer to roam info
12478 * @index: Index
12479 * @preauth: Preauth flag
12480 *
12481 * This function is used to notify the supplicant of a new PMKSA candidate.
12482 *
12483 * Return: 0 for success, non-zero for failure
12484 */
12485int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12486 tCsrRoamInfo *pRoamInfo,
12487 int index, bool preauth)
12488{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012489 struct net_device *dev = pAdapter->dev;
12490 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12491
12492 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012493 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012494
12495 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012496 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012497 return -EINVAL;
12498 }
12499
12500 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012501 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012502 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12503 cfg80211_pmksa_candidate_notify(dev, index,
12504 pRoamInfo->bssid.bytes,
12505 preauth, GFP_KERNEL);
12506 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012507 return 0;
12508}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012509
12510#ifdef FEATURE_WLAN_LFR_METRICS
12511/**
12512 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12513 * @pAdapter: Pointer to adapter
12514 * @pRoamInfo: Pointer to roam info
12515 *
12516 * 802.11r/LFR metrics reporting function to report preauth initiation
12517 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012518 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 */
12520#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012521QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 tCsrRoamInfo *pRoamInfo)
12523{
12524 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12525 union iwreq_data wrqu;
12526
12527 ENTER();
12528
12529 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012530 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012531 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012532 }
12533
12534 /* create the event */
12535 memset(&wrqu, 0, sizeof(wrqu));
12536 memset(metrics_notification, 0, sizeof(metrics_notification));
12537
12538 wrqu.data.pointer = metrics_notification;
12539 wrqu.data.length = scnprintf(metrics_notification,
12540 sizeof(metrics_notification),
12541 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12542 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12543
12544 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12545 metrics_notification);
12546
12547 EXIT();
12548
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012549 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550}
12551
12552/**
12553 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12554 * @pAdapter: Pointer to adapter
12555 * @pRoamInfo: Pointer to roam info
12556 * @preauth_status: Preauth status
12557 *
12558 * 802.11r/LFR metrics reporting function to report handover initiation
12559 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012560 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012561 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012562QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12564 tCsrRoamInfo *pRoamInfo,
12565 bool preauth_status)
12566{
12567 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12568 union iwreq_data wrqu;
12569
12570 ENTER();
12571
12572 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012573 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012574 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 }
12576
12577 /* create the event */
12578 memset(&wrqu, 0, sizeof(wrqu));
12579 memset(metrics_notification, 0, sizeof(metrics_notification));
12580
12581 scnprintf(metrics_notification, sizeof(metrics_notification),
12582 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12583 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12584
12585 if (1 == preauth_status)
12586 strlcat(metrics_notification, " true",
12587 sizeof(metrics_notification));
12588 else
12589 strlcat(metrics_notification, " false",
12590 sizeof(metrics_notification));
12591
12592 wrqu.data.pointer = metrics_notification;
12593 wrqu.data.length = strlen(metrics_notification);
12594
12595 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12596 metrics_notification);
12597
12598 EXIT();
12599
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012600 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012601}
12602
12603/**
12604 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12605 * @pAdapter: Pointer to adapter
12606 * @pRoamInfo: Pointer to roam info
12607 *
12608 * 802.11r/LFR metrics reporting function to report handover initiation
12609 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012610 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012612QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012613 tCsrRoamInfo *pRoamInfo)
12614{
12615 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12616 union iwreq_data wrqu;
12617
12618 ENTER();
12619
12620 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012621 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012622 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623 }
12624
12625 /* create the event */
12626 memset(&wrqu, 0, sizeof(wrqu));
12627 memset(metrics_notification, 0, sizeof(metrics_notification));
12628
12629 wrqu.data.pointer = metrics_notification;
12630 wrqu.data.length = scnprintf(metrics_notification,
12631 sizeof(metrics_notification),
12632 "QCOM: LFR_PREAUTH_HANDOVER "
12633 MAC_ADDRESS_STR,
12634 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12635
12636 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12637 metrics_notification);
12638
12639 EXIT();
12640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012641 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012642}
12643#endif
12644
12645/**
12646 * hdd_select_cbmode() - select channel bonding mode
12647 * @pAdapter: Pointer to adapter
12648 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012649 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012650 *
12651 * Return: none
12652 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012653void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12654 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012655{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012656 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012657 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012658 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012659
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012660 /*
12661 * CDS api expects secondary channel for calculating
12662 * the channel params
12663 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012664 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012665 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12666 if (operationChannel >= 1 && operationChannel <= 5)
12667 sec_ch = operationChannel + 4;
12668 else if (operationChannel >= 6 && operationChannel <= 13)
12669 sec_ch = operationChannel - 4;
12670 }
12671
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012672 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012673 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012674
12675 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012676 eHddDot11Mode hdd_dot11_mode;
12677 uint8_t iniDot11Mode =
12678 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12679
12680 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12681 switch (iniDot11Mode) {
12682 case eHDD_DOT11_MODE_AUTO:
12683 case eHDD_DOT11_MODE_11ac:
12684 case eHDD_DOT11_MODE_11ac_ONLY:
12685 if (sme_is_feature_supported_by_fw(DOT11AC))
12686 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12687 else
12688 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12689 break;
12690 case eHDD_DOT11_MODE_11n:
12691 case eHDD_DOT11_MODE_11n_ONLY:
12692 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12693 break;
12694 default:
12695 hdd_dot11_mode = iniDot11Mode;
12696 break;
12697 }
12698 ch_info->channel_width = ch_params->ch_width;
12699 ch_info->phy_mode =
12700 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012701 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012702 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012703 hdd_info("ch_info width %d, phymode %d channel %d",
12704 ch_info->channel_width, ch_info->phy_mode,
12705 ch_info->channel);
12706 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012707}
12708
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012709/**
12710 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12711 * @adapter: STA adapter
12712 * @roam_profile: STA roam profile
12713 *
12714 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12715 *
12716 * Return: false if sta-sap conc is not allowed, else return true
12717 */
12718static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12719 tCsrRoamProfile *roam_profile)
12720{
12721 hdd_context_t *hdd_ctx;
12722 hdd_adapter_t *ap_adapter;
12723 hdd_ap_ctx_t *hdd_ap_ctx;
12724 hdd_hostapd_state_t *hostapd_state;
12725 uint8_t channel = 0;
12726 QDF_STATUS status;
12727
12728 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12729 if (!hdd_ctx) {
12730 hdd_err("HDD context is NULL");
12731 return true;
12732 }
12733
12734 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12735 /* probably no sap running, no handling required */
12736 if (ap_adapter == NULL)
12737 return true;
12738
12739 /*
12740 * sap is not in started state, so it is fine to go ahead with sta.
12741 * if sap is currently doing CAC then don't allow sta to go further.
12742 */
12743 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12744 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12745 return true;
12746
12747 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12748 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12749 return false;
12750 }
12751
12752 /*
12753 * log and return error, if we allow STA to go through, we don't
12754 * know what is going to happen better stop sta connection
12755 */
12756 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12757 if (NULL == hdd_ap_ctx) {
12758 hdd_err("AP context not found");
12759 return false;
12760 }
12761
12762 /* sap is on non-dfs channel, nothing to handle */
12763 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12764 hdd_info("sap is on non-dfs channel, sta is allowed");
12765 return true;
12766 }
12767 /*
12768 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012769 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012770 */
12771 status = cds_get_channel_from_scan_result(adapter,
12772 roam_profile, &channel);
12773
Nitesh Shah59774522016-09-16 15:14:21 +053012774 /*
12775 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12776 * channels for roaming case.
12777 */
12778 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12779 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12780 return true;
12781 }
12782
12783 /*
12784 * If channel is 0 or DFS then better to call pcl and find out the
12785 * best channel. If channel is non-dfs 5 GHz then better move SAP
12786 * to STA's channel to make scc, so we have room for 3port MCC
12787 * scenario.
12788 */
12789 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012790 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12791 true);
12792
12793 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12794 qdf_event_reset(&hostapd_state->qdf_event);
12795 status = wlansap_set_channel_change_with_csa(
12796 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12797 hdd_ap_ctx->sapConfig.ch_width_orig);
12798
12799 if (QDF_STATUS_SUCCESS != status) {
12800 hdd_err("Set channel with CSA IE failed, can't allow STA");
12801 return false;
12802 }
12803
12804 /*
12805 * wait here for SAP to finish the channel switch. When channel
12806 * switch happens, SAP sends few beacons with CSA_IE. After
12807 * successfully Transmission of those beacons, it will move its
12808 * state from started to disconnected and move to new channel.
12809 * once it moves to new channel, sap again moves its state
12810 * machine from disconnected to started and set this event.
12811 * wait for 10 secs to finish this.
12812 */
12813 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12814 if (!QDF_IS_STATUS_SUCCESS(status)) {
12815 hdd_err("wait for qdf_event failed, STA not allowed!!");
12816 return false;
12817 }
12818
12819 return true;
12820}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012821
Krunal Soni31949422016-07-29 17:17:53 -070012822/**
12823 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012825 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826 * @ssid_len: Length of ssid
12827 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012828 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012829 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012830 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012831 *
12832 * This function is used to start the association process
12833 *
12834 * Return: 0 for success, non-zero for failure
12835 */
Krunal Soni31949422016-07-29 17:17:53 -070012836static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012837 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012838 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012839 u8 operatingChannel,
12840 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012841{
12842 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012843 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012844 hdd_wext_state_t *pWextState;
12845 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012846 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012847 uint32_t roamId;
12848 tCsrRoamProfile *pRoamProfile;
12849 eCsrAuthType RSNAuthType;
12850 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012851 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012852
12853 ENTER();
12854
12855 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12856 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012857 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012858
12859 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012860 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012861 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012862
12863 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012864 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012865 status = -EINVAL;
12866 goto ret_status;
12867 }
12868
12869 if (true == cds_is_connection_in_progress()) {
12870 hdd_err("Connection refused: conn in progress");
12871 status = -EINVAL;
12872 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012873 }
12874
12875 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012876 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12877 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012878
12879 if (pRoamProfile) {
12880 hdd_station_ctx_t *pHddStaCtx;
12881 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12882
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012883 /* Restart the opportunistic timer
12884 *
12885 * If hw_mode_change_in_progress is true, then wait
12886 * till firmware sends the callback for hw_mode change.
12887 *
12888 * Else set connect_in_progress as true and proceed.
12889 */
12890 cds_restart_opportunistic_timer(false);
12891 if (cds_is_hw_mode_change_in_progress()) {
12892 status = qdf_wait_for_connection_update();
12893 if (!QDF_IS_STATUS_SUCCESS(status)) {
12894 hdd_err("qdf wait for event failed!!");
12895 status = -EINVAL;
12896 goto ret_status;
12897 }
12898 }
12899 cds_set_connection_in_progress(true);
12900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012901 if (HDD_WMM_USER_MODE_NO_QOS ==
12902 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12903 /*QoS not enabled in cfg file */
12904 pRoamProfile->uapsd_mask = 0;
12905 } else {
12906 /*QoS enabled, update uapsd mask from cfg file */
12907 pRoamProfile->uapsd_mask =
12908 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12909 }
12910
12911 pRoamProfile->SSIDs.numOfSSIDs = 1;
12912 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012913 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012914 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012915 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916 ssid, ssid_len);
12917
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012918 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012919 /* cleanup bssid hint */
12920 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12921 QDF_MAC_ADDR_SIZE);
12922 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12923 QDF_MAC_ADDR_SIZE);
12924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012925 if (bssid) {
12926 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012927 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012928 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012929 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012930 /*
12931 * Save BSSID in seperate variable as
12932 * pRoamProfile's BSSID is getting zeroed out in the
12933 * association process. In case of join failure
12934 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012936 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012937 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012938 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012939 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012940 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12941 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012942 /*
12943 * Save BSSID in a separate variable as
12944 * pRoamProfile's BSSID is getting zeroed out in the
12945 * association process. In case of join failure
12946 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012947 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012948 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012949 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012950 hdd_info("bssid_hint is given by upper layer %pM",
12951 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012952 }
12953
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012954 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955 pRoamProfile->SSIDs.SSIDList->SSID.length,
12956 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12957 operatingChannel);
12958
12959 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12960 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012962 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12963 }
12964#ifdef FEATURE_WLAN_WAPI
12965 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012966 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012967 switch (pAdapter->wapi_info.wapiAuthMode) {
12968 case WAPI_AUTH_MODE_PSK:
12969 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012970 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 pAdapter->wapi_info.wapiAuthMode);
12972 pRoamProfile->AuthType.authType[0] =
12973 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12974 break;
12975 }
12976 case WAPI_AUTH_MODE_CERT:
12977 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012978 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979 pAdapter->wapi_info.wapiAuthMode);
12980 pRoamProfile->AuthType.authType[0] =
12981 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12982 break;
12983 }
12984 } /* End of switch */
12985 if (pAdapter->wapi_info.wapiAuthMode ==
12986 WAPI_AUTH_MODE_PSK
12987 || pAdapter->wapi_info.wapiAuthMode ==
12988 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012989 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012990 pRoamProfile->AuthType.numEntries = 1;
12991 pRoamProfile->EncryptionType.numEntries = 1;
12992 pRoamProfile->EncryptionType.encryptionType[0] =
12993 eCSR_ENCRYPT_TYPE_WPI;
12994 pRoamProfile->mcEncryptionType.numEntries = 1;
12995 pRoamProfile->mcEncryptionType.
12996 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12997 }
12998 }
Krunal Soni31949422016-07-29 17:17:53 -070012999#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013000 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001 pRoamProfile->csrPersona = pAdapter->device_mode;
13002
13003 if (operatingChannel) {
13004 pRoamProfile->ChannelInfo.ChannelList =
13005 &operatingChannel;
13006 pRoamProfile->ChannelInfo.numOfChannels = 1;
13007 } else {
13008 pRoamProfile->ChannelInfo.ChannelList = NULL;
13009 pRoamProfile->ChannelInfo.numOfChannels = 0;
13010 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013011 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013012 && operatingChannel) {
13013 /*
13014 * Need to post the IBSS power save parameters
13015 * to WMA. WMA will configure this parameters
13016 * to firmware if power save is enabled by the
13017 * firmware.
13018 */
13019 status = hdd_set_ibss_power_save_params(pAdapter);
13020
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013021 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013022 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013023 status = -EINVAL;
13024 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013025 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013026 pRoamProfile->ch_params.ch_width =
13027 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013028 /*
13029 * In IBSS mode while operating in 2.4 GHz,
13030 * the device supports only 20 MHz.
13031 */
13032 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13033 pRoamProfile->ch_params.ch_width =
13034 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013035 hdd_select_cbmode(pAdapter, operatingChannel,
13036 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013037 }
Abhishek Singh99bce862016-06-20 15:10:51 +053013038 /*
13039 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13040 * or pmf=2 is an explicit configuration in the supplicant
13041 * configuration, drop the connection request.
13042 */
13043 if (pWextState->roamProfile.MFPEnabled &&
13044 !(pWextState->roamProfile.MFPRequired ||
13045 pWextState->roamProfile.MFPCapable)) {
13046 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13047 pWextState->roamProfile.MFPEnabled,
13048 pWextState->roamProfile.MFPRequired,
13049 pWextState->roamProfile.MFPCapable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013050
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013051 status = -EINVAL;
13052 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 }
13054
Krunal Soni31949422016-07-29 17:17:53 -070013055 /*
13056 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013057 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013058 * enhancements, the supplicant is not issuing the scan command
13059 * now. So the unicast frames which are sent from the host are
13060 * not having the additional IEs. If it is P2P CLIENT and there
13061 * is no additional IE present in roamProfile, then use the
13062 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 */
13064
Krunal Sonib4326f22016-03-10 13:05:51 -080013065 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066 (!pRoamProfile->pAddIEScan)) {
13067 pRoamProfile->pAddIEScan =
13068 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13069 pRoamProfile->nAddIEScanLength =
13070 pAdapter->scan_info.scanAddIE.length;
13071 }
13072 /*
13073 * When policy manager is enabled from ini file, we shouldn't
13074 * check for other concurrency rules.
13075 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013076 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013077 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013078 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013079 pAdapter, pRoamProfile, &roamId)) {
13080 status = 0;
13081 goto conn_failure;
13082 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013083 }
13084
Krunal Soni3091bcc2016-06-23 12:28:21 -070013085 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013086 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13087 pRoamProfile))) {
13088 hdd_err("sap-sta conc will fail, can't allow sta");
13089 hdd_conn_set_connection_state(pAdapter,
13090 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013091 status = -ENOMEM;
13092 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013093 }
13094
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013095 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 if (!sme_config) {
13097 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013098 hdd_conn_set_connection_state(pAdapter,
13099 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013100 status = -ENOMEM;
13101 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013103 sme_get_config_param(pHddCtx->hHal, sme_config);
13104 /* These values are not sessionized. So, any change in these SME
13105 * configs on an older or parallel interface will affect the
13106 * cb mode. So, restoring the default INI params before starting
13107 * interfaces such as sta, cli etc.,
13108 */
13109 sme_config->csrConfig.channelBondingMode5GHz =
13110 pHddCtx->config->nChannelBondingMode5GHz;
13111 sme_config->csrConfig.channelBondingMode24GHz =
13112 pHddCtx->config->nChannelBondingMode24GHz;
13113 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013114 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013115 /*
13116 * Change conn_state to connecting before sme_roam_connect(),
13117 * because sme_roam_connect() has a direct path to call
13118 * hdd_sme_roam_callback(), which will change the conn_state
13119 * If direct path, conn_state will be accordingly changed to
13120 * NotConnected or Associated by either
13121 * hdd_association_completion_handler() or
13122 * hdd_dis_connect_handler() in sme_RoamCallback()if
13123 * sme_RomConnect is to be queued,
13124 * Connecting state will remain until it is completed.
13125 *
13126 * If connection state is not changed, connection state will
13127 * remain in eConnectionState_NotConnected state.
13128 * In hdd_association_completion_handler, "hddDisconInProgress"
13129 * is set to true if conn state is
13130 * eConnectionState_NotConnected.
13131 * If "hddDisconInProgress" is set to true then cfg80211 layer
13132 * is not informed of connect result indication which
13133 * is an issue.
13134 */
13135 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013136 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013137 hdd_conn_set_connection_state(pAdapter,
13138 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013139
Komal Seelama89be8d2016-09-29 11:09:26 +053013140 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13141 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013142 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013143 pAdapter->sessionId, pRoamProfile,
13144 &roamId);
13145
Rajeev Kumard31e1542017-01-13 14:37:42 -080013146 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013147 (QDF_STA_MODE == pAdapter->device_mode ||
13148 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013149 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013150 "qdf_status %d. -> NotConnected",
13151 pAdapter->sessionId, qdf_status);
13152 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013153 /* change back to NotAssociated */
13154 hdd_conn_set_connection_state(pAdapter,
13155 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013156 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13157 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013158 }
13159
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013160 /* Reset connect_in_progress */
13161 cds_set_connection_in_progress(false);
13162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163 pRoamProfile->ChannelInfo.ChannelList = NULL;
13164 pRoamProfile->ChannelInfo.numOfChannels = 0;
13165
Nitesh Shah044fd672016-10-13 18:53:25 +053013166 if ((QDF_STA_MODE == pAdapter->device_mode)
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013167 && wma_is_current_hwmode_dbs() &&
13168 !wma_is_hw_dbs_2x2_capable()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013169 cds_get_channel_from_scan_result(pAdapter,
13170 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013171 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013172 if (channel)
13173 cds_checkn_update_hw_mode_single_mac_mode
13174 (channel);
13175 }
13176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013178 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013179 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013181 goto ret_status;
13182
13183conn_failure:
13184 /* Reset connect_in_progress */
13185 cds_set_connection_in_progress(false);
13186
13187ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 EXIT();
13189 return status;
13190}
13191
13192/**
13193 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13194 * @pAdapter: Pointer to adapter
13195 * @auth_type: Auth type
13196 *
13197 * This function is used to set the authentication type (OPEN/SHARED).
13198 *
13199 * Return: 0 for success, non-zero for failure
13200 */
13201static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13202 enum nl80211_auth_type auth_type)
13203{
13204 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13205 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 /*set authentication type */
13208 switch (auth_type) {
13209 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013210 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13212 break;
13213
13214 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013215 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013216 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13218 break;
13219
13220 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013221 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013222 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13223 break;
13224#ifdef FEATURE_WLAN_ESE
13225 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013226 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013227 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13228 break;
13229#endif
13230
13231 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013232 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13234 return -EINVAL;
13235 }
13236
13237 pWextState->roamProfile.AuthType.authType[0] =
13238 pHddStaCtx->conn_info.authType;
13239 return 0;
13240}
13241
13242/**
13243 * wlan_hdd_set_akm_suite() - set key management type
13244 * @pAdapter: Pointer to adapter
13245 * @key_mgmt: Key management type
13246 *
13247 * This function is used to set the key mgmt type(PSK/8021x).
13248 *
13249 * Return: 0 for success, non-zero for failure
13250 */
13251static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13252{
13253 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013255#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13256#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13257 /*set key mgmt type */
13258 switch (key_mgmt) {
13259 case WLAN_AKM_SUITE_PSK:
13260 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013261 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013262 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13264 break;
13265
13266 case WLAN_AKM_SUITE_8021X_SHA256:
13267 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013269 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013270 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13271 break;
13272#ifdef FEATURE_WLAN_ESE
13273#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13274#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13275 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013276 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013277 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13278 break;
13279#endif
13280#ifndef WLAN_AKM_SUITE_OSEN
13281#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13282#endif
13283 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013284 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013285 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13286 break;
13287
13288 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013289 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 return -EINVAL;
13291
13292 }
13293 return 0;
13294}
13295
13296/**
13297 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13298 * @pAdapter: Pointer to adapter
13299 * @cipher: Cipher type
13300 * @ucast: Unicast flag
13301 *
13302 * This function is used to set the encryption type
13303 * (NONE/WEP40/WEP104/TKIP/CCMP).
13304 *
13305 * Return: 0 for success, non-zero for failure
13306 */
13307static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13308 u32 cipher, bool ucast)
13309{
13310 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13311 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13312 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013315 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013316 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13317 } else {
13318
13319 /*set encryption method */
13320 switch (cipher) {
13321 case IW_AUTH_CIPHER_NONE:
13322 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13323 break;
13324
13325 case WLAN_CIPHER_SUITE_WEP40:
13326 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13327 break;
13328
13329 case WLAN_CIPHER_SUITE_WEP104:
13330 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13331 break;
13332
13333 case WLAN_CIPHER_SUITE_TKIP:
13334 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13335 break;
13336
13337 case WLAN_CIPHER_SUITE_CCMP:
13338 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13339 break;
13340#ifdef FEATURE_WLAN_WAPI
13341 case WLAN_CIPHER_SUITE_SMS4:
13342 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13343 break;
13344#endif
13345
13346#ifdef FEATURE_WLAN_ESE
13347 case WLAN_CIPHER_SUITE_KRK:
13348 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13349 break;
13350#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13351 case WLAN_CIPHER_SUITE_BTK:
13352 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13353 break;
13354#endif
13355#endif
13356 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013357 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 return -EOPNOTSUPP;
13359 }
13360 }
13361
13362 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013363 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13365 pWextState->roamProfile.EncryptionType.numEntries = 1;
13366 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13367 encryptionType;
13368 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013369 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13371 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13372 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13373 encryptionType;
13374 }
13375
13376 return 0;
13377}
13378
13379/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013380 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13381 * @wext_state: Pointer to wext state
13382 * @gen_ie: Pointer to IE data
13383 * @len: length of IE data
13384 *
13385 * Return: 0 for success, non-zero for failure
13386 */
13387static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13388 const uint8_t *gen_ie, uint16_t len)
13389{
13390 uint16_t cur_add_ie_len =
13391 wext_state->assocAddIE.length;
13392
13393 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13394 (wext_state->assocAddIE.length + len)) {
13395 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13396 QDF_ASSERT(0);
13397 return -ENOMEM;
13398 }
13399 memcpy(wext_state->assocAddIE.addIEdata +
13400 cur_add_ie_len, gen_ie, len);
13401 wext_state->assocAddIE.length += len;
13402
13403 wext_state->roamProfile.pAddIEAssoc =
13404 wext_state->assocAddIE.addIEdata;
13405 wext_state->roamProfile.nAddIEAssocLength =
13406 wext_state->assocAddIE.length;
13407 return 0;
13408}
13409
13410/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411 * wlan_hdd_cfg80211_set_ie() - set IEs
13412 * @pAdapter: Pointer to adapter
13413 * @ie: Pointer ot ie
13414 * @ie: IE length
13415 *
13416 * Return: 0 for success, non-zero for failure
13417 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013418static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013419 size_t ie_len)
13420{
13421 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13422 const uint8_t *genie = ie;
13423 uint16_t remLen = ie_len;
13424#ifdef FEATURE_WLAN_WAPI
13425 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13426 u16 *tmp;
13427 uint16_t akmsuiteCount;
13428 int *akmlist;
13429#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013430 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013431
13432 /* clear previous assocAddIE */
13433 pWextState->assocAddIE.length = 0;
13434 pWextState->roamProfile.bWPSAssociation = false;
13435 pWextState->roamProfile.bOSENAssociation = false;
13436
13437 while (remLen >= 2) {
13438 uint16_t eLen = 0;
13439 uint8_t elementId;
13440 elementId = *genie++;
13441 eLen = *genie++;
13442 remLen -= 2;
13443
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013444 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445
13446 switch (elementId) {
13447 case DOT11F_EID_WPA:
13448 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 -070013449 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013450 return -EINVAL;
13451 } else if (0 ==
13452 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13453 uint16_t curAddIELen =
13454 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013455 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456
13457 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13458 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013459 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013460 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013461 return -ENOMEM;
13462 }
13463 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13464 memcpy(pWextState->assocAddIE.addIEdata +
13465 curAddIELen, genie - 2, eLen + 2);
13466 pWextState->assocAddIE.length += eLen + 2;
13467
13468 pWextState->roamProfile.bWPSAssociation = true;
13469 pWextState->roamProfile.pAddIEAssoc =
13470 pWextState->assocAddIE.addIEdata;
13471 pWextState->roamProfile.nAddIEAssocLength =
13472 pWextState->assocAddIE.length;
13473 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013474 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013475 memset(pWextState->WPARSNIE, 0,
13476 MAX_WPA_RSN_IE_LEN);
13477 memcpy(pWextState->WPARSNIE, genie - 2,
13478 (eLen + 2));
13479 pWextState->roamProfile.pWPAReqIE =
13480 pWextState->WPARSNIE;
13481 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13482 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13483 P2P_OUI_TYPE_SIZE))) {
13484 uint16_t curAddIELen =
13485 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013486 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013487
13488 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13489 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013490 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013491 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 return -ENOMEM;
13493 }
13494 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13495 memcpy(pWextState->assocAddIE.addIEdata +
13496 curAddIELen, genie - 2, eLen + 2);
13497 pWextState->assocAddIE.length += eLen + 2;
13498
13499 pWextState->roamProfile.pAddIEAssoc =
13500 pWextState->assocAddIE.addIEdata;
13501 pWextState->roamProfile.nAddIEAssocLength =
13502 pWextState->assocAddIE.length;
13503 }
13504#ifdef WLAN_FEATURE_WFD
13505 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13506 WFD_OUI_TYPE_SIZE)) &&
13507 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013508 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013509 pAdapter->device_mode)) {
13510 uint16_t curAddIELen =
13511 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013512 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513
13514 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13515 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013516 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013517 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013518 return -ENOMEM;
13519 }
13520 /* WFD IE is saved to Additional IE ; it should
13521 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013522 * WFD IE
13523 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013524 memcpy(pWextState->assocAddIE.addIEdata +
13525 curAddIELen, genie - 2, eLen + 2);
13526 pWextState->assocAddIE.length += eLen + 2;
13527
13528 pWextState->roamProfile.pAddIEAssoc =
13529 pWextState->assocAddIE.addIEdata;
13530 pWextState->roamProfile.nAddIEAssocLength =
13531 pWextState->assocAddIE.length;
13532 }
13533#endif
13534 /* Appending HS 2.0 Indication Element in Assiciation Request */
13535 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13536 HS20_OUI_TYPE_SIZE))) {
13537 uint16_t curAddIELen =
13538 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013539 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013540
13541 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13542 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013543 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013544 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 return -ENOMEM;
13546 }
13547 memcpy(pWextState->assocAddIE.addIEdata +
13548 curAddIELen, genie - 2, eLen + 2);
13549 pWextState->assocAddIE.length += eLen + 2;
13550
13551 pWextState->roamProfile.pAddIEAssoc =
13552 pWextState->assocAddIE.addIEdata;
13553 pWextState->roamProfile.nAddIEAssocLength =
13554 pWextState->assocAddIE.length;
13555 }
13556 /* Appending OSEN Information Element in Assiciation Request */
13557 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13558 OSEN_OUI_TYPE_SIZE))) {
13559 uint16_t curAddIELen =
13560 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013561 hdd_notice("Set OSEN 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 memcpy(pWextState->assocAddIE.addIEdata +
13570 curAddIELen, genie - 2, eLen + 2);
13571 pWextState->assocAddIE.length += eLen + 2;
13572
13573 pWextState->roamProfile.bOSENAssociation = true;
13574 pWextState->roamProfile.pAddIEAssoc =
13575 pWextState->assocAddIE.addIEdata;
13576 pWextState->roamProfile.nAddIEAssocLength =
13577 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013578 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13579 MBO_OUI_TYPE_SIZE))){
13580 hdd_info("Set MBO IE(len %d)", eLen + 2);
13581 status = wlan_hdd_add_assoc_ie(pWextState,
13582 genie - 2, eLen + 2);
13583 if (status)
13584 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013585 } else {
13586 uint16_t add_ie_len =
13587 pWextState->assocAddIE.length;
13588
13589 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13590
13591 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13592 (pWextState->assocAddIE.length + eLen)) {
13593 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013594 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013595 return -ENOMEM;
13596 }
13597
13598 memcpy(pWextState->assocAddIE.addIEdata +
13599 add_ie_len, genie - 2, eLen + 2);
13600 pWextState->assocAddIE.length += eLen + 2;
13601
13602 pWextState->roamProfile.pAddIEAssoc =
13603 pWextState->assocAddIE.addIEdata;
13604 pWextState->roamProfile.nAddIEAssocLength =
13605 pWextState->assocAddIE.length;
13606 }
13607 break;
13608 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013609 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13611 memcpy(pWextState->WPARSNIE, genie - 2,
13612 (eLen + 2));
13613 pWextState->roamProfile.pRSNReqIE =
13614 pWextState->WPARSNIE;
13615 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13616 break;
13617 /*
13618 * Appending Extended Capabilities with Interworking bit set
13619 * in Assoc Req.
13620 *
13621 * In assoc req this EXT Cap will only be taken into account if
13622 * interworkingService bit is set to 1. Currently
13623 * driver is only interested in interworkingService capability
13624 * from supplicant. If in future any other EXT Cap info is
13625 * required from supplicat, it needs to be handled while
13626 * sending Assoc Req in LIM.
13627 */
13628 case DOT11F_EID_EXTCAP:
13629 {
13630 uint16_t curAddIELen =
13631 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013632 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013633
13634 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13635 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013636 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013637 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 return -ENOMEM;
13639 }
13640 memcpy(pWextState->assocAddIE.addIEdata +
13641 curAddIELen, genie - 2, eLen + 2);
13642 pWextState->assocAddIE.length += eLen + 2;
13643
13644 pWextState->roamProfile.pAddIEAssoc =
13645 pWextState->assocAddIE.addIEdata;
13646 pWextState->roamProfile.nAddIEAssocLength =
13647 pWextState->assocAddIE.length;
13648 break;
13649 }
13650#ifdef FEATURE_WLAN_WAPI
13651 case WLAN_EID_WAPI:
13652 /* Setting WAPI Mode to ON=1 */
13653 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013654 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655 tmp = (u16 *) ie;
13656 tmp = tmp + 2; /* Skip element Id and Len, Version */
13657 akmsuiteCount = WPA_GET_LE16(tmp);
13658 tmp = tmp + 1;
13659 akmlist = (int *)(tmp);
13660 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13661 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13662 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013663 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013664 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 return -EINVAL;
13666 }
13667
13668 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013669 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670 pAdapter->wapi_info.wapiAuthMode =
13671 WAPI_AUTH_MODE_PSK;
13672 }
13673 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013674 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013675 pAdapter->wapi_info.wapiAuthMode =
13676 WAPI_AUTH_MODE_CERT;
13677 }
13678 break;
13679#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013680 case DOT11F_EID_SUPPOPERATINGCLASSES:
13681 {
13682 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13683 status = wlan_hdd_add_assoc_ie(pWextState,
13684 genie - 2, eLen + 2);
13685 if (status)
13686 return status;
13687 break;
13688 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013689 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013690 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013691 /* when Unknown IE is received we break
13692 * and continue to the next IE in the buffer
13693 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 break;
13695 }
13696 genie += eLen;
13697 remLen -= eLen;
13698 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013699 return 0;
13700}
13701
13702/**
13703 * hdd_is_wpaie_present() - check for WPA ie
13704 * @ie: Pointer to ie
13705 * @ie_len: Ie length
13706 *
13707 * Parse the received IE to find the WPA IE
13708 *
13709 * Return: true if wpa ie is found else false
13710 */
13711static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13712{
13713 uint8_t eLen = 0;
13714 uint16_t remLen = ie_len;
13715 uint8_t elementId = 0;
13716
13717 while (remLen >= 2) {
13718 elementId = *ie++;
13719 eLen = *ie++;
13720 remLen -= 2;
13721 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013722 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 return false;
13724 }
13725 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13726 /* OUI - 0x00 0X50 0XF2
13727 * WPA Information Element - 0x01
13728 * WPA version - 0x01
13729 */
13730 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13731 return true;
13732 }
13733 ie += eLen;
13734 remLen -= eLen;
13735 }
13736 return false;
13737}
13738
13739/**
13740 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13741 * @pAdapter: Pointer to adapter
13742 * @req: Pointer to security parameters
13743 *
13744 * Return: 0 for success, non-zero for failure
13745 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013746static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13747 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748{
13749 int status = 0;
13750 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13751 ENTER();
13752
13753 /*set wpa version */
13754 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13755
13756 if (req->crypto.wpa_versions) {
13757 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13758 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13759 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13760 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13761 }
13762 }
13763
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013764 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013765
13766 /*set authentication type */
13767 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13768
13769 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013770 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013771 return status;
13772 }
13773
13774 /*set key mgmt type */
13775 if (req->crypto.n_akm_suites) {
13776 status =
13777 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13778 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013779 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 return status;
13781 }
13782 }
13783
13784 /*set pairwise cipher type */
13785 if (req->crypto.n_ciphers_pairwise) {
13786 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13787 req->crypto.
13788 ciphers_pairwise[0],
13789 true);
13790 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013791 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013792 return status;
13793 }
13794 } else {
13795 /*Reset previous cipher suite to none */
13796 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13797 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013798 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 return status;
13800 }
13801 }
13802
13803 /*set group cipher type */
13804 status =
13805 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13806 false);
13807
13808 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013809 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013810 return status;
13811 }
13812#ifdef WLAN_FEATURE_11W
13813 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13814#endif
13815
13816 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13817 if (req->ie_len) {
13818 status =
13819 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13820 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013821 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 return status;
13823 }
13824 }
13825
13826 /*incase of WEP set default key information */
13827 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013828 u8 key_len = req->key_len;
13829 u8 key_idx = req->key_idx;
13830
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13832 || (WLAN_CIPHER_SUITE_WEP104 ==
13833 req->crypto.ciphers_pairwise[0])
13834 ) {
13835 if (IW_AUTH_KEY_MGMT_802_1X
13836 ==
13837 (pWextState->
13838 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013839 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013841 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013842
Jeff Johnson68755312017-02-10 11:46:55 -080013843 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13844 && (CSR_MAX_NUM_KEY > key_idx)) {
13845 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13846 key_idx, key_len);
13847 qdf_mem_copy(&pWextState->roamProfile.
13848 Keys.
13849 KeyMaterial[key_idx][0],
13850 req->key, key_len);
13851 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013852 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013853 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013854 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 }
13856 }
13857 }
13858
13859 return status;
13860}
13861
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013862int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013863{
13864 unsigned long rc;
13865 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013866 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867
13868 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13869
Jeff Johnson9edf9572016-10-03 15:24:49 -070013870 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013871 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13872 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13873 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013874 hdd_conn_set_connection_state(pAdapter,
13875 eConnectionState_Disconnecting);
13876 /* Issue disconnect to CSR */
13877 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013878
13879 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13880 pAdapter->sessionId,
13881 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13882 /*
13883 * Wait here instead of returning directly, this will block the
13884 * next connect command and allow processing of the scan for
13885 * ssid and the previous connect command in CSR. Else we might
13886 * hit some race conditions leading to SME and HDD out of sync.
13887 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013888 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013889 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13890 } else if (0 != status) {
13891 hdd_err("csrRoamDisconnect failure, returned %d",
13892 (int)status);
13893 pHddStaCtx->staDebugState = status;
13894 result = -EINVAL;
13895 goto disconnected;
13896 }
13897
13898 rc = wait_for_completion_timeout(
13899 &pAdapter->disconnect_comp_var,
13900 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013901 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013902 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13903 pAdapter->sessionId, pHddStaCtx->staDebugState);
13904 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905 }
13906 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013907 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013909 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013910 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013911 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013913 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 }
13915 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013916disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013917 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13918 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919}
13920
13921/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013922 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13923 * @adapter: Pointer to the HDD adapter
13924 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013925 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013926 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013927 * This function will start reassociation if prev_bssid is set and bssid/
13928 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013929 *
Naveen Rawat07332902016-07-27 09:13:17 -070013930 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013931 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013932#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13933 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013934static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13935 struct cfg80211_connect_params *req,
13936 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013937{
Naveen Rawat07332902016-07-27 09:13:17 -070013938 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013939 const uint8_t *bssid = NULL;
13940 uint16_t channel = 0;
13941
13942 if (req->bssid)
13943 bssid = req->bssid;
13944 else if (req->bssid_hint)
13945 bssid = req->bssid_hint;
13946
13947 if (req->channel)
13948 channel = req->channel->hw_value;
13949 else if (req->channel_hint)
13950 channel = req->channel_hint->hw_value;
13951
13952 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013953 reassoc = true;
13954 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013955 channel, MAC_ADDR_ARRAY(bssid));
13956 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013957 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013958 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013959 }
Naveen Rawat07332902016-07-27 09:13:17 -070013960 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013961}
13962#else
Naveen Rawat07332902016-07-27 09:13:17 -070013963static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13964 struct cfg80211_connect_params *req,
13965 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013966{
Naveen Rawat07332902016-07-27 09:13:17 -070013967 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013968}
13969#endif
13970
13971/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013972 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13973 * @wiphy: Pointer to wiphy
13974 * @dev: Pointer to network device
13975 * @req: Pointer to cfg80211 connect request
13976 *
13977 * This function is used to start the association process
13978 *
13979 * Return: 0 for success, non-zero for failure
13980 */
13981static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13982 struct net_device *ndev,
13983 struct cfg80211_connect_params *req)
13984{
13985 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013986 u16 channel;
13987#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13988 const u8 *bssid_hint = req->bssid_hint;
13989#else
13990 const u8 *bssid_hint = NULL;
13991#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013992 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13993 hdd_context_t *pHddCtx;
13994
13995 ENTER();
13996
Anurag Chouhan6d760662016-02-20 16:05:43 +053013997 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013998 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013999 return -EINVAL;
14000 }
14001
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014002 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14003 hdd_err("invalid session id: %d", pAdapter->sessionId);
14004 return -EINVAL;
14005 }
14006
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014007 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014008 TRACE_CODE_HDD_CFG80211_CONNECT,
14009 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014010 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 hdd_device_mode_to_string(pAdapter->device_mode),
14012 pAdapter->device_mode);
14013
Krunal Sonib4326f22016-03-10 13:05:51 -080014014 if (pAdapter->device_mode != QDF_STA_MODE &&
14015 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014016 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014017 hdd_device_mode_to_string(pAdapter->device_mode),
14018 pAdapter->device_mode);
14019 return -EINVAL;
14020 }
14021
14022 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14023 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014024 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025 return -EINVAL;
14026 }
14027
14028 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014029 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014031
Naveen Rawat07332902016-07-27 09:13:17 -070014032 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014033 return status;
14034
Agrawal Ashishf156e942016-08-04 14:54:47 +053014035 /* Try disconnecting if already in connected state */
14036 status = wlan_hdd_try_disconnect(pAdapter);
14037 if (0 > status) {
14038 hdd_err("Failed to disconnect the existing connection");
14039 return -EALREADY;
14040 }
14041
14042 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014043 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014044 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014045 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 pAdapter->device_mode),
14047 req->channel->hw_value, HW_MODE_20_MHZ)) {
14048 hdd_err("This concurrency combination is not allowed");
14049 return -ECONNREFUSED;
14050 }
14051 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014052 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014053 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14055 hdd_err("This concurrency combination is not allowed");
14056 return -ECONNREFUSED;
14057 }
14058 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014059
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060 /*initialise security parameters */
14061 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14062
14063 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014064 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014065 return status;
14066 }
14067
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014068 if (req->channel)
14069 channel = req->channel->hw_value;
14070 else
14071 channel = 0;
14072 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14073 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014074 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014075 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014076 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 return status;
14078 }
14079 EXIT();
14080 return status;
14081}
14082
14083/**
14084 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14085 * @wiphy: Pointer to wiphy
14086 * @dev: Pointer to network device
14087 * @req: Pointer to cfg80211 connect request
14088 *
14089 * Return: 0 for success, non-zero for failure
14090 */
14091static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14092 struct net_device *ndev,
14093 struct cfg80211_connect_params *req)
14094{
14095 int ret;
14096 cds_ssr_protect(__func__);
14097 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14098 cds_ssr_unprotect(__func__);
14099
14100 return ret;
14101}
14102
14103/**
14104 * wlan_hdd_disconnect() - hdd disconnect api
14105 * @pAdapter: Pointer to adapter
14106 * @reason: Disconnect reason code
14107 *
14108 * This function is used to issue a disconnect request to SME
14109 *
14110 * Return: 0 for success, non-zero for failure
14111 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014112static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014113{
14114 int status, result = 0;
14115 unsigned long rc;
14116 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14117 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14118
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014119 ENTER();
14120
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014121 status = wlan_hdd_validate_context(pHddCtx);
14122
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014123 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014124 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014125
14126 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014127 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014128 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
14129 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014130 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014131 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14132 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14133
14134 /*issue disconnect */
14135
14136 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14137 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053014138 /*
14139 * Wait here instead of returning directly, this will block the next
14140 * connect command and allow processing of the scan for ssid and
14141 * the previous connect command in CSR. Else we might hit some
14142 * race conditions leading to SME and HDD out of sync.
14143 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014144 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014145 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014147 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014148 (int)status);
14149 pHddStaCtx->staDebugState = status;
14150 result = -EINVAL;
14151 goto disconnected;
14152 }
14153 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14154 msecs_to_jiffies
14155 (WLAN_WAIT_TIME_DISCONNECT));
14156
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014157 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014158 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 result = -ETIMEDOUT;
14160 }
14161disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014162 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14163#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14164 /* Sending disconnect event to userspace for kernel version < 3.11
14165 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14166 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014167 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014168 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14169 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170#endif
14171
14172 return result;
14173}
14174
14175/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014176 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14177 * @reason: ieee80211 reason code.
14178 *
14179 * This utility function helps log string conversion of reason code.
14180 *
14181 * Return: string conversion of reason code, if match found;
14182 * "Unknown" otherwise.
14183 */
14184static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14185{
14186 switch (reason) {
14187 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14188 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14189 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14190 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14191 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14192 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14193 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14194 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14195 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14196 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14197 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14198 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14199 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14200 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14201 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14202 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14203 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14204 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14205 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14206 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14207 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14208 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14209 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14210 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14211 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14212 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14213 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14214 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14215 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14216 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14217 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14218 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14219 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14220 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14221 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14222 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14223 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14224 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14225 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14226 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14227 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14228 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14229 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14230 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14231 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14232 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14233 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14234 default:
14235 return "Unknown";
14236 }
14237}
14238
14239/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014240 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14241 * @wiphy: Pointer to wiphy
14242 * @dev: Pointer to network device
14243 * @reason: Disconnect reason code
14244 *
14245 * This function is used to issue a disconnect request to SME
14246 *
14247 * Return: 0 for success, non-zero for failure
14248 */
14249static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14250 struct net_device *dev, u16 reason)
14251{
14252 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14253 int status;
14254 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14255 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14256#ifdef FEATURE_WLAN_TDLS
14257 uint8_t staIdx;
14258#endif
14259
14260 ENTER();
14261
Anurag Chouhan6d760662016-02-20 16:05:43 +053014262 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014263 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 return -EINVAL;
14265 }
14266
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014267 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14268 hdd_err("invalid session id: %d", pAdapter->sessionId);
14269 return -EINVAL;
14270 }
14271
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014272 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014273 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14274 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014275 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014276 hdd_device_mode_to_string(pAdapter->device_mode),
14277 pAdapter->device_mode, reason);
14278
14279 status = wlan_hdd_validate_context(pHddCtx);
14280
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080014281 if (hdd_is_roaming_in_progress()) {
14282 hdd_err("Roaming In Progress. Ignore!!!");
14283 return -EAGAIN;
14284 }
14285
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014286 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014288
14289 /* Issue disconnect request to SME, if station is in connected state */
14290 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14291 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14292 eCsrRoamDisconnectReason reasonCode =
14293 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14294 hdd_scaninfo_t *pScanInfo;
14295
14296 switch (reason) {
14297 case WLAN_REASON_MIC_FAILURE:
14298 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14299 break;
14300
14301 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14302 case WLAN_REASON_DISASSOC_AP_BUSY:
14303 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14304 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14305 break;
14306
14307 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14308 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14309 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14310 break;
14311
14312 case WLAN_REASON_DEAUTH_LEAVING:
14313 reasonCode =
14314 pHddCtx->config->
14315 gEnableDeauthToDisassocMap ?
14316 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14317 eCSR_DISCONNECT_REASON_DEAUTH;
14318 break;
14319 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14320 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14321 break;
14322 default:
14323 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14324 break;
14325 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014326 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014327 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328 pScanInfo = &pAdapter->scan_info;
14329 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014330 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014332 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 eCSR_SCAN_ABORT_DEFAULT);
14334 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014335 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014336#ifdef FEATURE_WLAN_TDLS
14337 /* First clean up the tdls peers if any */
14338 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14339 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14340 pAdapter->sessionId)
14341 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14342 uint8_t *mac;
14343 mac =
14344 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014345 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14346 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 pHddCtx->tdlsConnInfo[staIdx].staId,
14348 pAdapter->sessionId,
14349 MAC_ADDR_ARRAY(mac));
14350 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14351 (pAdapter),
14352 pAdapter->sessionId, mac);
14353 }
14354 }
14355#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014356 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014357 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014358 hdd_info("Disconnect request from user space with reason: %s",
14359 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014360 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14361 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014362 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014363 return -EINVAL;
14364 }
14365 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014366 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 pHddStaCtx->conn_info.connState);
14368 }
14369
14370 return status;
14371}
14372
14373/**
14374 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14375 * @wiphy: Pointer to wiphy
14376 * @dev: Pointer to network device
14377 * @reason: Disconnect reason code
14378 *
14379 * Return: 0 for success, non-zero for failure
14380 */
14381static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14382 struct net_device *dev, u16 reason)
14383{
14384 int ret;
14385 cds_ssr_protect(__func__);
14386 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14387 cds_ssr_unprotect(__func__);
14388
14389 return ret;
14390}
14391
14392/**
14393 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14394 * @pAdapter: Pointer to adapter
14395 * @param: Pointer to IBSS parameters
14396 *
14397 * This function is used to initialize the security settings in IBSS mode
14398 *
14399 * Return: 0 for success, non-zero for failure
14400 */
14401static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14402 struct cfg80211_ibss_params
14403 *params)
14404{
14405 int status = 0;
14406 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14407 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14408 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14409
14410 ENTER();
14411
14412 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014413 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014414 pHddStaCtx->ibss_enc_key_installed = 0;
14415
14416 if (params->ie_len && (NULL != params->ie)) {
14417 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14418 params->ie_len, WLAN_EID_RSN)) {
14419 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14420 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14421 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14422 tDot11fIEWPA dot11WPAIE;
14423 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14424 u8 *ie;
14425
14426 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14427 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14428 params->ie_len,
14429 DOT11F_EID_WPA);
14430 if (NULL != ie) {
14431 pWextState->wpaVersion =
14432 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014433 /* Unpack the WPA IE
14434 * Skip past the EID byte and length byte
14435 * and four byte WiFi OUI
14436 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014437 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14438 &ie[2 + 4],
14439 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014440 /* Extract the multicast cipher, the
14441 * encType for unicast cipher for
14442 * wpa-none is none
14443 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014444 encryptionType =
14445 hdd_translate_wpa_to_csr_encryption_type
14446 (dot11WPAIE.multicast_cipher);
14447 }
14448 }
14449
14450 status =
14451 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14452 params->ie_len);
14453
14454 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014455 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014456 return status;
14457 }
14458 }
14459
14460 pWextState->roamProfile.AuthType.authType[0] =
14461 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14462
14463 if (params->privacy) {
14464 /* Security enabled IBSS, At this time there is no information
14465 * available about the security paramters, so initialise the
14466 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14467 * The correct security parameters will be updated later in
14468 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14469 * set inorder enable privacy bit in beacons
14470 */
14471
14472 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14473 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014474 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14476 pWextState->roamProfile.EncryptionType.numEntries = 1;
14477 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14478 encryptionType;
14479 return status;
14480}
14481
14482/**
14483 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14484 * @wiphy: Pointer to wiphy
14485 * @dev: Pointer to network device
14486 * @param: Pointer to IBSS join parameters
14487 *
14488 * This function is used to create/join an IBSS network
14489 *
14490 * Return: 0 for success, non-zero for failure
14491 */
14492static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14493 struct net_device *dev,
14494 struct cfg80211_ibss_params *params)
14495{
14496 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14497 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14498 tCsrRoamProfile *pRoamProfile;
14499 int status;
14500 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14501 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014502 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014503 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014504
14505 ENTER();
14506
Anurag Chouhan6d760662016-02-20 16:05:43 +053014507 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014508 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014509 return -EINVAL;
14510 }
14511
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014512 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14513 hdd_err("invalid session id: %d", pAdapter->sessionId);
14514 return -EINVAL;
14515 }
14516
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014517 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014518 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14519 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014520 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014521 hdd_device_mode_to_string(pAdapter->device_mode),
14522 pAdapter->device_mode);
14523
14524 status = wlan_hdd_validate_context(pHddCtx);
14525
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014526 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014527 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014528
14529 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014530 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014531 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14532 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14533 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14534 int indx;
14535
14536 /* Get channel number */
14537 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 params->
14539 chandef.
14540 chan->
14541 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014542
14543 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14544 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014545 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014546 return -EOPNOTSUPP;
14547 }
14548
14549 for (indx = 0; indx < numChans; indx++) {
14550 if (channelNum == validChan[indx]) {
14551 break;
14552 }
14553 }
14554 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014555 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014556 return -EINVAL;
14557 }
14558 }
14559
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014560 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 HW_MODE_20_MHZ)) {
14562 hdd_err("This concurrency combination is not allowed");
14563 return -ECONNREFUSED;
14564 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565
Krunal Soni3091bcc2016-06-23 12:28:21 -070014566 status = qdf_reset_connection_update();
14567 if (!QDF_IS_STATUS_SUCCESS(status))
14568 hdd_err("ERR: clear event failed");
14569
14570 status = cds_current_connections_update(pAdapter->sessionId,
14571 channelNum,
14572 SIR_UPDATE_REASON_JOIN_IBSS);
14573 if (QDF_STATUS_E_FAILURE == status) {
14574 hdd_err("ERROR: connections update failed!!");
14575 return -EINVAL;
14576 }
14577
14578 if (QDF_STATUS_SUCCESS == status) {
14579 status = qdf_wait_for_connection_update();
14580 if (!QDF_IS_STATUS_SUCCESS(status)) {
14581 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 return -EINVAL;
14583 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584 }
14585
14586 /*Try disconnecting if already in connected state */
14587 status = wlan_hdd_try_disconnect(pAdapter);
14588 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014589 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590 return -EALREADY;
14591 }
14592
14593 pRoamProfile = &pWextState->roamProfile;
14594
14595 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014596 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014597 return -EINVAL;
14598 }
14599
14600 /* enable selected protection checks in IBSS mode */
14601 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014603 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014604 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14605 pHddCtx->config->
14606 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014607 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 }
14609
14610 /* BSSID is provided by upper layers hence no need to AUTO generate */
14611 if (NULL != params->bssid) {
14612 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014613 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014614 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615 return -EIO;
14616 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014617 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014618 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14619 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014620 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014621 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014622 return -EIO;
14623 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014624 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014625 }
14626 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14627 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14628 pRoamProfile->beaconInterval = params->beacon_interval;
14629 else {
14630 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014631 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632 params->beacon_interval, pRoamProfile->beaconInterval);
14633 }
14634
14635 /* Set Channel */
14636 if (channelNum) {
14637 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014638 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014639 pRoamProfile->ChannelInfo.numOfChannels = 1;
14640 pHddStaCtx->conn_info.operationChannel = channelNum;
14641 pRoamProfile->ChannelInfo.ChannelList =
14642 &pHddStaCtx->conn_info.operationChannel;
14643 }
14644
14645 /* Initialize security parameters */
14646 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14647 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014648 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014649 return status;
14650 }
14651
14652 /* Issue connect start */
14653 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14654 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014655 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014657 operationChannel,
14658 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014659
14660 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014661 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014662 return status;
14663 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014664 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014665 return 0;
14666}
14667
14668/**
14669 * wlan_hdd_cfg80211_join_ibss() - join ibss
14670 * @wiphy: Pointer to wiphy
14671 * @dev: Pointer to network device
14672 * @param: Pointer to IBSS join parameters
14673 *
14674 * This function is used to create/join an IBSS network
14675 *
14676 * Return: 0 for success, non-zero for failure
14677 */
14678static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14679 struct net_device *dev,
14680 struct cfg80211_ibss_params *params)
14681{
14682 int ret = 0;
14683
14684 cds_ssr_protect(__func__);
14685 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14686 cds_ssr_unprotect(__func__);
14687
14688 return ret;
14689}
14690
14691/**
14692 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14693 * @wiphy: Pointer to wiphy
14694 * @dev: Pointer to network device
14695 *
14696 * This function is used to leave an IBSS network
14697 *
14698 * Return: 0 for success, non-zero for failure
14699 */
14700static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14701 struct net_device *dev)
14702{
14703 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14704 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14705 tCsrRoamProfile *pRoamProfile;
14706 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14707 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014708 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014709 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014710 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711
14712 ENTER();
14713
Anurag Chouhan6d760662016-02-20 16:05:43 +053014714 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014715 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 return -EINVAL;
14717 }
14718
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014719 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14720 hdd_err("invalid session id: %d", pAdapter->sessionId);
14721 return -EINVAL;
14722 }
14723
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014724 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014725 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14726 pAdapter->sessionId,
14727 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14728 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014729 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014730 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014732 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733 hdd_device_mode_to_string(pAdapter->device_mode),
14734 pAdapter->device_mode);
14735 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014736 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014737 return -EIO;
14738 }
14739
14740 pRoamProfile = &pWextState->roamProfile;
14741
14742 /* Issue disconnect only if interface type is set to IBSS */
14743 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014744 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014745 return -EINVAL;
14746 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014747 /* Clearing add IE of beacon */
14748 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14749 sizeof(tSirMacAddr));
14750 updateIE.smeSessionId = pAdapter->sessionId;
14751 updateIE.ieBufferlength = 0;
14752 updateIE.pAdditionIEBuffer = NULL;
14753 updateIE.append = true;
14754 updateIE.notify = true;
14755 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14756 &updateIE,
14757 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014758 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014759 }
14760
14761 /* Reset WNI_CFG_PROBE_RSP Flags */
14762 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014763
14764 /* Issue Disconnect request */
14765 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14766 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14767 pAdapter->sessionId,
14768 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014769 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014770 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014771 hal_status);
14772 return -EAGAIN;
14773 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014774
14775 /* wait for mc thread to cleanup and then return to upper stack
14776 * so by the time upper layer calls the change interface, we are
14777 * all set to proceed further
14778 */
14779 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14780 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14781 if (!rc) {
14782 hdd_err("Failed to disconnect, timed out");
14783 return -ETIMEDOUT;
14784 }
14785
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014786 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014787 return 0;
14788}
14789
14790/**
14791 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14792 * @wiphy: Pointer to wiphy
14793 * @dev: Pointer to network device
14794 *
14795 * This function is used to leave an IBSS network
14796 *
14797 * Return: 0 for success, non-zero for failure
14798 */
14799static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14800 struct net_device *dev)
14801{
14802 int ret = 0;
14803
14804 cds_ssr_protect(__func__);
14805 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14806 cds_ssr_unprotect(__func__);
14807
14808 return ret;
14809}
14810
14811/**
14812 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14813 * @wiphy: Pointer to wiphy
14814 * @changed: Parameters changed
14815 *
14816 * This function is used to set the phy parameters. RTS Threshold/FRAG
14817 * Threshold/Retry Count etc.
14818 *
14819 * Return: 0 for success, non-zero for failure
14820 */
14821static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14822 u32 changed)
14823{
14824 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14825 tHalHandle hHal = pHddCtx->hHal;
14826 int status;
14827
14828 ENTER();
14829
Anurag Chouhan6d760662016-02-20 16:05:43 +053014830 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014831 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014832 return -EINVAL;
14833 }
14834
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014835 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014836 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14837 NO_SESSION, wiphy->rts_threshold));
14838 status = wlan_hdd_validate_context(pHddCtx);
14839
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014840 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014841 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014842
14843 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14844 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14845 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14846
14847 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14848 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014849 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 rts_threshold);
14851 return -EINVAL;
14852 }
14853
14854 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14855 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014856 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014857 rts_threshold);
14858 return -EIO;
14859 }
14860
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014861 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014862 }
14863
14864 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14865 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14866 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14867 wiphy->frag_threshold;
14868
14869 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14870 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014871 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014872 frag_threshold);
14873 return -EINVAL;
14874 }
14875
14876 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14877 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014878 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879 frag_threshold);
14880 return -EIO;
14881 }
14882
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014883 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014884 }
14885
14886 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14887 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14888 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14889 wiphy->retry_short : wiphy->retry_long;
14890
14891 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14892 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014893 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014894 return -EINVAL;
14895 }
14896
14897 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14898 if (0 != sme_cfg_set_int(hHal,
14899 WNI_CFG_LONG_RETRY_LIMIT,
14900 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014901 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014902 retry_value);
14903 return -EIO;
14904 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014905 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014906 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14907 if (0 != sme_cfg_set_int(hHal,
14908 WNI_CFG_SHORT_RETRY_LIMIT,
14909 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014910 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 retry_value);
14912 return -EIO;
14913 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014914 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014915 }
14916 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014917 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918 return 0;
14919}
14920
14921/**
14922 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14923 * @wiphy: Pointer to wiphy
14924 * @changed: Parameters changed
14925 *
14926 * Return: 0 for success, non-zero for failure
14927 */
14928static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14929{
14930 int ret;
14931
14932 cds_ssr_protect(__func__);
14933 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14934 cds_ssr_unprotect(__func__);
14935
14936 return ret;
14937}
14938
14939/**
14940 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14941 * key
14942 * @wiphy: Pointer to wiphy
14943 * @dev: Pointer to network device
14944 * @key_index: Key index
14945 *
14946 * Return: 0
14947 */
14948static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14949 struct net_device *netdev,
14950 u8 key_index)
14951{
14952 ENTER();
14953 return 0;
14954}
14955
14956/**
14957 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14958 * wlan_hdd_set_default_mgmt_key
14959 * @wiphy: pointer to wiphy
14960 * @netdev: pointer to net_device structure
14961 * @key_index: key index
14962 *
14963 * Return: 0 on success, error number on failure
14964 */
14965static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14966 struct net_device *netdev,
14967 u8 key_index)
14968{
14969 int ret;
14970
14971 cds_ssr_protect(__func__);
14972 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14973 cds_ssr_unprotect(__func__);
14974
14975 return ret;
14976}
14977
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978/**
14979 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14980 * @wiphy: Pointer to wiphy
14981 * @dev: Pointer to network device
14982 * @params: Pointer to tx queue parameters
14983 *
14984 * Return: 0
14985 */
14986static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14987 struct net_device *dev,
14988 struct ieee80211_txq_params *params)
14989{
14990 ENTER();
14991 return 0;
14992}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014993
14994/**
14995 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
14996 * @wiphy: pointer to wiphy
14997 * @netdev: pointer to net_device structure
14998 * @params: pointer to ieee80211_txq_params
14999 *
15000 * Return: 0 on success, error number on failure
15001 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15003 struct net_device *dev,
15004 struct ieee80211_txq_params *params)
15005{
15006 int ret;
15007
15008 cds_ssr_protect(__func__);
15009 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15010 cds_ssr_unprotect(__func__);
15011
15012 return ret;
15013}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015014
15015/**
15016 * __wlan_hdd_cfg80211_del_station() - delete station v2
15017 * @wiphy: Pointer to wiphy
15018 * @param: Pointer to delete station parameter
15019 *
15020 * Return: 0 for success, non-zero for failure
15021 */
15022static
15023int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15024 struct net_device *dev,
15025 struct tagCsrDelStaParams *pDelStaParams)
15026{
15027 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15028 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015029 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 hdd_hostapd_state_t *hapd_state;
15031 int status;
15032 uint8_t staId;
15033 uint8_t *mac;
15034
15035 ENTER();
15036
Anurag Chouhan6d760662016-02-20 16:05:43 +053015037 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015038 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 return -EINVAL;
15040 }
15041
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015042 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15043 hdd_err("invalid session id: %d", pAdapter->sessionId);
15044 return -EINVAL;
15045 }
15046
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015047 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015048 TRACE_CODE_HDD_CFG80211_DEL_STA,
15049 pAdapter->sessionId, pAdapter->device_mode));
15050
15051 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15052 status = wlan_hdd_validate_context(pHddCtx);
15053
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015054 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015055 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015056
15057 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15058
Krunal Sonib4326f22016-03-10 13:05:51 -080015059 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15060 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015061
15062 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15063 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015064 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015065 return 0;
15066 }
15067
Anurag Chouhanc5548422016-02-24 18:33:27 +053015068 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015069 uint16_t i;
15070 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15071 if ((pAdapter->aStaInfo[i].isUsed) &&
15072 (!pAdapter->aStaInfo[i].
15073 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015074 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075 mac,
15076 pAdapter->aStaInfo[i].
15077 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015078 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015079 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15080 hdd_ipa_wlan_evt(pAdapter,
15081 pAdapter->
15082 aStaInfo[i].
15083 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015084 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 mac);
15086 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015087 hdd_notice("Delete STA with MAC::"
15088 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015089 MAC_ADDR_ARRAY(mac));
15090
15091 if (pHddCtx->dev_dfs_cac_status ==
15092 DFS_CAC_IN_PROGRESS)
15093 goto fn_end;
15094
Wei Song2f76f642016-11-18 16:32:53 +080015095 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015097 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015098 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015099 hdd_softap_sta_deauth(pAdapter,
15100 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015101 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015102 pAdapter->aStaInfo[i].
15103 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015104 qdf_status =
15105 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015106 &hapd_state->
15107 qdf_sta_disassoc_event,
15108 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015109 if (!QDF_IS_STATUS_SUCCESS(
15110 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015111 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015112 }
15113 }
15114 }
15115 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015116 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015117 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015118 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015119 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015120 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015121 hdd_notice("Skip DEL STA as this is not used::"
15122 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015123 MAC_ADDR_ARRAY(mac));
15124 return -ENOENT;
15125 }
15126
15127 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15128 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015129 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015130 }
15131
15132 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15133 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015134 hdd_notice("Skip DEL STA as deauth is in progress::"
15135 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015136 MAC_ADDR_ARRAY(mac));
15137 return -ENOENT;
15138 }
15139
15140 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15141
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015142 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015143 MAC_ADDR_ARRAY(mac));
15144
15145 /* Case: SAP in ACS selected DFS ch and client connected
15146 * Now Radar detected. Then if random channel is another
15147 * DFS ch then new CAC is initiated and no TX allowed.
15148 * So do not send any mgmt frames as it will timeout
15149 * during CAC.
15150 */
15151
15152 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15153 goto fn_end;
15154
Wei Song2f76f642016-11-18 16:32:53 +080015155 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015156 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15157 (pAdapter), pAdapter->sessionId,
15158 (uint8_t *)&pDelStaParams->peerMacAddr,
15159 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015160 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015161 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015162 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163 pAdapter->aStaInfo[staId].isDeauthInProgress =
15164 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015165 hdd_notice("STA removal failed for ::"
15166 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015167 MAC_ADDR_ARRAY(mac));
15168 return -ENOENT;
15169 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015170 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015171 &hapd_state->
15172 qdf_sta_disassoc_event,
15173 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015174 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015175 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015176 }
15177 }
15178 }
15179
15180fn_end:
15181 EXIT();
15182 return 0;
15183}
15184
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015185#if defined(USE_CFG80211_DEL_STA_V2)
15186/**
15187 * wlan_hdd_del_station() - delete station wrapper
15188 * @adapter: pointer to the hdd adapter
15189 *
15190 * Return: None
15191 */
15192void wlan_hdd_del_station(hdd_adapter_t *adapter)
15193{
15194 struct station_del_parameters del_sta;
15195 del_sta.mac = NULL;
15196 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15197 del_sta.reason_code = eCsrForcedDeauthSta;
15198
15199 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15200 &del_sta);
15201}
15202#else
15203void wlan_hdd_del_station(hdd_adapter_t *adapter)
15204{
15205 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15206}
15207#endif
15208
15209#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015210/**
15211 * wlan_hdd_cfg80211_del_station() - delete station v2
15212 * @wiphy: Pointer to wiphy
15213 * @param: Pointer to delete station parameter
15214 *
15215 * Return: 0 for success, non-zero for failure
15216 */
15217int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15218 struct net_device *dev,
15219 struct station_del_parameters *param)
15220#else
15221/**
15222 * wlan_hdd_cfg80211_del_station() - delete station
15223 * @wiphy: Pointer to wiphy
15224 * @mac: Pointer to station mac address
15225 *
15226 * Return: 0 for success, non-zero for failure
15227 */
15228#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15229int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15230 struct net_device *dev,
15231 const uint8_t *mac)
15232#else
15233int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15234 struct net_device *dev,
15235 uint8_t *mac)
15236#endif
15237#endif
15238{
15239 int ret;
15240 struct tagCsrDelStaParams delStaParams;
15241
15242 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015243#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015244 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015245 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 return -EINVAL;
15247 }
15248 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15249 param->subtype, &delStaParams);
15250#else
15251 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15252 (SIR_MAC_MGMT_DEAUTH >> 4),
15253 &delStaParams);
15254#endif
15255 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15256 cds_ssr_unprotect(__func__);
15257
15258 return ret;
15259}
15260
15261/**
15262 * __wlan_hdd_cfg80211_add_station() - add station
15263 * @wiphy: Pointer to wiphy
15264 * @mac: Pointer to station mac address
15265 * @pmksa: Pointer to add station parameter
15266 *
15267 * Return: 0 for success, non-zero for failure
15268 */
15269static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15270 struct net_device *dev,
15271 const uint8_t *mac,
15272 struct station_parameters *params)
15273{
15274 int status = -EPERM;
15275#ifdef FEATURE_WLAN_TDLS
15276 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15277 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15278 u32 mask, set;
15279
15280 ENTER();
15281
Anurag Chouhan6d760662016-02-20 16:05:43 +053015282 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015283 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284 return -EINVAL;
15285 }
15286
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015287 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15288 hdd_err("invalid session id: %d", pAdapter->sessionId);
15289 return -EINVAL;
15290 }
15291
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015292 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 TRACE_CODE_HDD_CFG80211_ADD_STA,
15294 pAdapter->sessionId, params->listen_interval));
15295
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015296 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015297 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298
15299 mask = params->sta_flags_mask;
15300
15301 set = params->sta_flags_set;
15302
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015303 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 MAC_ADDR_ARRAY(mac));
15305
15306 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15307 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15308 status =
15309 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15310 }
15311 }
15312#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015313 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015314 return status;
15315}
15316
15317/**
15318 * wlan_hdd_cfg80211_add_station() - add station
15319 * @wiphy: Pointer to wiphy
15320 * @mac: Pointer to station mac address
15321 * @pmksa: Pointer to add station parameter
15322 *
15323 * Return: 0 for success, non-zero for failure
15324 */
15325#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15326static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15327 struct net_device *dev,
15328 const uint8_t *mac,
15329 struct station_parameters *params)
15330#else
15331static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15332 struct net_device *dev, uint8_t *mac,
15333 struct station_parameters *params)
15334#endif
15335{
15336 int ret;
15337
15338 cds_ssr_protect(__func__);
15339 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15340 cds_ssr_unprotect(__func__);
15341
15342 return ret;
15343}
15344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015345/**
15346 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15347 * @wiphy: Pointer to wiphy
15348 * @dev: Pointer to network device
15349 * @pmksa: Pointer to set pmksa parameter
15350 *
15351 * Return: 0 for success, non-zero for failure
15352 */
15353static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15354 struct net_device *dev,
15355 struct cfg80211_pmksa *pmksa)
15356{
15357 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15358 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15359 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015360 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015361 int status;
15362 tPmkidCacheInfo pmk_id;
15363
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015364 ENTER();
15365
Anurag Chouhan6d760662016-02-20 16:05:43 +053015366 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015367 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015368 return -EINVAL;
15369 }
15370
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015371 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15372 hdd_err("invalid session id: %d", pAdapter->sessionId);
15373 return -EINVAL;
15374 }
15375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015376 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015377 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015378 return -EINVAL;
15379 }
15380
15381 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015382 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015383 pmksa->bssid, pmksa->pmkid);
15384 return -EINVAL;
15385 }
15386
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015387 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015388 MAC_ADDR_ARRAY(pmksa->bssid));
15389
15390 status = wlan_hdd_validate_context(pHddCtx);
15391
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015392 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015393 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015394
15395 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15396
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015397 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15398 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015399
15400 /* Add to the PMKSA ID Cache in CSR */
15401 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15402 &pmk_id, 1, false);
15403
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015404 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015405 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15406 pAdapter->sessionId, result));
15407
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015408 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015409 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015410}
15411
15412/**
15413 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15414 * @wiphy: Pointer to wiphy
15415 * @dev: Pointer to network device
15416 * @pmksa: Pointer to set pmksa parameter
15417 *
15418 * Return: 0 for success, non-zero for failure
15419 */
15420static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15421 struct net_device *dev,
15422 struct cfg80211_pmksa *pmksa)
15423{
15424 int ret;
15425
15426 cds_ssr_protect(__func__);
15427 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15428 cds_ssr_unprotect(__func__);
15429
15430 return ret;
15431}
15432
15433/**
15434 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15435 * @wiphy: Pointer to wiphy
15436 * @dev: Pointer to network device
15437 * @pmksa: Pointer to pmksa parameter
15438 *
15439 * Return: 0 for success, non-zero for failure
15440 */
15441static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15442 struct net_device *dev,
15443 struct cfg80211_pmksa *pmksa)
15444{
15445 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15446 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15447 tHalHandle halHandle;
15448 int status = 0;
15449
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015450 ENTER();
15451
Anurag Chouhan6d760662016-02-20 16:05:43 +053015452 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015453 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015454 return -EINVAL;
15455 }
15456
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015457 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15458 hdd_err("invalid session id: %d", pAdapter->sessionId);
15459 return -EINVAL;
15460 }
15461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015462 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015463 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015464 return -EINVAL;
15465 }
15466
15467 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015468 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 return -EINVAL;
15470 }
15471
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015472 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015473 MAC_ADDR_ARRAY(pmksa->bssid));
15474
15475 status = wlan_hdd_validate_context(pHddCtx);
15476
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015477 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015478 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015479
15480 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15481
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015482 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015483 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15484 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015485 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015486 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015487 sme_roam_del_pmkid_from_cache(halHandle,
15488 pAdapter->sessionId, pmksa->bssid,
15489 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015490 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 MAC_ADDR_ARRAY(pmksa->bssid));
15492 status = -EINVAL;
15493 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015494 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015495 return status;
15496}
15497
15498/**
15499 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15500 * @wiphy: Pointer to wiphy
15501 * @dev: Pointer to network device
15502 * @pmksa: Pointer to pmksa parameter
15503 *
15504 * Return: 0 for success, non-zero for failure
15505 */
15506static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15507 struct net_device *dev,
15508 struct cfg80211_pmksa *pmksa)
15509{
15510 int ret;
15511
15512 cds_ssr_protect(__func__);
15513 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15514 cds_ssr_unprotect(__func__);
15515
15516 return ret;
15517
15518}
15519
15520/**
15521 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15522 * @wiphy: Pointer to wiphy
15523 * @dev: Pointer to network device
15524 *
15525 * Return: 0 for success, non-zero for failure
15526 */
15527static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15528 struct net_device *dev)
15529{
15530 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15531 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15532 tHalHandle halHandle;
15533 int status = 0;
15534
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015535 ENTER();
15536
Anurag Chouhan6d760662016-02-20 16:05:43 +053015537 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015538 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015539 return -EINVAL;
15540 }
15541
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015542 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15543 hdd_err("invalid session id: %d", pAdapter->sessionId);
15544 return -EINVAL;
15545 }
15546
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015547 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015548
15549 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15550 status = wlan_hdd_validate_context(pHddCtx);
15551
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015552 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015553 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015554
15555 /* Retrieve halHandle */
15556 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15557
15558 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015559 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015560 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15561 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015562 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015563 status = -EINVAL;
15564 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015565 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015566 return status;
15567}
15568
15569/**
15570 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15571 * @wiphy: Pointer to wiphy
15572 * @dev: Pointer to network device
15573 *
15574 * Return: 0 for success, non-zero for failure
15575 */
15576static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15577 struct net_device *dev)
15578{
15579 int ret;
15580
15581 cds_ssr_protect(__func__);
15582 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15583 cds_ssr_unprotect(__func__);
15584
15585 return ret;
15586}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015587
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015588#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015589/**
15590 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15591 * @wiphy: Pointer to wiphy
15592 * @dev: Pointer to network device
15593 * @ftie: Pointer to fast transition ie parameter
15594 *
15595 * Return: 0 for success, non-zero for failure
15596 */
15597static int
15598__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15599 struct net_device *dev,
15600 struct cfg80211_update_ft_ies_params *ftie)
15601{
15602 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15603 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15604 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15605 int status;
15606
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015607 ENTER();
15608
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015609 status = wlan_hdd_validate_context(hdd_ctx);
15610 if (status)
15611 return status;
15612
Anurag Chouhan6d760662016-02-20 16:05:43 +053015613 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015614 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015615 return -EINVAL;
15616 }
15617
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015618 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15619 hdd_err("invalid session id: %d", pAdapter->sessionId);
15620 return -EINVAL;
15621 }
15622
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015623 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015624 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15625 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15626 /* Added for debug on reception of Re-assoc Req. */
15627 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015628 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015629 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015630 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015631 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015632 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015633 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015634
15635 /* Pass the received FT IEs to SME */
15636 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15637 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015638 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015639 return 0;
15640}
15641
15642/**
15643 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15644 * @wiphy: Pointer to wiphy
15645 * @dev: Pointer to network device
15646 * @ftie: Pointer to fast transition ie parameter
15647 *
15648 * Return: 0 for success, non-zero for failure
15649 */
15650static int
15651wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15652 struct net_device *dev,
15653 struct cfg80211_update_ft_ies_params *ftie)
15654{
15655 int ret;
15656
15657 cds_ssr_protect(__func__);
15658 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15659 cds_ssr_unprotect(__func__);
15660
15661 return ret;
15662}
15663#endif
15664
Mukul Sharma3d36c392017-01-18 18:39:12 +053015665void wlan_hdd_cfg80211_update_replay_counter_callback(
15666 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15667
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015668{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015669 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15670 uint8_t temp_replay_counter[8];
15671 int i;
15672 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015673
15674 ENTER();
15675
Mukul Sharma3d36c392017-01-18 18:39:12 +053015676 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015677 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015678 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015679 }
15680
Mukul Sharma3d36c392017-01-18 18:39:12 +053015681 if (!gtk_rsp_param) {
15682 hdd_err("gtk_rsp_param is Null");
15683 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015684 }
15685
Mukul Sharma3d36c392017-01-18 18:39:12 +053015686 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015687 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015688 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015689 }
15690
Mukul Sharma3d36c392017-01-18 18:39:12 +053015691 hdd_notice("updated replay counter: %llu from fwr",
15692 gtk_rsp_param->replay_counter);
15693 /* convert little to big endian since supplicant works on big endian */
15694 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15695 for (i = 0; i < 8; i++)
15696 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015697
Mukul Sharma3d36c392017-01-18 18:39:12 +053015698 hdd_notice("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015699 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015700 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015701 gtk_rsp_param->bssid.bytes,
15702 temp_replay_counter, GFP_KERNEL);
15703out:
15704 EXIT();
15705
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015706}
15707
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015708static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015709int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015710 struct net_device *dev,
15711 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015712{
15713 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015714 int result, i;
15715 struct pmo_gtk_req *gtk_req = NULL;
15716 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15717 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015718 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719
15720 ENTER();
15721
Anurag Chouhan6d760662016-02-20 16:05:43 +053015722 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015723 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015724 result = -EINVAL;
15725 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015726 }
15727
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015728 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15729 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015730 result = -EINVAL;
15731 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015732 }
15733
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015734 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15736 pAdapter->sessionId, pAdapter->device_mode));
15737
Mukul Sharma3d36c392017-01-18 18:39:12 +053015738 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015739 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015740 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741
Mukul Sharma3d36c392017-01-18 18:39:12 +053015742 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15743 if (!gtk_req) {
15744 hdd_err("cannot allocate gtk_req");
15745 result = -ENOMEM;
15746 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015747 }
15748
Mukul Sharma3d36c392017-01-18 18:39:12 +053015749 /* convert big to little endian since driver work on little endian */
15750 buf = (uint8_t *)&gtk_req->replay_counter;
15751 for (i = 0; i < 8; i++)
15752 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015753
Mukul Sharma3d36c392017-01-18 18:39:12 +053015754 hdd_notice("current replay counter: %llu in user space",
15755 gtk_req->replay_counter);
15756 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15757 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15758 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15759 if (status != QDF_STATUS_SUCCESS) {
15760 hdd_err("Failed to cache GTK Offload");
15761 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015762 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015763out:
15764 if (gtk_req)
15765 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015766 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015767
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015768 return result;
15769}
15770
15771/**
15772 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15773 * @wiphy: Pointer to wiphy
15774 * @dev: Pointer to network device
15775 * @data: Pointer to rekey data
15776 *
15777 * This function is used to offload GTK rekeying job to the firmware.
15778 *
15779 * Return: 0 for success, non-zero for failure
15780 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015781static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015782int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15783 struct net_device *dev,
15784 struct cfg80211_gtk_rekey_data *data)
15785{
15786 int ret;
15787
15788 cds_ssr_protect(__func__);
15789 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15790 cds_ssr_unprotect(__func__);
15791
15792 return ret;
15793}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015794
15795/**
15796 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15797 * @wiphy: Pointer to wiphy
15798 * @dev: Pointer to network device
15799 * @param: Pointer to access control parameter
15800 *
15801 * Return: 0 for success, non-zero for failure
15802 */
15803static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15804 struct net_device *dev,
15805 const struct cfg80211_acl_data *params)
15806{
15807 int i;
15808 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15809 hdd_hostapd_state_t *pHostapdState;
15810 tsap_Config_t *pConfig;
15811 v_CONTEXT_t p_cds_context = NULL;
15812 hdd_context_t *pHddCtx;
15813 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015814 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015815
15816 ENTER();
15817
Anurag Chouhan6d760662016-02-20 16:05:43 +053015818 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015819 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015820 return -EINVAL;
15821 }
15822
15823 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015824 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825 return -EINVAL;
15826 }
15827
15828 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15829 status = wlan_hdd_validate_context(pHddCtx);
15830
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015831 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015832 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015833
15834 p_cds_context = pHddCtx->pcds_context;
15835 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15836
15837 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015838 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015839 return -EINVAL;
15840 }
15841
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015842 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015843 params->n_acl_entries);
15844
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015845 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015846 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15847 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015848 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15850
15851 /* default value */
15852 pConfig->num_accept_mac = 0;
15853 pConfig->num_deny_mac = 0;
15854
15855 /**
15856 * access control policy
15857 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15858 * listed in hostapd.deny file.
15859 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15860 * listed in hostapd.accept file.
15861 */
15862 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15863 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15864 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15865 params->acl_policy) {
15866 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15867 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015868 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015869 params->acl_policy);
15870 return -ENOTSUPP;
15871 }
15872
15873 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15874 pConfig->num_accept_mac = params->n_acl_entries;
15875 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015876 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15877 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015878 MAC_ADDR_ARRAY(
15879 params->mac_addrs[i].addr));
15880
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015881 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015882 params->mac_addrs[i].addr,
15883 sizeof(qcmacaddr));
15884 }
15885 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15886 pConfig->num_deny_mac = params->n_acl_entries;
15887 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015888 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15889 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015890 MAC_ADDR_ARRAY(
15891 params->mac_addrs[i].addr));
15892
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015893 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894 params->mac_addrs[i].addr,
15895 sizeof(qcmacaddr));
15896 }
15897 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015898 qdf_status = wlansap_set_mac_acl(
15899 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015900 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015901 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015902 return -EINVAL;
15903 }
15904 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015905 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015906 hdd_device_mode_to_string(pAdapter->device_mode),
15907 pAdapter->device_mode);
15908 return -EINVAL;
15909 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015910 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015911 return 0;
15912}
15913
15914/**
15915 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15916 * __wlan_hdd_cfg80211_set_mac_acl
15917 * @wiphy: pointer to wiphy structure
15918 * @dev: pointer to net_device
15919 * @params: pointer to cfg80211_acl_data
15920 *
15921 * Return; 0 on success, error number otherwise
15922 */
15923static int
15924wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15925 struct net_device *dev,
15926 const struct cfg80211_acl_data *params)
15927{
15928 int ret;
15929
15930 cds_ssr_protect(__func__);
15931 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15932 cds_ssr_unprotect(__func__);
15933
15934 return ret;
15935}
15936
15937#ifdef WLAN_NL80211_TESTMODE
15938#ifdef FEATURE_WLAN_LPHB
15939/**
15940 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15941 * @pHddCtx: Pointer to hdd context
15942 * @lphbInd: Pointer to low power heart beat indication parameter
15943 *
15944 * Return: none
15945 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015946static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15947 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015948{
15949 struct sk_buff *skb;
15950
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015951 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015952
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015953 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015954 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015955
15956 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015957 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015958 return;
15959 }
15960
15961 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15962 wiphy, sizeof(tSirLPHBInd),
15963 GFP_ATOMIC);
15964 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015965 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015966 return;
15967 }
15968
15969 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015970 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015971 goto nla_put_failure;
15972 }
15973 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015974 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015975 goto nla_put_failure;
15976 }
15977 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015978 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015979 goto nla_put_failure;
15980 }
15981 cfg80211_testmode_event(skb, GFP_ATOMIC);
15982 return;
15983
15984nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015985 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015986 kfree_skb(skb);
15987
15988 return;
15989}
15990#endif /* FEATURE_WLAN_LPHB */
15991
15992/**
15993 * __wlan_hdd_cfg80211_testmode() - test mode
15994 * @wiphy: Pointer to wiphy
15995 * @data: Data pointer
15996 * @len: Data length
15997 *
15998 * Return: 0 for success, non-zero for failure
15999 */
16000static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16001 void *data, int len)
16002{
16003 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16004 int err;
16005 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16006
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016007 ENTER();
16008
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016009 err = wlan_hdd_validate_context(pHddCtx);
16010 if (err)
16011 return err;
16012
16013 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16014 len, wlan_hdd_tm_policy);
16015 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016016 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017 return err;
16018 }
16019
16020 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016021 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016022 return -EINVAL;
16023 }
16024
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016025 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016026 TRACE_CODE_HDD_CFG80211_TESTMODE,
16027 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016028 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16029#ifdef FEATURE_WLAN_LPHB
16030 /* Low Power Heartbeat configuration request */
16031 case WLAN_HDD_TM_CMD_WLAN_HB:
16032 {
16033 int buf_len;
16034 void *buf;
16035 tSirLPHBReq *hb_params = NULL;
16036 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016037 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016038
16039 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016040 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016041 return -EINVAL;
16042 }
16043
16044 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16045 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16046
16047 hb_params_temp = (tSirLPHBReq *) buf;
16048 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16049 && (hb_params_temp->params.lphbTcpParamReq.
16050 timePeriodSec == 0))
16051 return -EINVAL;
16052
16053 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016054 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016055 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016056 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 return -ENOMEM;
16058 }
16059
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016060 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016061 smeStatus =
16062 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16063 hb_params,
16064 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016065 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016066 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016067 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016068 }
16069 return 0;
16070 }
16071#endif /* FEATURE_WLAN_LPHB */
16072
16073#if defined(QCA_WIFI_FTM)
16074 case WLAN_HDD_TM_CMD_WLAN_FTM:
16075 {
16076 int buf_len;
16077 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016078 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016079 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016080 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016081 return -EINVAL;
16082 }
16083
16084 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16085 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16086
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016087 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016088
16089 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016091 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092 err = -EBUSY;
16093 break;
16094 }
16095#endif
16096
16097 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016098 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016099 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16100 return -EOPNOTSUPP;
16101 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016102 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016103 return err;
16104}
16105
16106/**
16107 * wlan_hdd_cfg80211_testmode() - test mode
16108 * @wiphy: Pointer to wiphy
16109 * @dev: Pointer to network device
16110 * @data: Data pointer
16111 * @len: Data length
16112 *
16113 * Return: 0 for success, non-zero for failure
16114 */
16115static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16116#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16117 struct wireless_dev *wdev,
16118#endif
16119 void *data, int len)
16120{
16121 int ret;
16122
16123 cds_ssr_protect(__func__);
16124 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16125 cds_ssr_unprotect(__func__);
16126
16127 return ret;
16128}
16129
16130#if defined(QCA_WIFI_FTM)
16131/**
16132 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16133 * @buf: Pointer to buffer
16134 * @buf_len: Buffer length
16135 *
16136 * Return: none
16137 */
16138void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16139{
16140 struct sk_buff *skb;
16141 hdd_context_t *hdd_ctx;
16142
16143 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016144 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016145 return;
16146 }
16147
Anurag Chouhan6d760662016-02-20 16:05:43 +053016148 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016149 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016150 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016151 return;
16152 }
16153
16154 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16155 buf_len, GFP_KERNEL);
16156 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016157 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016158 return;
16159 }
16160
16161 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16162 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16163 goto nla_put_failure;
16164
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016165 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166
16167 cfg80211_testmode_event(skb, GFP_KERNEL);
16168 return;
16169
16170nla_put_failure:
16171 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016172 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016173}
16174#endif
16175#endif /* CONFIG_NL80211_TESTMODE */
16176
16177#ifdef QCA_HT_2040_COEX
16178/**
16179 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16180 * @wiphy: Pointer to wiphy
16181 * @dev: Pointer to network device
16182 * @chandef: Pointer to channel definition parameter
16183 *
16184 * Return: 0 for success, non-zero for failure
16185 */
16186static int
16187__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16188 struct net_device *dev,
16189 struct cfg80211_chan_def *chandef)
16190{
16191 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16192 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016193 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016194 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016195 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016196
Anurag Chouhan6d760662016-02-20 16:05:43 +053016197 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016198 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016199 return -EINVAL;
16200 }
16201
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016202 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16203 hdd_err("invalid session id: %d", pAdapter->sessionId);
16204 return -EINVAL;
16205 }
16206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016207 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16208 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016209 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016211
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016212 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016213 sme_get_config_param(pHddCtx->hHal, &sme_config);
16214 switch (chandef->width) {
16215 case NL80211_CHAN_WIDTH_20:
16216 if (sme_config.csrConfig.channelBondingMode24GHz !=
16217 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16218 sme_config.csrConfig.channelBondingMode24GHz =
16219 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16220 sme_update_config(pHddCtx->hHal, &sme_config);
16221 cbModeChange = true;
16222 }
16223 break;
16224
16225 case NL80211_CHAN_WIDTH_40:
16226 if (sme_config.csrConfig.channelBondingMode24GHz ==
16227 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16228 if (NL80211_CHAN_HT40MINUS ==
16229 cfg80211_get_chandef_type(chandef))
16230 sme_config.csrConfig.channelBondingMode24GHz =
16231 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16232 else
16233 sme_config.csrConfig.channelBondingMode24GHz =
16234 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16235 sme_update_config(pHddCtx->hHal, &sme_config);
16236 cbModeChange = true;
16237 }
16238 break;
16239
16240 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016241 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016242 return -EINVAL;
16243 }
16244
16245 if (!cbModeChange)
16246 return 0;
16247
Krunal Sonib4326f22016-03-10 13:05:51 -080016248 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 return 0;
16250
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016251 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016252 sme_config.csrConfig.channelBondingMode24GHz);
16253
16254 /* Change SAP ht2040 mode */
16255 status = hdd_set_sap_ht2040_mode(pAdapter,
16256 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016257 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016258 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016259 return -EINVAL;
16260 }
16261
16262 return 0;
16263}
16264
16265/**
16266 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16267 * @wiphy: Pointer to wiphy
16268 * @dev: Pointer to network device
16269 * @chandef: Pointer to channel definition parameter
16270 *
16271 * Return: 0 for success, non-zero for failure
16272 */
16273static int
16274wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16275 struct net_device *dev,
16276 struct cfg80211_chan_def *chandef)
16277{
16278 int ret;
16279
16280 cds_ssr_protect(__func__);
16281 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16282 cds_ssr_unprotect(__func__);
16283
16284 return ret;
16285}
16286#endif
16287
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016288#ifdef CHANNEL_SWITCH_SUPPORTED
16289/**
16290 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16291 * channel in SAP/GO
16292 * @wiphy: wiphy pointer
16293 * @dev: dev pointer.
16294 * @csa_params: Change channel params
16295 *
16296 * This function is called to switch channel in SAP/GO
16297 *
16298 * Return: 0 if success else return non zero
16299 */
16300static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16301 struct net_device *dev,
16302 struct cfg80211_csa_settings *csa_params)
16303{
16304 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16305 hdd_context_t *hdd_ctx;
16306 uint8_t channel;
16307 uint16_t freq;
16308 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016309 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016310
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016311 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016312 csa_params->chandef.chan->center_freq);
16313
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016314 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16315 hdd_err("invalid session id: %d", adapter->sessionId);
16316 return -EINVAL;
16317 }
16318
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016319 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16320 ret = wlan_hdd_validate_context(hdd_ctx);
16321
16322 if (0 != ret)
16323 return ret;
16324
Krunal Sonib4326f22016-03-10 13:05:51 -080016325 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16326 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016327 return -ENOTSUPP;
16328
16329 freq = csa_params->chandef.chan->center_freq;
16330 channel = cds_freq_to_chan(freq);
16331
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016332 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16333
16334 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016335 return ret;
16336}
16337
16338/**
16339 * wlan_hdd_cfg80211_channel_switch()- function to switch
16340 * channel in SAP/GO
16341 * @wiphy: wiphy pointer
16342 * @dev: dev pointer.
16343 * @csa_params: Change channel params
16344 *
16345 * This function is called to switch channel in SAP/GO
16346 *
16347 * Return: 0 if success else return non zero
16348 */
16349static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16350 struct net_device *dev,
16351 struct cfg80211_csa_settings *csa_params)
16352{
16353 int ret;
16354
16355 cds_ssr_protect(__func__);
16356 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16357 cds_ssr_unprotect(__func__);
16358 return ret;
16359}
16360#endif
16361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016362/**
16363 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16364 * translation from NL to policy manager type
16365 * @type: Generic connection mode type defined in NL
16366 *
16367 *
16368 * This function provides the type translation
16369 *
16370 * Return: cds_con_mode enum
16371 */
16372enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16373 enum nl80211_iftype type)
16374{
16375 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16376 switch (type) {
16377 case NL80211_IFTYPE_STATION:
16378 mode = CDS_STA_MODE;
16379 break;
16380 case NL80211_IFTYPE_P2P_CLIENT:
16381 mode = CDS_P2P_CLIENT_MODE;
16382 break;
16383 case NL80211_IFTYPE_P2P_GO:
16384 mode = CDS_P2P_GO_MODE;
16385 break;
16386 case NL80211_IFTYPE_AP:
16387 mode = CDS_SAP_MODE;
16388 break;
16389 case NL80211_IFTYPE_ADHOC:
16390 mode = CDS_IBSS_MODE;
16391 break;
16392 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016393 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016394 type);
16395 }
16396 return mode;
16397}
16398
16399/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016400 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16401 * @wiphy: Handle to struct wiphy to get handle to module context.
16402 * @chandef: Contains information about the capture channel to be set.
16403 *
16404 * This interface is called if and only if monitor mode interface alone is
16405 * active.
16406 *
16407 * Return: 0 success or error code on failure.
16408 */
16409static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16410 struct cfg80211_chan_def *chandef)
16411{
16412 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16413 hdd_adapter_t *adapter;
16414 hdd_station_ctx_t *sta_ctx;
16415 struct hdd_mon_set_ch_info *ch_info;
16416 QDF_STATUS status;
16417 tHalHandle hal_hdl;
16418 struct qdf_mac_addr bssid;
16419 tCsrRoamProfile roam_profile;
16420 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016421 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016422 int ret;
16423 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16424
16425 ENTER();
16426
16427 ret = wlan_hdd_validate_context(hdd_ctx);
16428 if (ret)
16429 return ret;
16430
16431 hal_hdl = hdd_ctx->hHal;
16432
16433 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16434 if (!adapter)
16435 return -EIO;
16436
16437 hdd_info("%s: set monitor mode Channel %d and freq %d",
16438 adapter->dev->name, chan_num, chandef->chan->center_freq);
16439
16440 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16441 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016442 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16443 roam_profile.ChannelInfo.numOfChannels = 1;
16444 roam_profile.phyMode = ch_info->phy_mode;
16445 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016446 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016447
16448 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16449 QDF_MAC_ADDR_SIZE);
16450
16451 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016452 /*
16453 * CDS api expects secondary channel for calculating
16454 * the channel params
16455 */
16456 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16457 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16458 if (chan_num >= 1 && chan_num <= 5)
16459 sec_ch = chan_num + 4;
16460 else if (chan_num >= 6 && chan_num <= 13)
16461 sec_ch = chan_num - 4;
16462 }
16463 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016464 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16465 &roam_profile);
16466 if (status) {
16467 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16468 status);
16469 ret = qdf_status_to_os_return(status);
16470 return ret;
16471 }
16472 EXIT();
16473 return 0;
16474}
16475
16476/**
16477 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16478 * @wiphy: Handle to struct wiphy to get handle to module context.
16479 * @chandef: Contains information about the capture channel to be set.
16480 *
16481 * This interface is called if and only if monitor mode interface alone is
16482 * active.
16483 *
16484 * Return: 0 success or error code on failure.
16485 */
16486static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16487 struct cfg80211_chan_def *chandef)
16488{
16489 int ret;
16490
16491 cds_ssr_protect(__func__);
16492 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16493 cds_ssr_unprotect(__func__);
16494 return ret;
16495}
16496
16497/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016498 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16499 * @adapter: pointer to adapter
16500 *
16501 * Wrapper function to clear link layer stats.
16502 * return - void
16503 */
16504void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16505{
16506 tSirLLStatsClearReq link_layer_stats_clear_req;
16507 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16508
Mukul Sharma491021c2016-09-29 21:39:19 +053016509 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16510 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016511 link_layer_stats_clear_req.stopReq = 0;
16512 link_layer_stats_clear_req.reqId = 1;
16513 link_layer_stats_clear_req.staId = adapter->sessionId;
16514 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16515
16516 return;
16517}
16518
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016519#define CNT_DIFF(cur, prev) \
16520 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16521#define MAX_COUNT 0xffffffff
16522static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16523 struct scan_chan_info *chan,
16524 struct scan_chan_info *info, uint32_t cmd_flag)
16525{
16526 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16527 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16528 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16529
16530 mutex_lock(&hdd_ctx->chan_info_lock);
16531
16532 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16533 qdf_mem_zero(chan, sizeof(*chan));
16534
16535 chan->freq = info->freq;
16536 chan->noise_floor = info->noise_floor;
16537 chan->clock_freq = info->clock_freq;
16538 chan->cmd_flag = info->cmd_flag;
16539 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16540
16541 chan->rx_clear_count =
16542 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16543
16544 chan->tx_frame_count =
16545 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16546
16547 mutex_unlock(&hdd_ctx->chan_info_lock);
16548
16549}
16550#undef CNT_DIFF
16551#undef MAX_COUNT
16552
16553/**
16554 * wlan_hdd_chan_info_cb() - channel info callback
16555 * @chan_info: struct scan_chan_info
16556 *
16557 * Store channel info into HDD context
16558 *
16559 * Return: None.
16560 */
16561static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16562{
16563 hdd_context_t *hdd_ctx;
16564 struct scan_chan_info *chan;
16565 uint8_t idx;
16566
16567 ENTER();
16568
16569 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16570 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16571 hdd_err("hdd_ctx is invalid");
16572 return;
16573 }
16574
16575 if (!hdd_ctx->chan_info) {
16576 hdd_err("chan_info is NULL");
16577 return;
16578 }
16579
16580 chan = hdd_ctx->chan_info;
16581 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16582 if (chan[idx].freq == info->freq) {
16583 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16584 info->cmd_flag);
16585 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16586 chan[idx].cmd_flag, chan[idx].freq,
16587 chan[idx].noise_floor,
16588 chan[idx].cycle_count, chan[idx].rx_clear_count,
16589 chan[idx].clock_freq, chan[idx].cmd_flag,
16590 chan[idx].tx_frame_count, idx);
16591 if (chan[idx].freq == 0)
16592 break;
16593
16594 }
16595 }
16596
16597 EXIT();
16598}
16599
16600/**
16601 * wlan_hdd_init_chan_info() - init chan info in hdd context
16602 * @hdd_ctx: HDD context pointer
16603 *
16604 * Return: none
16605 */
16606void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16607{
16608 uint8_t num_2g, num_5g, index = 0;
16609
16610 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16611 hdd_info("SNR monitoring is disabled");
16612 return;
16613 }
16614
16615 hdd_ctx->chan_info =
16616 qdf_mem_malloc(sizeof(struct scan_chan_info)
16617 * QDF_MAX_NUM_CHAN);
16618 if (hdd_ctx->chan_info == NULL) {
16619 hdd_err("Failed to malloc for chan info");
16620 return;
16621 }
16622 mutex_init(&hdd_ctx->chan_info_lock);
16623
16624 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16625 for (; index < num_2g; index++) {
16626 hdd_ctx->chan_info[index].freq =
16627 hdd_channels_2_4_ghz[index].center_freq;
16628 }
16629
16630 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16631 for (; (index - num_2g) < num_5g; index++) {
16632 if (cds_is_dsrc_channel(
16633 hdd_channels_5_ghz[index - num_2g].center_freq))
16634 continue;
16635 hdd_ctx->chan_info[index].freq =
16636 hdd_channels_5_ghz[index - num_2g].center_freq;
16637 }
16638 sme_set_chan_info_callback(hdd_ctx->hHal,
16639 &wlan_hdd_chan_info_cb);
16640}
16641
16642/**
16643 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16644 * @hdd_ctx: hdd context pointer
16645 *
16646 * Return: none
16647 */
16648void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16649{
16650 struct scan_chan_info *chan;
16651
16652 chan = hdd_ctx->chan_info;
16653 hdd_ctx->chan_info = NULL;
16654 if (chan)
16655 qdf_mem_free(chan);
16656}
16657
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016658/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016659 * struct cfg80211_ops - cfg80211_ops
16660 *
16661 * @add_virtual_intf: Add virtual interface
16662 * @del_virtual_intf: Delete virtual interface
16663 * @change_virtual_intf: Change virtual interface
16664 * @change_station: Change station
16665 * @add_beacon: Add beacon in sap mode
16666 * @del_beacon: Delete beacon in sap mode
16667 * @set_beacon: Set beacon in sap mode
16668 * @start_ap: Start ap
16669 * @change_beacon: Change beacon
16670 * @stop_ap: Stop ap
16671 * @change_bss: Change bss
16672 * @add_key: Add key
16673 * @get_key: Get key
16674 * @del_key: Delete key
16675 * @set_default_key: Set default key
16676 * @set_channel: Set channel
16677 * @scan: Scan
16678 * @connect: Connect
16679 * @disconnect: Disconnect
16680 * @join_ibss = Join ibss
16681 * @leave_ibss = Leave ibss
16682 * @set_wiphy_params = Set wiphy params
16683 * @set_tx_power = Set tx power
16684 * @get_tx_power = get tx power
16685 * @remain_on_channel = Remain on channel
16686 * @cancel_remain_on_channel = Cancel remain on channel
16687 * @mgmt_tx = Tx management frame
16688 * @mgmt_tx_cancel_wait = Cancel management tx wait
16689 * @set_default_mgmt_key = Set default management key
16690 * @set_txq_params = Set tx queue parameters
16691 * @get_station = Get station
16692 * @set_power_mgmt = Set power management
16693 * @del_station = Delete station
16694 * @add_station = Add station
16695 * @set_pmksa = Set pmksa
16696 * @del_pmksa = Delete pmksa
16697 * @flush_pmksa = Flush pmksa
16698 * @update_ft_ies = Update FT IEs
16699 * @tdls_mgmt = Tdls management
16700 * @tdls_oper = Tdls operation
16701 * @set_rekey_data = Set rekey data
16702 * @sched_scan_start = Scheduled scan start
16703 * @sched_scan_stop = Scheduled scan stop
16704 * @resume = Resume wlan
16705 * @suspend = Suspend wlan
16706 * @set_mac_acl = Set mac acl
16707 * @testmode_cmd = Test mode command
16708 * @set_ap_chanwidth = Set AP channel bandwidth
16709 * @dump_survey = Dump survey
16710 * @key_mgmt_set_pmk = Set pmk key management
16711 */
16712static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16713 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16714 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16715 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16716 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016717 .start_ap = wlan_hdd_cfg80211_start_ap,
16718 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16719 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016720 .change_bss = wlan_hdd_cfg80211_change_bss,
16721 .add_key = wlan_hdd_cfg80211_add_key,
16722 .get_key = wlan_hdd_cfg80211_get_key,
16723 .del_key = wlan_hdd_cfg80211_del_key,
16724 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16725 .scan = wlan_hdd_cfg80211_scan,
16726 .connect = wlan_hdd_cfg80211_connect,
16727 .disconnect = wlan_hdd_cfg80211_disconnect,
16728 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16729 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16730 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16731 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16732 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16733 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16734 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16735 .mgmt_tx = wlan_hdd_mgmt_tx,
16736 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16737 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16738 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016739 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016740 .get_station = wlan_hdd_cfg80211_get_station,
16741 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16742 .del_station = wlan_hdd_cfg80211_del_station,
16743 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016744 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16745 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16746 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016747#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016748 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16749#endif
16750#ifdef FEATURE_WLAN_TDLS
16751 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16752 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16753#endif
16754#ifdef WLAN_FEATURE_GTK_OFFLOAD
16755 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16756#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16757#ifdef FEATURE_WLAN_SCAN_PNO
16758 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16759 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16760#endif /*FEATURE_WLAN_SCAN_PNO */
16761 .resume = wlan_hdd_cfg80211_resume_wlan,
16762 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16763 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16764#ifdef WLAN_NL80211_TESTMODE
16765 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16766#endif
16767#ifdef QCA_HT_2040_COEX
16768 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16769#endif
16770 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016771#ifdef CHANNEL_SWITCH_SUPPORTED
16772 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16773#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016774 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016775#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16776 defined(CFG80211_ABORT_SCAN)
16777 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16778#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016779};