blob: 5e0f4661d5afde6351040479f5fd3070e6fd255e [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
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304875 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4876 hdd_err("Driver Modules are closed, can not start logger");
4877 return -EINVAL;
4878 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004879
4880 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4881 data, data_len,
4882 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004883 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004884 return -EINVAL;
4885 }
4886
4887 /* Parse and fetch ring id */
4888 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 return -EINVAL;
4891 }
4892 start_log.ring_id = nla_get_u32(
4893 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004894 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895
4896 /* Parse and fetch verbose level */
4897 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004898 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004899 return -EINVAL;
4900 }
4901 start_log.verbose_level = nla_get_u32(
4902 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004903 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904
4905 /* Parse and fetch flag */
4906 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004907 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908 return -EINVAL;
4909 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304910 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304912 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304914 /* size is buff size which can be set using iwpriv command*/
4915 start_log.size = 0;
4916
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4918
4919 if (start_log.ring_id == RING_ID_WAKELOCK) {
4920 /* Start/stop wakelock events */
4921 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4922 cds_set_wakelock_logging(true);
4923 else
4924 cds_set_wakelock_logging(false);
4925 return 0;
4926 }
4927
4928 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304929 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004930 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931 status);
4932 return -EINVAL;
4933 }
4934 return 0;
4935}
4936
4937/**
4938 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4939 * or disable the collection of packet statistics from the firmware
4940 * @wiphy: WIPHY structure pointer
4941 * @wdev: Wireless device structure pointer
4942 * @data: Pointer to the data received
4943 * @data_len: Length of the data received
4944 *
4945 * This function is used to enable or disable the collection of packet
4946 * statistics from the firmware
4947 *
4948 * Return: 0 on success and errno on failure
4949 */
4950static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4951 struct wireless_dev *wdev,
4952 const void *data,
4953 int data_len)
4954{
4955 int ret = 0;
4956
4957 cds_ssr_protect(__func__);
4958 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4959 wdev, data, data_len);
4960 cds_ssr_unprotect(__func__);
4961
4962 return ret;
4963}
4964
4965static const struct
4966nla_policy
4967qca_wlan_vendor_wifi_logger_get_ring_data_policy
4968[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4969 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4970 = {.type = NLA_U32 },
4971};
4972
4973/**
4974 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4975 * @wiphy: WIPHY structure pointer
4976 * @wdev: Wireless device structure pointer
4977 * @data: Pointer to the data received
4978 * @data_len: Length of the data received
4979 *
4980 * This function is used to flush or retrieve the per packet statistics from
4981 * the driver
4982 *
4983 * Return: 0 on success and errno on failure
4984 */
4985static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4986 struct wireless_dev *wdev,
4987 const void *data,
4988 int data_len)
4989{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304990 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004991 uint32_t ring_id;
4992 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4993 struct nlattr *tb
4994 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4995
Jeff Johnson1f61b612016-02-12 16:28:33 -08004996 ENTER_DEV(wdev->netdev);
4997
Anurag Chouhan6d760662016-02-20 16:05:43 +05304998 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 hdd_err("Command not allowed in FTM mode");
5000 return -EPERM;
5001 }
5002
5003 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305004 if (status)
5005 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006
5007 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5008 data, data_len,
5009 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005010 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 return -EINVAL;
5012 }
5013
5014 /* Parse and fetch ring id */
5015 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005016 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017 return -EINVAL;
5018 }
5019
5020 ring_id = nla_get_u32(
5021 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5022
5023 if (ring_id == RING_ID_PER_PACKET_STATS) {
5024 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07005025 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305026 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5027 /*
5028 * As part of DRIVER ring ID, flush both driver and fw logs.
5029 * For other Ring ID's driver doesn't have any rings to flush
5030 */
5031 hdd_notice("Bug report triggered by framework");
5032
5033 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5034 WLAN_LOG_INDICATOR_FRAMEWORK,
5035 WLAN_LOG_REASON_CODE_UNUSED,
5036 true, false);
5037 if (QDF_STATUS_SUCCESS != status) {
5038 hdd_err("Failed to trigger bug report");
5039 return -EINVAL;
5040 }
5041 } else {
5042 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5043 WLAN_LOG_INDICATOR_FRAMEWORK,
5044 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005046 return 0;
5047}
5048
5049/**
5050 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5051 * @wiphy: WIPHY structure pointer
5052 * @wdev: Wireless device structure pointer
5053 * @data: Pointer to the data received
5054 * @data_len: Length of the data received
5055 *
5056 * This function is used to flush or retrieve the per packet statistics from
5057 * the driver
5058 *
5059 * Return: 0 on success and errno on failure
5060 */
5061static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5062 struct wireless_dev *wdev,
5063 const void *data,
5064 int data_len)
5065{
5066 int ret = 0;
5067
5068 cds_ssr_protect(__func__);
5069 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5070 wdev, data, data_len);
5071 cds_ssr_unprotect(__func__);
5072
5073 return ret;
5074}
5075
5076#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5077/**
5078 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5079 * @hdd_ctx: HDD context
5080 * @request_id: [input] request id
5081 * @pattern_id: [output] pattern id
5082 *
5083 * This function loops through request id to pattern id array
5084 * if the slot is available, store the request id and return pattern id
5085 * if entry exists, return the pattern id
5086 *
5087 * Return: 0 on success and errno on failure
5088 */
5089static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5090 uint32_t request_id,
5091 uint8_t *pattern_id)
5092{
5093 uint32_t i;
5094
5095 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5096 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5097 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5098 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5099 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5100 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5101 return 0;
5102 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5103 request_id) {
5104 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5105 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5106 return 0;
5107 }
5108 }
5109 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5110 return -EINVAL;
5111}
5112
5113/**
5114 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5115 * @hdd_ctx: HDD context
5116 * @request_id: [input] request id
5117 * @pattern_id: [output] pattern id
5118 *
5119 * This function loops through request id to pattern id array
5120 * reset request id to 0 (slot available again) and
5121 * return pattern id
5122 *
5123 * Return: 0 on success and errno on failure
5124 */
5125static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5126 uint32_t request_id,
5127 uint8_t *pattern_id)
5128{
5129 uint32_t i;
5130
5131 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5132 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5133 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5134 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5135 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5136 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5137 return 0;
5138 }
5139 }
5140 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5141 return -EINVAL;
5142}
5143
5144
5145/*
5146 * define short names for the global vendor params
5147 * used by __wlan_hdd_cfg80211_offloaded_packets()
5148 */
5149#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5150#define PARAM_REQUEST_ID \
5151 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5152#define PARAM_CONTROL \
5153 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5154#define PARAM_IP_PACKET \
5155 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5156#define PARAM_SRC_MAC_ADDR \
5157 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5158#define PARAM_DST_MAC_ADDR \
5159 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5160#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5161
5162/**
5163 * wlan_hdd_add_tx_ptrn() - add tx pattern
5164 * @adapter: adapter pointer
5165 * @hdd_ctx: hdd context
5166 * @tb: nl attributes
5167 *
5168 * This function reads the NL attributes and forms a AddTxPtrn message
5169 * posts it to SME.
5170 *
5171 */
5172static int
5173wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5174 struct nlattr **tb)
5175{
5176 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305177 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 uint32_t request_id, ret, len;
5179 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305180 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 uint16_t eth_type = htons(ETH_P_IP);
5182
5183 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005184 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185 return -ENOTSUPP;
5186 }
5187
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305188 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005190 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005191 return -ENOMEM;
5192 }
5193
5194 /* Parse and fetch request Id */
5195 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005196 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005197 goto fail;
5198 }
5199
5200 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5201 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005202 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 return -EINVAL;
5204 }
Jeff Johnson77848112016-06-29 14:52:06 -07005205 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206
5207 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005208 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209 goto fail;
5210 }
5211 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005212 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005213 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005214 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005215 goto fail;
5216 }
5217
5218 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005219 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 goto fail;
5221 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005222 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305223 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005224 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005225 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226
Anurag Chouhanc5548422016-02-24 18:33:27 +05305227 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005228 &adapter->macAddressCurrent)) {
5229 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 goto fail;
5231 }
5232
5233 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005234 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 goto fail;
5236 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305237 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 MAC_ADDR_ARRAY(dst_addr.bytes));
5240
5241 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005242 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243 goto fail;
5244 }
5245 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005246 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247
5248 if (add_req->ucPtrnSize < 0 ||
5249 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5250 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005251 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 add_req->ucPtrnSize);
5253 goto fail;
5254 }
5255
5256 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305257 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305258 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305259 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305260 QDF_MAC_ADDR_SIZE);
5261 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305262 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263 len += 2;
5264
5265 /*
5266 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5267 * ------------------------------------------------------------
5268 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5269 * ------------------------------------------------------------
5270 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305271 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272 nla_data(tb[PARAM_IP_PACKET]),
5273 add_req->ucPtrnSize);
5274 add_req->ucPtrnSize += len;
5275
5276 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5277 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005278 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005279 goto fail;
5280 }
5281 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005282 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283
5284 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305285 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005286 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287 goto fail;
5288 }
5289
5290 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305291 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 return 0;
5293
5294fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305295 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005296 return -EINVAL;
5297}
5298
5299/**
5300 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5301 * @adapter: adapter pointer
5302 * @hdd_ctx: hdd context
5303 * @tb: nl attributes
5304 *
5305 * This function reads the NL attributes and forms a DelTxPtrn message
5306 * posts it to SME.
5307 *
5308 */
5309static int
5310wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5311 struct nlattr **tb)
5312{
5313 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305314 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005315 uint32_t request_id, ret;
5316 uint8_t pattern_id = 0;
5317
5318 /* Parse and fetch request Id */
5319 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005320 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 return -EINVAL;
5322 }
5323 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5324 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005325 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005326 return -EINVAL;
5327 }
5328
5329 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5330 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005331 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 return -EINVAL;
5333 }
5334
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305335 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005337 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338 return -ENOMEM;
5339 }
5340
Anurag Chouhanc5548422016-02-24 18:33:27 +05305341 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005342 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005344 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005345 request_id, del_req->ucPtrnId);
5346
5347 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305348 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005349 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005350 goto fail;
5351 }
5352
5353 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305354 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355 return 0;
5356
5357fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305358 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 return -EINVAL;
5360}
5361
5362
5363/**
5364 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5365 * @wiphy: Pointer to wireless phy
5366 * @wdev: Pointer to wireless device
5367 * @data: Pointer to data
5368 * @data_len: Data length
5369 *
5370 * Return: 0 on success, negative errno on failure
5371 */
5372static int
5373__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5374 struct wireless_dev *wdev,
5375 const void *data,
5376 int data_len)
5377{
5378 struct net_device *dev = wdev->netdev;
5379 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5380 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5381 struct nlattr *tb[PARAM_MAX + 1];
5382 uint8_t control;
5383 int ret;
5384 static const struct nla_policy policy[PARAM_MAX + 1] = {
5385 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5386 [PARAM_CONTROL] = { .type = NLA_U32 },
5387 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305388 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305390 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391 [PARAM_PERIOD] = { .type = NLA_U32 },
5392 };
5393
Jeff Johnson1f61b612016-02-12 16:28:33 -08005394 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395
Anurag Chouhan6d760662016-02-20 16:05:43 +05305396 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397 hdd_err("Command not allowed in FTM mode");
5398 return -EPERM;
5399 }
5400
5401 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305402 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005404
5405 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005406 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407 return -ENOTSUPP;
5408 }
5409
5410 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005411 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 return -EINVAL;
5413 }
5414
5415 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005416 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 return -EINVAL;
5418 }
5419 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005420 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421
5422 if (control == WLAN_START_OFFLOADED_PACKETS)
5423 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005424 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005426
5427 hdd_err("Invalid control: %d", control);
5428
5429 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430}
5431
5432/*
5433 * done with short names for the global vendor params
5434 * used by __wlan_hdd_cfg80211_offloaded_packets()
5435 */
5436#undef PARAM_MAX
5437#undef PARAM_REQUEST_ID
5438#undef PARAM_CONTROL
5439#undef PARAM_IP_PACKET
5440#undef PARAM_SRC_MAC_ADDR
5441#undef PARAM_DST_MAC_ADDR
5442#undef PARAM_PERIOD
5443
5444/**
5445 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5446 * @wiphy: wiphy structure pointer
5447 * @wdev: Wireless device structure pointer
5448 * @data: Pointer to the data received
5449 * @data_len: Length of @data
5450 *
5451 * Return: 0 on success; errno on failure
5452 */
5453static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5454 struct wireless_dev *wdev,
5455 const void *data,
5456 int data_len)
5457{
5458 int ret = 0;
5459
5460 cds_ssr_protect(__func__);
5461 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5462 wdev, data, data_len);
5463 cds_ssr_unprotect(__func__);
5464
5465 return ret;
5466}
5467#endif
5468
5469/*
5470 * define short names for the global vendor params
5471 * used by __wlan_hdd_cfg80211_monitor_rssi()
5472 */
5473#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5474#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5475#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5476#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5477#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5478
5479/**
5480 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5481 * @wiphy: Pointer to wireless phy
5482 * @wdev: Pointer to wireless device
5483 * @data: Pointer to data
5484 * @data_len: Data length
5485 *
5486 * Return: 0 on success, negative errno on failure
5487 */
5488static int
5489__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5490 struct wireless_dev *wdev,
5491 const void *data,
5492 int data_len)
5493{
5494 struct net_device *dev = wdev->netdev;
5495 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5496 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5497 struct nlattr *tb[PARAM_MAX + 1];
5498 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305499 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005500 int ret;
5501 uint32_t control;
5502 static const struct nla_policy policy[PARAM_MAX + 1] = {
5503 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5504 [PARAM_CONTROL] = { .type = NLA_U32 },
5505 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5506 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5507 };
5508
Jeff Johnson1f61b612016-02-12 16:28:33 -08005509 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005510
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305511 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5512 hdd_err("invalid session id: %d", adapter->sessionId);
5513 return -EINVAL;
5514 }
5515
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305517 if (ret)
5518 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005519
5520 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005521 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 return -ENOTSUPP;
5523 }
5524
5525 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005526 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527 return -EINVAL;
5528 }
5529
5530 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005531 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532 return -EINVAL;
5533 }
5534
5535 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005536 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537 return -EINVAL;
5538 }
5539
5540 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5541 req.session_id = adapter->sessionId;
5542 control = nla_get_u32(tb[PARAM_CONTROL]);
5543
5544 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5545 req.control = true;
5546 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005547 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 return -EINVAL;
5549 }
5550
5551 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005552 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553 return -EINVAL;
5554 }
5555
5556 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5557 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5558
5559 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005560 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561 req.min_rssi, req.max_rssi);
5562 return -EINVAL;
5563 }
Jeff Johnson77848112016-06-29 14:52:06 -07005564 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565 req.min_rssi, req.max_rssi);
5566
5567 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5568 req.control = false;
5569 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005570 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 return -EINVAL;
5572 }
Jeff Johnson77848112016-06-29 14:52:06 -07005573 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 req.request_id, req.session_id, req.control);
5575
5576 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305577 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005578 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579 return -EINVAL;
5580 }
5581
5582 return 0;
5583}
5584
5585/*
5586 * done with short names for the global vendor params
5587 * used by __wlan_hdd_cfg80211_monitor_rssi()
5588 */
5589#undef PARAM_MAX
5590#undef PARAM_CONTROL
5591#undef PARAM_REQUEST_ID
5592#undef PARAM_MAX_RSSI
5593#undef PARAM_MIN_RSSI
5594
5595/**
5596 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5597 * @wiphy: wiphy structure pointer
5598 * @wdev: Wireless device structure pointer
5599 * @data: Pointer to the data received
5600 * @data_len: Length of @data
5601 *
5602 * Return: 0 on success; errno on failure
5603 */
5604static int
5605wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5606 const void *data, int data_len)
5607{
5608 int ret;
5609
5610 cds_ssr_protect(__func__);
5611 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5612 cds_ssr_unprotect(__func__);
5613
5614 return ret;
5615}
5616
5617/**
5618 * hdd_rssi_threshold_breached() - rssi breached NL event
5619 * @hddctx: HDD context
5620 * @data: rssi breached event data
5621 *
5622 * This function reads the rssi breached event %data and fill in the skb with
5623 * NL attributes and send up the NL event.
5624 *
5625 * Return: none
5626 */
5627void hdd_rssi_threshold_breached(void *hddctx,
5628 struct rssi_breach_event *data)
5629{
5630 hdd_context_t *hdd_ctx = hddctx;
5631 struct sk_buff *skb;
5632
5633 ENTER();
5634
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305635 if (wlan_hdd_validate_context(hdd_ctx))
5636 return;
5637 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005638 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005639 return;
5640 }
5641
5642 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5643 NULL,
5644 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5645 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5646 GFP_KERNEL);
5647
5648 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005649 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 return;
5651 }
5652
Jeff Johnson77848112016-06-29 14:52:06 -07005653 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005655 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5657
5658 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5659 data->request_id) ||
5660 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5661 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5662 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5663 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005664 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 goto fail;
5666 }
5667
5668 cfg80211_vendor_event(skb, GFP_KERNEL);
5669 return;
5670
5671fail:
5672 kfree_skb(skb);
5673 return;
5674}
5675
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305676static const struct nla_policy
5677ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5678 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5679};
5680
5681/**
5682 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5683 * @wiphy: Pointer to wireless phy
5684 * @wdev: Pointer to wireless device
5685 * @data: Pointer to data
5686 * @data_len: Length of @data
5687 *
5688 * Return: 0 on success, negative errno on failure
5689 */
5690static int
5691__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5692 struct wireless_dev *wdev,
5693 const void *data, int data_len)
5694{
5695 int status;
5696 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5697 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005698 struct net_device *dev = wdev->netdev;
5699 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305700
5701 ENTER_DEV(wdev->netdev);
5702
5703 status = wlan_hdd_validate_context(pHddCtx);
5704 if (0 != status)
5705 return status;
5706 if (!pHddCtx->config->fhostNSOffload) {
5707 hdd_err("ND Offload not supported");
5708 return -EINVAL;
5709 }
5710
5711 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5712 (struct nlattr *)data,
5713 data_len, ns_offload_set_policy)) {
5714 hdd_err("nla_parse failed");
5715 return -EINVAL;
5716 }
5717
5718 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5719 hdd_err("ND Offload flag attribute not present");
5720 return -EINVAL;
5721 }
5722
5723 pHddCtx->ns_offload_enable =
5724 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5725
Dustin Brownd8279d22016-09-07 14:52:57 -07005726 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305727 if (pHddCtx->ns_offload_enable)
5728 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5729 else
5730 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005731
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305732 return 0;
5733}
5734
5735/**
5736 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5737 * @wiphy: pointer to wireless wiphy structure.
5738 * @wdev: pointer to wireless_dev structure.
5739 * @data: Pointer to the data to be passed via vendor interface
5740 * @data_len:Length of the data to be passed
5741 *
5742 * Return: Return the Success or Failure code.
5743 */
5744static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5745 struct wireless_dev *wdev,
5746 const void *data, int data_len)
5747{
5748 int ret;
5749
5750 cds_ssr_protect(__func__);
5751 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5752 cds_ssr_unprotect(__func__);
5753
5754 return ret;
5755}
5756
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5758 * @wiphy: Pointer to wireless phy
5759 * @wdev: Pointer to wireless device
5760 * @data: Pointer to data
5761 * @data_len: Data length
5762 *
5763 * This function return the preferred frequency list generated by the policy
5764 * manager.
5765 *
5766 * Return: success or failure code
5767 */
5768static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5769 struct wireless_dev
5770 *wdev, const void *data,
5771 int data_len)
5772{
5773 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5774 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305775 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305776 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005777 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305778 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 enum cds_con_mode intf_mode;
5780 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5781 struct sk_buff *reply_skb;
5782
Jeff Johnson1f61b612016-02-12 16:28:33 -08005783 ENTER_DEV(wdev->netdev);
5784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005785 ret = wlan_hdd_validate_context(hdd_ctx);
5786 if (ret)
5787 return -EINVAL;
5788
5789 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5790 data, data_len, NULL)) {
5791 hdd_err("Invalid ATTR");
5792 return -EINVAL;
5793 }
5794
5795 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5796 hdd_err("attr interface type failed");
5797 return -EINVAL;
5798 }
5799
5800 intf_mode = nla_get_u32(tb
5801 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5802
5803 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5804 hdd_err("Invalid interface type");
5805 return -EINVAL;
5806 }
5807
5808 hdd_debug("Userspace requested pref freq list");
5809
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305810 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5811 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305812 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005813 hdd_err("Get pcl failed");
5814 return -EINVAL;
5815 }
5816
5817 /* convert channel number to frequency */
5818 for (i = 0; i < pcl_len; i++) {
5819 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5820 freq_list[i] =
5821 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005822 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005823 else
5824 freq_list[i] =
5825 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005826 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005827 }
5828
5829 /* send the freq_list back to supplicant */
5830 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5831 sizeof(u32) *
5832 pcl_len +
5833 NLMSG_HDRLEN);
5834
5835 if (!reply_skb) {
5836 hdd_err("Allocate reply_skb failed");
5837 return -EINVAL;
5838 }
5839
5840 if (nla_put_u32(reply_skb,
5841 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5842 intf_mode) ||
5843 nla_put(reply_skb,
5844 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5845 sizeof(uint32_t) * pcl_len,
5846 freq_list)) {
5847 hdd_err("nla put fail");
5848 kfree_skb(reply_skb);
5849 return -EINVAL;
5850 }
5851
5852 return cfg80211_vendor_cmd_reply(reply_skb);
5853}
5854
5855/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5856 * @wiphy: Pointer to wireless phy
5857 * @wdev: Pointer to wireless device
5858 * @data: Pointer to data
5859 * @data_len: Data length
5860 *
5861 * This function return the preferred frequency list generated by the policy
5862 * manager.
5863 *
5864 * Return: success or failure code
5865 */
5866static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5867 struct wireless_dev
5868 *wdev, const void *data,
5869 int data_len)
5870{
5871 int ret = 0;
5872
5873 cds_ssr_protect(__func__);
5874 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5875 data, data_len);
5876 cds_ssr_unprotect(__func__);
5877
5878 return ret;
5879}
5880
5881/**
5882 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5883 * @wiphy: Pointer to wireless phy
5884 * @wdev: Pointer to wireless device
5885 * @data: Pointer to data
5886 * @data_len: Data length
5887 *
5888 * Return: 0 on success, negative errno on failure
5889 */
5890static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5891 struct wireless_dev *wdev,
5892 const void *data,
5893 int data_len)
5894{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305895 struct net_device *ndev = wdev->netdev;
5896 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005897 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5898 int ret = 0;
5899 enum cds_con_mode intf_mode;
5900 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5901 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005902
Jeff Johnson1f61b612016-02-12 16:28:33 -08005903 ENTER_DEV(ndev);
5904
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 ret = wlan_hdd_validate_context(hdd_ctx);
5906 if (ret)
5907 return ret;
5908
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5910 data, data_len, NULL)) {
5911 hdd_err("Invalid ATTR");
5912 return -EINVAL;
5913 }
5914
5915 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5916 hdd_err("attr interface type failed");
5917 return -EINVAL;
5918 }
5919
5920 intf_mode = nla_get_u32(tb
5921 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5922
5923 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5924 hdd_err("Invalid interface type");
5925 return -EINVAL;
5926 }
5927
5928 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5929 hdd_err("attr probable freq failed");
5930 return -EINVAL;
5931 }
5932
5933 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5934 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5935
5936 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005937 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938 channel_hint, HW_MODE_20_MHZ)) {
5939 hdd_err("Set channel hint failed due to concurrency check");
5940 return -EINVAL;
5941 }
5942
Krunal Soni09e55032016-06-07 10:06:55 -07005943 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5944 hdd_warn("Remain On Channel Pending");
5945
Krunal Soni3091bcc2016-06-23 12:28:21 -07005946 ret = qdf_reset_connection_update();
5947 if (!QDF_IS_STATUS_SUCCESS(ret))
5948 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949
Krunal Soni3091bcc2016-06-23 12:28:21 -07005950 ret = cds_current_connections_update(adapter->sessionId,
5951 channel_hint,
5952 SIR_UPDATE_REASON_SET_OPER_CHAN);
5953 if (QDF_STATUS_E_FAILURE == ret) {
5954 /* return in the failure case */
5955 hdd_err("ERROR: connections update failed!!");
5956 return -EINVAL;
5957 }
5958
5959 if (QDF_STATUS_SUCCESS == ret) {
5960 /*
5961 * Success is the only case for which we expect hw mode
5962 * change to take place, hence we need to wait.
5963 * For any other return value it should be a pass
5964 * through
5965 */
5966 ret = qdf_wait_for_connection_update();
5967 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5968 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005969 return -EINVAL;
5970 }
5971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972 }
5973
5974 return 0;
5975}
5976
5977/**
5978 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5979 * @wiphy: Pointer to wireless phy
5980 * @wdev: Pointer to wireless device
5981 * @data: Pointer to data
5982 * @data_len: Data length
5983 *
5984 * Return: 0 on success, negative errno on failure
5985 */
5986static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5987 struct wireless_dev *wdev,
5988 const void *data,
5989 int data_len)
5990{
5991 int ret = 0;
5992
5993 cds_ssr_protect(__func__);
5994 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5995 data, data_len);
5996 cds_ssr_unprotect(__func__);
5997
5998 return ret;
5999}
6000
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306001static const struct
6002nla_policy
6003qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6004 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6005};
6006
6007/**
6008 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6009 * @wiphy: WIPHY structure pointer
6010 * @wdev: Wireless device structure pointer
6011 * @data: Pointer to the data received
6012 * @data_len: Length of the data received
6013 *
6014 * This function is used to get link properties like nss, rate flags and
6015 * operating frequency for the active connection with the given peer.
6016 *
6017 * Return: 0 on success and errno on failure
6018 */
6019static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6020 struct wireless_dev *wdev,
6021 const void *data,
6022 int data_len)
6023{
6024 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6025 struct net_device *dev = wdev->netdev;
6026 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6027 hdd_station_ctx_t *hdd_sta_ctx;
6028 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306029 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306030 uint32_t sta_id;
6031 struct sk_buff *reply_skb;
6032 uint32_t rate_flags = 0;
6033 uint8_t nss;
6034 uint8_t final_rate_flags = 0;
6035 uint32_t freq;
6036
Jeff Johnson1f61b612016-02-12 16:28:33 -08006037 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306038
Anurag Chouhan6d760662016-02-20 16:05:43 +05306039 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306040 hdd_err("Command not allowed in FTM mode");
6041 return -EPERM;
6042 }
6043
6044 if (0 != wlan_hdd_validate_context(hdd_ctx))
6045 return -EINVAL;
6046
6047 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6048 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006049 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306050 return -EINVAL;
6051 }
6052
6053 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006054 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306055 adapter->device_mode);
6056 return -EINVAL;
6057 }
6058
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306059 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306060 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006061 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306062 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6063
Krunal Sonib4326f22016-03-10 13:05:51 -08006064 if (adapter->device_mode == QDF_STA_MODE ||
6065 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306066 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6067 if ((hdd_sta_ctx->conn_info.connState !=
6068 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306069 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306070 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006071 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306072 MAC_ADDR_ARRAY(peer_mac));
6073 return -EINVAL;
6074 }
6075
6076 nss = hdd_sta_ctx->conn_info.nss;
6077 freq = cds_chan_to_freq(
6078 hdd_sta_ctx->conn_info.operationChannel);
6079 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006080 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6081 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306082
6083 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6084 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306085 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306086 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306087 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306088 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306089 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306090 break;
6091 }
6092
6093 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006094 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306095 MAC_ADDR_ARRAY(peer_mac));
6096 return -EINVAL;
6097 }
6098
6099 nss = adapter->aStaInfo[sta_id].nss;
6100 freq = cds_chan_to_freq(
6101 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6102 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6103 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006104 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306105 MAC_ADDR_ARRAY(peer_mac));
6106 return -EINVAL;
6107 }
6108
6109 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6110 if (rate_flags & eHAL_TX_RATE_VHT80) {
6111 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006112#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306113 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006114#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306115 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6116 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006117#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306118 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006119#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306120 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6121 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6122 } else if (rate_flags &
6123 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6124 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006125#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306126 if (rate_flags & eHAL_TX_RATE_HT40)
6127 final_rate_flags |=
6128 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006129#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306130 }
6131
6132 if (rate_flags & eHAL_TX_RATE_SGI) {
6133 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6134 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6135 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6136 }
6137 }
6138
6139 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6140 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6141
6142 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006143 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306144 return -EINVAL;
6145 }
6146
6147 if (nla_put_u8(reply_skb,
6148 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6149 nss) ||
6150 nla_put_u8(reply_skb,
6151 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6152 final_rate_flags) ||
6153 nla_put_u32(reply_skb,
6154 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6155 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006156 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306157 kfree_skb(reply_skb);
6158 return -EINVAL;
6159 }
6160
6161 return cfg80211_vendor_cmd_reply(reply_skb);
6162}
6163
6164/**
6165 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6166 * properties.
6167 * @wiphy: WIPHY structure pointer
6168 * @wdev: Wireless device structure pointer
6169 * @data: Pointer to the data received
6170 * @data_len: Length of the data received
6171 *
6172 * This function is used to get link properties like nss, rate flags and
6173 * operating frequency for the active connection with the given peer.
6174 *
6175 * Return: 0 on success and errno on failure
6176 */
6177static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6178 struct wireless_dev *wdev,
6179 const void *data,
6180 int data_len)
6181{
6182 int ret = 0;
6183
6184 cds_ssr_protect(__func__);
6185 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6186 wdev, data, data_len);
6187 cds_ssr_unprotect(__func__);
6188
6189 return ret;
6190}
6191
Peng Xu278d0122015-09-24 16:34:17 -07006192static const struct
6193nla_policy
6194qca_wlan_vendor_ota_test_policy
6195[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6196 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6197};
6198
6199/**
6200 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6201 * @wiphy: Pointer to wireless phy
6202 * @wdev: Pointer to wireless device
6203 * @data: Pointer to data
6204 * @data_len: Data length
6205 *
6206 * Return: 0 on success, negative errno on failure
6207 */
6208static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6209 struct wireless_dev *wdev,
6210 const void *data,
6211 int data_len)
6212{
6213 struct net_device *dev = wdev->netdev;
6214 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6215 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6216 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6217 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6218 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306219 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006220 uint32_t current_roam_state;
6221
Jeff Johnson1f61b612016-02-12 16:28:33 -08006222 ENTER_DEV(dev);
6223
Anurag Chouhan6d760662016-02-20 16:05:43 +05306224 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006225 hdd_err("Command not allowed in FTM mode");
6226 return -EPERM;
6227 }
6228
6229 if (0 != wlan_hdd_validate_context(hdd_ctx))
6230 return -EINVAL;
6231
6232 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6233 data, data_len,
6234 qca_wlan_vendor_ota_test_policy)) {
6235 hdd_err("invalid attr");
6236 return -EINVAL;
6237 }
6238
6239 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6240 hdd_err("attr ota test failed");
6241 return -EINVAL;
6242 }
6243
6244 ota_enable = nla_get_u8(
6245 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6246
6247 hdd_info(" OTA test enable = %d", ota_enable);
6248 if (ota_enable != 1) {
6249 hdd_err("Invalid value, only enable test mode is supported!");
6250 return -EINVAL;
6251 }
6252
6253 current_roam_state =
6254 sme_get_current_roam_state(hal, adapter->sessionId);
6255 status = sme_stop_roaming(hal, adapter->sessionId,
6256 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306257 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006258 hdd_err("Enable/Disable roaming failed");
6259 return -EINVAL;
6260 }
6261
6262 status = sme_ps_enable_disable(hal, adapter->sessionId,
6263 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306264 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006265 hdd_err("Enable/Disable power save failed");
6266 /* restore previous roaming setting */
6267 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6268 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6269 status = sme_start_roaming(hal, adapter->sessionId,
6270 eCsrHddIssued);
6271 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6272 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6273 status = sme_stop_roaming(hal, adapter->sessionId,
6274 eCsrHddIssued);
6275
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306276 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006277 hdd_err("Restoring roaming state failed");
6278
6279 return -EINVAL;
6280 }
6281
6282
6283 return 0;
6284}
6285
6286/**
6287 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6288 * @wiphy: Pointer to wireless phy
6289 * @wdev: Pointer to wireless device
6290 * @data: Pointer to data
6291 * @data_len: Data length
6292 *
6293 * Return: 0 on success, negative errno on failure
6294 */
6295static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6296 struct wireless_dev *wdev,
6297 const void *data,
6298 int data_len)
6299{
6300 int ret = 0;
6301
6302 cds_ssr_protect(__func__);
6303 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6304 cds_ssr_unprotect(__func__);
6305
6306 return ret;
6307}
6308
Peng Xu4d67c8f2015-10-16 16:02:26 -07006309/**
6310 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6311 * @wiphy: Pointer to wireless phy
6312 * @wdev: Pointer to wireless device
6313 * @data: Pointer to data
6314 * @data_len: Data length
6315 *
6316 * Return: 0 on success, negative errno on failure
6317 */
6318static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6319 struct wireless_dev *wdev,
6320 const void *data,
6321 int data_len)
6322{
6323 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6324 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006325 hdd_adapter_t *adapter;
6326 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006327 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6328 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006329 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006330
Jeff Johnson1f61b612016-02-12 16:28:33 -08006331 ENTER_DEV(dev);
6332
Peng Xu4d67c8f2015-10-16 16:02:26 -07006333 ret = wlan_hdd_validate_context(hdd_ctx);
6334 if (ret)
6335 return ret;
6336
6337 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6338
6339 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6340 data, data_len, NULL)) {
6341 hdd_err("Invalid ATTR");
6342 return -EINVAL;
6343 }
6344
6345 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6346 hdd_err("attr tx power scale failed");
6347 return -EINVAL;
6348 }
6349
6350 scale_value = nla_get_u8(tb
6351 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6352
6353 if (scale_value > MAX_TXPOWER_SCALE) {
6354 hdd_err("Invalid tx power scale level");
6355 return -EINVAL;
6356 }
6357
Peng Xu62c8c432016-05-09 15:23:02 -07006358 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006359
Peng Xu62c8c432016-05-09 15:23:02 -07006360 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006361 hdd_err("Set tx power scale failed");
6362 return -EINVAL;
6363 }
6364
6365 return 0;
6366}
6367
6368/**
6369 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6370 * @wiphy: Pointer to wireless phy
6371 * @wdev: Pointer to wireless device
6372 * @data: Pointer to data
6373 * @data_len: Data length
6374 *
6375 * Return: 0 on success, negative errno on failure
6376 */
6377static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6378 struct wireless_dev *wdev,
6379 const void *data,
6380 int data_len)
6381{
Peng Xu62c8c432016-05-09 15:23:02 -07006382 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006383
6384 cds_ssr_protect(__func__);
6385 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6386 data, data_len);
6387 cds_ssr_unprotect(__func__);
6388
6389 return ret;
6390}
6391
6392/**
6393 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6394 * @wiphy: Pointer to wireless phy
6395 * @wdev: Pointer to wireless device
6396 * @data: Pointer to data
6397 * @data_len: Data length
6398 *
6399 * Return: 0 on success, negative errno on failure
6400 */
6401static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6402 struct wireless_dev *wdev,
6403 const void *data,
6404 int data_len)
6405{
6406 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6407 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006408 hdd_adapter_t *adapter;
6409 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006410 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6411 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006412 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006413
Jeff Johnson1f61b612016-02-12 16:28:33 -08006414 ENTER_DEV(dev);
6415
Peng Xu4d67c8f2015-10-16 16:02:26 -07006416 ret = wlan_hdd_validate_context(hdd_ctx);
6417 if (ret)
6418 return ret;
6419
6420 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6421
6422 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6423 data, data_len, NULL)) {
6424 hdd_err("Invalid ATTR");
6425 return -EINVAL;
6426 }
6427
6428 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6429 hdd_err("attr tx power decrease db value failed");
6430 return -EINVAL;
6431 }
6432
6433 scale_value = nla_get_u8(tb
6434 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6435
Peng Xu62c8c432016-05-09 15:23:02 -07006436 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6437 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006438
Peng Xu62c8c432016-05-09 15:23:02 -07006439 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006440 hdd_err("Set tx power decrease db failed");
6441 return -EINVAL;
6442 }
6443
6444 return 0;
6445}
6446
6447/**
6448 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6449 * @wiphy: Pointer to wireless phy
6450 * @wdev: Pointer to wireless device
6451 * @data: Pointer to data
6452 * @data_len: Data length
6453 *
6454 * Return: 0 on success, negative errno on failure
6455 */
6456static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6457 struct wireless_dev *wdev,
6458 const void *data,
6459 int data_len)
6460{
Peng Xu62c8c432016-05-09 15:23:02 -07006461 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006462
6463 cds_ssr_protect(__func__);
6464 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6465 data, data_len);
6466 cds_ssr_unprotect(__func__);
6467
6468 return ret;
6469}
Peng Xu8fdaa492016-06-22 10:20:47 -07006470
6471/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306472 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6473 * @wiphy: Pointer to wireless phy
6474 * @wdev: Pointer to wireless device
6475 * @data: Pointer to data
6476 * @data_len: Data length
6477 *
6478 * Processes the conditional channel switch request and invokes the helper
6479 * APIs to process the channel switch request.
6480 *
6481 * Return: 0 on success, negative errno on failure
6482 */
6483static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6484 struct wireless_dev *wdev,
6485 const void *data,
6486 int data_len)
6487{
6488 int ret;
6489 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6490 struct net_device *dev = wdev->netdev;
6491 hdd_adapter_t *adapter;
6492 struct nlattr
6493 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6494 uint32_t freq_len, i;
6495 uint32_t *freq;
6496 uint8_t chans[QDF_MAX_NUM_CHAN];
6497
6498 ENTER_DEV(dev);
6499
6500 ret = wlan_hdd_validate_context(hdd_ctx);
6501 if (ret)
6502 return ret;
6503
6504 if (!hdd_ctx->config->enableDFSMasterCap) {
6505 hdd_err("DFS master capability is not present in the driver");
6506 return -EINVAL;
6507 }
6508
6509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6510 hdd_err("Command not allowed in FTM mode");
6511 return -EPERM;
6512 }
6513
6514 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6515 if (adapter->device_mode != QDF_SAP_MODE) {
6516 hdd_err("Invalid device mode %d", adapter->device_mode);
6517 return -EINVAL;
6518 }
6519
6520 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6521 data, data_len, NULL)) {
6522 hdd_err("Invalid ATTR");
6523 return -EINVAL;
6524 }
6525
6526 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6527 hdd_err("Frequency list is missing");
6528 return -EINVAL;
6529 }
6530
6531 freq_len = nla_len(
6532 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6533 sizeof(uint32_t);
6534
6535 if (freq_len > QDF_MAX_NUM_CHAN) {
6536 hdd_err("insufficient space to hold channels");
6537 return -ENOMEM;
6538 }
6539
6540 hdd_debug("freq_len=%d", freq_len);
6541
6542 freq = nla_data(
6543 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6544
6545
6546 for (i = 0; i < freq_len; i++) {
6547 if (freq[i] == 0)
6548 chans[i] = 0;
6549 else
6550 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6551
6552 hdd_debug("freq[%d]=%d", i, freq[i]);
6553 }
6554
6555 /*
6556 * The input frequency list from user space is designed to be a
6557 * priority based frequency list. This is only to accommodate any
6558 * future request. But, current requirement is only to perform CAC
6559 * on a single channel. So, the first entry from the list is picked.
6560 *
6561 * If channel is zero, any channel in the available outdoor regulatory
6562 * domain will be selected.
6563 */
6564 ret = wlan_hdd_request_pre_cac(chans[0]);
6565 if (ret) {
6566 hdd_err("pre cac request failed with reason:%d", ret);
6567 return ret;
6568 }
6569
6570 return 0;
6571}
6572
6573/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006574 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6575 * @wiphy: Pointer to wireless phy
6576 * @wdev: Pointer to wireless device
6577 * @data: Pointer to data
6578 * @data_len: Data length
6579 *
6580 * This function is to process the p2p listen offload start vendor
6581 * command. It parses the input parameters and invoke WMA API to
6582 * send the command to firmware.
6583 *
6584 * Return: 0 on success, negative errno on failure
6585 */
6586static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6587 struct wireless_dev *wdev,
6588 const void *data,
6589 int data_len)
6590{
6591 int ret;
6592 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6593 struct net_device *dev = wdev->netdev;
6594 hdd_adapter_t *adapter;
6595 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6596 struct sir_p2p_lo_start params;
6597 QDF_STATUS status;
6598
6599 ENTER_DEV(dev);
6600
6601 ret = wlan_hdd_validate_context(hdd_ctx);
6602 if (ret)
6603 return ret;
6604
6605 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6606 hdd_err("Command not allowed in FTM mode");
6607 return -EPERM;
6608 }
6609
6610 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6611 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6612 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6613 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6614 hdd_err("Invalid device mode %d", adapter->device_mode);
6615 return -EINVAL;
6616 }
6617
6618 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6619 data, data_len, NULL)) {
6620 hdd_err("Invalid ATTR");
6621 return -EINVAL;
6622 }
6623
6624 memset(&params, 0, sizeof(params));
6625
6626 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6627 params.ctl_flags = 1; /* set to default value */
6628 else
6629 params.ctl_flags = nla_get_u32(tb
6630 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6631
6632 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6633 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6634 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6635 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6636 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6637 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6638 hdd_err("Attribute parsing failed");
6639 return -EINVAL;
6640 }
6641
6642 params.vdev_id = adapter->sessionId;
6643 params.freq = nla_get_u32(tb
6644 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6645 if ((params.freq != 2412) && (params.freq != 2437) &&
6646 (params.freq != 2462)) {
6647 hdd_err("Invalid listening channel: %d", params.freq);
6648 return -EINVAL;
6649 }
6650
6651 params.period = nla_get_u32(tb
6652 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6653 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6654 hdd_err("Invalid period: %d", params.period);
6655 return -EINVAL;
6656 }
6657
6658 params.interval = nla_get_u32(tb
6659 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6660 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6661 hdd_err("Invalid interval: %d", params.interval);
6662 return -EINVAL;
6663 }
6664
6665 params.count = nla_get_u32(tb
6666 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006667 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006668 hdd_err("Invalid count: %d", params.count);
6669 return -EINVAL;
6670 }
6671
6672 params.device_types = nla_data(tb
6673 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6674 if (params.device_types == NULL) {
6675 hdd_err("Invalid device types");
6676 return -EINVAL;
6677 }
6678
6679 params.dev_types_len = nla_len(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6681 if (params.dev_types_len < 8) {
6682 hdd_err("Invalid device type length: %d", params.dev_types_len);
6683 return -EINVAL;
6684 }
6685
6686 params.probe_resp_tmplt = nla_data(tb
6687 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6688 if (params.probe_resp_tmplt == NULL) {
6689 hdd_err("Invalid probe response template");
6690 return -EINVAL;
6691 }
6692
6693 params.probe_resp_len = nla_len(tb
6694 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6695 if (params.probe_resp_len == 0) {
6696 hdd_err("Invalid probe resp template length: %d",
6697 params.probe_resp_len);
6698 return -EINVAL;
6699 }
6700
6701 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6702 params.freq, params.period, params.interval, params.count);
6703
6704 status = wma_p2p_lo_start(&params);
6705
6706 if (!QDF_IS_STATUS_SUCCESS(status)) {
6707 hdd_err("P2P LO start failed");
6708 return -EINVAL;
6709 }
6710
6711 return 0;
6712}
6713
6714
6715/**
6716 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6717 * @wiphy: Pointer to wireless phy
6718 * @wdev: Pointer to wireless device
6719 * @data: Pointer to data
6720 * @data_len: Data length
6721 *
6722 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6723 * to process p2p listen offload start vendor command.
6724 *
6725 * Return: 0 on success, negative errno on failure
6726 */
6727static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6728 struct wireless_dev *wdev,
6729 const void *data,
6730 int data_len)
6731{
6732 int ret = 0;
6733
6734 cds_ssr_protect(__func__);
6735 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6736 data, data_len);
6737 cds_ssr_unprotect(__func__);
6738
6739 return ret;
6740}
6741
6742/**
6743 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6744 * @wiphy: Pointer to wireless phy
6745 * @wdev: Pointer to wireless device
6746 * @data: Pointer to data
6747 * @data_len: Data length
6748 *
6749 * This function is to process the p2p listen offload stop vendor
6750 * command. It invokes WMA API to send command to firmware.
6751 *
6752 * Return: 0 on success, negative errno on failure
6753 */
6754static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6755 struct wireless_dev *wdev,
6756 const void *data,
6757 int data_len)
6758{
6759 QDF_STATUS status;
6760 hdd_adapter_t *adapter;
6761 struct net_device *dev = wdev->netdev;
6762
6763 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6764 hdd_err("Command not allowed in FTM mode");
6765 return -EPERM;
6766 }
6767
6768 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6769 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6770 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6771 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6772 hdd_err("Invalid device mode");
6773 return -EINVAL;
6774 }
6775
6776 status = wma_p2p_lo_stop(adapter->sessionId);
6777
6778 if (!QDF_IS_STATUS_SUCCESS(status)) {
6779 hdd_err("P2P LO stop failed");
6780 return -EINVAL;
6781 }
6782
6783 return 0;
6784}
6785
6786/**
6787 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6788 * @wiphy: Pointer to wireless phy
6789 * @wdev: Pointer to wireless device
6790 * @data: Pointer to data
6791 * @data_len: Data length
6792 *
6793 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6794 * to process p2p listen offload stop vendor command.
6795 *
6796 * Return: 0 on success, negative errno on failure
6797 */
6798static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6799 struct wireless_dev *wdev,
6800 const void *data,
6801 int data_len)
6802{
6803 int ret = 0;
6804
6805 cds_ssr_protect(__func__);
6806 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6807 data, data_len);
6808 cds_ssr_unprotect(__func__);
6809
6810 return ret;
6811}
6812
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306813/**
6814 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6815 * @wiphy: Pointer to wireless phy
6816 * @wdev: Pointer to wireless device
6817 * @data: Pointer to data
6818 * @data_len: Data length
6819 *
6820 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6821 * to process the conditional channel switch request.
6822 *
6823 * Return: 0 on success, negative errno on failure
6824 */
6825static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6826 struct wireless_dev *wdev,
6827 const void *data,
6828 int data_len)
6829{
6830 int ret;
6831
6832 cds_ssr_protect(__func__);
6833 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6834 data, data_len);
6835 cds_ssr_unprotect(__func__);
6836
6837 return ret;
6838}
6839
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306840/*
6841 * define short names for the global vendor params
6842 * used by __wlan_hdd_cfg80211_bpf_offload()
6843 */
6844#define BPF_INVALID \
6845 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6846#define BPF_SET_RESET \
6847 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6848#define BPF_VERSION \
6849 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6850#define BPF_FILTER_ID \
6851 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6852#define BPF_PACKET_SIZE \
6853 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6854#define BPF_CURRENT_OFFSET \
6855 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6856#define BPF_PROGRAM \
6857 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6858#define BPF_MAX \
6859 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006860
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306861static const struct nla_policy
6862wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6863 [BPF_SET_RESET] = {.type = NLA_U32},
6864 [BPF_VERSION] = {.type = NLA_U32},
6865 [BPF_FILTER_ID] = {.type = NLA_U32},
6866 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6867 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6868 [BPF_PROGRAM] = {.type = NLA_U8},
6869};
6870
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006871struct bpf_offload_priv {
6872 struct sir_bpf_get_offload bpf_get_offload;
6873};
6874
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306875/**
6876 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006877 * @context: opaque context originally passed to SME. HDD always passes
6878 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306879 * @bpf_get_offload: struct for get offload
6880 *
6881 * This function receives the response/data from the lower layer and
6882 * checks to see if the thread is still waiting then post the results to
6883 * upper layer, if the request has timed out then ignore.
6884 *
6885 * Return: None
6886 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006887static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006888 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306889{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006890 struct hdd_request *request;
6891 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306892
6893 ENTER();
6894
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006895 request = hdd_request_get(context);
6896 if (!request) {
6897 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306898 return;
6899 }
6900
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006901 priv = hdd_request_priv(request);
6902 priv->bpf_get_offload = *data;
6903 hdd_request_complete(request);
6904 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306905}
6906
6907/**
6908 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6909 * @hdd_context: hdd_context
6910 * @bpf_get_offload: struct for get offload
6911 *
6912 * Return: 0 on success, error number otherwise.
6913 */
6914static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6915 struct sir_bpf_get_offload *bpf_get_offload)
6916{
6917 struct sk_buff *skb;
6918 uint32_t nl_buf_len;
6919
6920 ENTER();
6921
6922 nl_buf_len = NLMSG_HDRLEN;
6923 nl_buf_len +=
6924 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6925 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6926
6927 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6928 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006929 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306930 return -ENOMEM;
6931 }
6932
Jeff Johnson77848112016-06-29 14:52:06 -07006933 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306934 bpf_get_offload->bpf_version,
6935 bpf_get_offload->max_bytes_for_bpf_inst);
6936
6937 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6938 bpf_get_offload->max_bytes_for_bpf_inst) ||
6939 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006940 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306941 goto nla_put_failure;
6942 }
6943
6944 cfg80211_vendor_cmd_reply(skb);
6945 EXIT();
6946 return 0;
6947
6948nla_put_failure:
6949 kfree_skb(skb);
6950 return -EINVAL;
6951}
6952
6953/**
6954 * hdd_get_bpf_offload - Get BPF offload Capabilities
6955 * @hdd_ctx: Hdd context
6956 *
6957 * Return: 0 on success, errno on failure
6958 */
6959static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6960{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306961 QDF_STATUS status;
6962 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006963 void *cookie;
6964 struct hdd_request *request;
6965 struct bpf_offload_priv *priv;
6966 static const struct hdd_request_params params = {
6967 .priv_size = sizeof(*priv),
6968 .timeout_ms = WLAN_WAIT_TIME_BPF,
6969 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306970
6971 ENTER();
6972
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006973 request = hdd_request_alloc(&params);
6974 if (!request) {
6975 hdd_err("Unable to allocate request");
6976 return -EINVAL;
6977 }
6978 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306979
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006980 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6981 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006982 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006984 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006985 ret = qdf_status_to_os_return(status);
6986 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306987 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006988 ret = hdd_request_wait_for_response(request);
6989 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006990 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006991 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306992 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006993 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306994 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006995 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306996 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006997 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306998
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006999cleanup:
7000 /*
7001 * either we never sent a request to SME, we sent a request to
7002 * SME and timed out, or we sent a request to SME, received a
7003 * response from SME, and posted the response to userspace.
7004 * regardless we are done with the request.
7005 */
7006 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307007 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007008
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307009 return ret;
7010}
7011
7012/**
7013 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7014 * @hdd_ctx: Hdd context
7015 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307016 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307017 *
7018 * Return: 0 on success; errno on failure
7019 */
7020static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7021 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307022 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307023{
7024 struct sir_bpf_set_offload *bpf_set_offload;
7025 QDF_STATUS status;
7026 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307027 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307028
7029 ENTER();
7030
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307031 if (adapter->device_mode == QDF_STA_MODE ||
7032 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7033 if (!hdd_conn_is_connected(
7034 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7035 hdd_err("Not in Connected state!");
7036 return -ENOTSUPP;
7037 }
7038 }
7039
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307040 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7041 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007042 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307043 return -ENOMEM;
7044 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307045
7046 /* Parse and fetch bpf packet size */
7047 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007048 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307049 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307050 goto fail;
7051 }
7052 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7053
7054 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007055 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307056 goto post_sme;
7057 }
7058
7059 /* Parse and fetch bpf program */
7060 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007061 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307062 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307063 goto fail;
7064 }
7065
7066 prog_len = nla_len(tb[BPF_PROGRAM]);
7067 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307068
7069 if (bpf_set_offload->program == NULL) {
7070 hdd_err("qdf_mem_malloc failed for bpf offload program");
7071 ret = -ENOMEM;
7072 goto fail;
7073 }
7074
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307075 bpf_set_offload->current_length = prog_len;
7076 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307077 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307078
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307079 hdd_info("BPF set instructions");
7080 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7081 bpf_set_offload->program, prog_len);
7082
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307083 /* Parse and fetch filter Id */
7084 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007085 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307086 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307087 goto fail;
7088 }
7089 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7090
7091 /* Parse and fetch current offset */
7092 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007093 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307094 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307095 goto fail;
7096 }
7097 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7098
7099post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007100 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 +05307101 bpf_set_offload->session_id,
7102 bpf_set_offload->version,
7103 bpf_set_offload->filter_id,
7104 bpf_set_offload->total_length,
7105 bpf_set_offload->current_length,
7106 bpf_set_offload->current_offset);
7107
7108 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7109 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007110 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307111 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307112 goto fail;
7113 }
7114 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307115
7116fail:
7117 if (bpf_set_offload->current_length)
7118 qdf_mem_free(bpf_set_offload->program);
7119 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307120 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307121}
7122
7123/**
7124 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7125 * @wiphy: wiphy structure pointer
7126 * @wdev: Wireless device structure pointer
7127 * @data: Pointer to the data received
7128 * @data_len: Length of @data
7129 *
7130 * Return: 0 on success; errno on failure
7131 */
7132static int
7133__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7134 struct wireless_dev *wdev,
7135 const void *data, int data_len)
7136{
7137 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7138 struct net_device *dev = wdev->netdev;
7139 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7140 struct nlattr *tb[BPF_MAX + 1];
7141 int ret_val, packet_filter_subcmd;
7142
7143 ENTER();
7144
7145 ret_val = wlan_hdd_validate_context(hdd_ctx);
7146 if (ret_val)
7147 return ret_val;
7148
7149 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007150 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307151 return -EINVAL;
7152 }
7153
7154 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007155 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307156 return -ENOTSUPP;
7157 }
7158
7159 if (nla_parse(tb, BPF_MAX, data, data_len,
7160 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007161 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307162 return -EINVAL;
7163 }
7164
7165 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007166 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307167 return -EINVAL;
7168 }
7169
7170 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7171
7172 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7173 return hdd_get_bpf_offload(hdd_ctx);
7174 else
7175 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307176 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307177}
7178
7179/**
7180 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7181 * @wiphy: wiphy structure pointer
7182 * @wdev: Wireless device structure pointer
7183 * @data: Pointer to the data received
7184 * @data_len: Length of @data
7185 *
7186 * Return: 0 on success; errno on failure
7187 */
7188
7189static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7190 struct wireless_dev *wdev,
7191 const void *data, int data_len)
7192{
7193 int ret;
7194
7195 cds_ssr_protect(__func__);
7196 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7197 cds_ssr_unprotect(__func__);
7198
7199 return ret;
7200}
7201
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307202/**
7203 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7204 * @pre_cac_adapter: AP adapter used for pre cac
7205 * @status: Status (true or false)
7206 * @handle: Global handle
7207 *
7208 * Sets the status of pre cac i.e., whether the pre cac is active or not
7209 *
7210 * Return: Zero on success, non-zero on failure
7211 */
7212static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7213 bool status, tHalHandle handle)
7214{
7215 QDF_STATUS ret;
7216
7217 ret = wlan_sap_set_pre_cac_status(
7218 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7219 if (QDF_IS_STATUS_ERROR(ret))
7220 return -EINVAL;
7221
7222 return 0;
7223}
7224
7225/**
7226 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7227 * @ap_adapter: AP adapter
7228 * @chan_before_pre_cac: Channel
7229 *
7230 * Saves the channel which the AP was beaconing on before moving to the pre
7231 * cac channel. If radar is detected on the pre cac channel, this saved
7232 * channel will be used for AP operations.
7233 *
7234 * Return: Zero on success, non-zero on failure
7235 */
7236static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7237 uint8_t chan_before_pre_cac)
7238{
7239 QDF_STATUS ret;
7240
7241 ret = wlan_sap_set_chan_before_pre_cac(
7242 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7243 if (QDF_IS_STATUS_ERROR(ret))
7244 return -EINVAL;
7245
7246 return 0;
7247}
7248
7249/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307250 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7251 * are in nol list from provided channel list
7252 * @adapter: AP adapter
7253 * @channel_count: channel count
7254 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307255 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307256 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307257 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307258static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7259 uint32_t *channel_count,
7260 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307261{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307262 uint8_t i, j;
7263 uint32_t nol_len = 0;
7264 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7265 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7266 uint32_t chan_count;
7267 bool found;
7268 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307269
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307270 if (!hdd_ctx) {
7271 hdd_err("hdd ctx not found");
7272 *channel_count = 0;
7273 return;
7274 }
7275
7276 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7277 hdd_err("invalid channel count %d", *channel_count);
7278 return;
7279 }
7280
7281 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7282 if (nol_len == 0)
7283 return;
7284
7285 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7286 chan_count = *channel_count;
7287 qdf_mem_zero(channel_list, chan_count);
7288 *channel_count = 0;
7289
7290 for (i = 0 ; i < chan_count; i++) {
7291 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7292 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7293 continue;
7294 found = false;
7295 for (j = 0; j < nol_len; j++) {
7296 if (tmp_chan_list[i] == nol[j]) {
7297 found = true;
7298 hdd_notice("skipped channel %d due to nol",
7299 nol[j]);
7300 break;
7301 }
7302 }
7303 if (!found) {
7304 channel_list[*channel_count] = tmp_chan_list[i];
7305 *channel_count = *channel_count + 1;
7306 }
7307 }
7308}
7309
7310int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7311 uint32_t *channel_count,
7312 uint8_t *channel_list)
7313{
7314 tsap_Config_t *sap_config;
7315
7316 sap_config = &adapter->sessionCtx.ap.sapConfig;
7317
7318 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7319 sap_config->acs_cfg.ch_list_count);
7320 *channel_count = sap_config->acs_cfg.ch_list_count;
7321 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7322
7323 if (*channel_count == 0) {
7324 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307325 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307326 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307327
7328 return 0;
7329}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307330
7331/**
7332 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7333 * @hdd_ctx: HDD context
7334 * @ap_adapter: AP adapter
7335 * @channel: Channel requested by userspace
7336 * @pre_cac_chan: Pointer to the pre CAC channel
7337 *
7338 * Validates the channel provided by userspace. If user provided channel 0,
7339 * a valid outdoor channel must be selected from the regulatory channel.
7340 *
7341 * Return: Zero on success and non zero value on error
7342 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007343static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7344 hdd_adapter_t *ap_adapter,
7345 uint8_t channel,
7346 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307347{
7348 uint32_t i, j;
7349 QDF_STATUS status;
7350 int ret;
7351 uint8_t nol[QDF_MAX_NUM_CHAN];
7352 uint32_t nol_len = 0, weight_len = 0;
7353 bool found;
7354 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7355 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7356 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7357
7358 if (0 == channel) {
7359 /* Channel is not obtained from PCL because PCL may not have
7360 * the entire channel list. For example: if SAP is up on
7361 * channel 6 and PCL is queried for the next SAP interface,
7362 * if SCC is preferred, the PCL will contain only the channel
7363 * 6. But, we are in need of a DFS channel. So, going with the
7364 * first channel from the valid channel list.
7365 */
7366 status = cds_get_valid_chans(channel_list, &len);
7367 if (QDF_IS_STATUS_ERROR(status)) {
7368 hdd_err("Failed to get channel list");
7369 return -EINVAL;
7370 }
7371 cds_update_with_safe_channel_list(channel_list, &len,
7372 pcl_weights, weight_len);
7373 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7374 for (i = 0; i < len; i++) {
7375 found = false;
7376 for (j = 0; j < nol_len; j++) {
7377 if (channel_list[i] == nol[j]) {
7378 found = true;
7379 break;
7380 }
7381 }
7382 if (found)
7383 continue;
7384 if (CDS_IS_DFS_CH(channel_list[i])) {
7385 *pre_cac_chan = channel_list[i];
7386 break;
7387 }
7388 }
7389 if (*pre_cac_chan == 0) {
7390 hdd_err("unable to find outdoor channel");
7391 return -EINVAL;
7392 }
7393 } else {
7394 /* Only when driver selects a channel, check is done for
7395 * unnsafe and NOL channels. When user provides a fixed channel
7396 * the user is expected to take care of this.
7397 */
7398 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7399 !CDS_IS_DFS_CH(channel)) {
7400 hdd_err("Invalid channel for pre cac:%d", channel);
7401 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307402 }
Jeff Johnson68755312017-02-10 11:46:55 -08007403
7404 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307405 }
7406 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7407 return 0;
7408}
7409
7410/**
7411 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7412 * @channel: Channel option provided by userspace
7413 *
7414 * Sets the driver to the required hardware mode and start an adapater for
7415 * pre CAC which will mimic an AP.
7416 *
7417 * Return: Zero on success, non-zero value on error
7418 */
7419int wlan_hdd_request_pre_cac(uint8_t channel)
7420{
Krunal Sonib37bb352016-12-20 14:12:21 -08007421 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307422 hdd_context_t *hdd_ctx;
7423 int ret;
7424 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7425 hdd_ap_ctx_t *hdd_ap_ctx;
7426 QDF_STATUS status;
7427 struct wiphy *wiphy;
7428 struct net_device *dev;
7429 struct cfg80211_chan_def chandef;
7430 enum nl80211_channel_type channel_type;
7431 uint32_t freq;
7432 struct ieee80211_channel *chan;
7433 tHalHandle handle;
7434 bool val;
7435
7436 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7437 if (0 != wlan_hdd_validate_context(hdd_ctx))
7438 return -EINVAL;
7439
7440 if (cds_get_connection_count() > 1) {
7441 hdd_err("pre cac not allowed in concurrency");
7442 return -EINVAL;
7443 }
7444
7445 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7446 if (!ap_adapter) {
7447 hdd_err("unable to get SAP adapter");
7448 return -EINVAL;
7449 }
7450
7451 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7452 if (!handle) {
7453 hdd_err("Invalid handle");
7454 return -EINVAL;
7455 }
7456
7457 val = wlan_sap_is_pre_cac_active(handle);
7458 if (val) {
7459 hdd_err("pre cac is already in progress");
7460 return -EINVAL;
7461 }
7462
7463 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7464 if (!hdd_ap_ctx) {
7465 hdd_err("SAP context is NULL");
7466 return -EINVAL;
7467 }
7468
7469 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7470 hdd_err("SAP is already on DFS channel:%d",
7471 hdd_ap_ctx->operatingChannel);
7472 return -EINVAL;
7473 }
7474
7475 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7476 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7477 hdd_ap_ctx->operatingChannel);
7478 return -EINVAL;
7479 }
7480
Krunal Sonib37bb352016-12-20 14:12:21 -08007481 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7482 if (!mac_addr) {
7483 hdd_err("can't add virtual intf: Not getting valid mac addr");
7484 return -EINVAL;
7485 }
7486
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307487 hdd_info("channel:%d", channel);
7488
7489 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7490 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007491 if (ret != 0) {
7492 hdd_err("can't validate pre-cac channel");
7493 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307494 }
7495
7496 hdd_debug("starting pre cac SAP adapter");
7497
7498 /* Starting a SAP adapter:
7499 * Instead of opening an adapter, we could just do a SME open session
7500 * for AP type. But, start BSS would still need an adapter.
7501 * So, this option is not taken.
7502 *
7503 * hdd open adapter is going to register this precac interface with
7504 * user space. This interface though exposed to user space will be in
7505 * DOWN state. Consideration was done to avoid this registration to the
7506 * user space. But, as part of SAP operations multiple events are sent
7507 * to user space. Some of these events received from unregistered
7508 * interface was causing crashes. So, retaining the registration.
7509 *
7510 * So, this interface would remain registered and will remain in DOWN
7511 * state for the CAC duration. We will add notes in the feature
7512 * announcement to not use this temporary interface for any activity
7513 * from user space.
7514 */
7515 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007516 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307517 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307518 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007519 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307520 }
7521
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307522 /*
7523 * This interface is internally created by the driver. So, no interface
7524 * up comes for this interface from user space and hence starting
7525 * the adapter internally.
7526 */
7527 if (hdd_start_adapter(pre_cac_adapter)) {
7528 hdd_err("error starting the pre cac adapter");
7529 goto close_pre_cac_adapter;
7530 }
7531
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307532 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7533
7534 wiphy = hdd_ctx->wiphy;
7535 dev = pre_cac_adapter->dev;
7536
7537 /* Since this is only a dummy interface lets us use the IEs from the
7538 * other active SAP interface. In regular scenarios, these IEs would
7539 * come from the user space entity
7540 */
7541 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7542 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7543 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7544 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307545 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307546 }
7547 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7548 ap_adapter->sessionCtx.ap.beacon,
7549 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7550 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7551 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7552 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7553 ap_adapter->sessionCtx.ap.sapConfig.authType;
7554
7555 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7556 * to operate on the same bandwidth as that of the 2.4GHz operations.
7557 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7558 */
7559 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7560 case CH_WIDTH_20MHZ:
7561 channel_type = NL80211_CHAN_HT20;
7562 break;
7563 case CH_WIDTH_40MHZ:
7564 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7565 ap_adapter->sessionCtx.ap.sapConfig.channel)
7566 channel_type = NL80211_CHAN_HT40PLUS;
7567 else
7568 channel_type = NL80211_CHAN_HT40MINUS;
7569 break;
7570 default:
7571 channel_type = NL80211_CHAN_NO_HT;
7572 break;
7573 }
7574
7575 freq = cds_chan_to_freq(pre_cac_chan);
7576 chan = __ieee80211_get_channel(wiphy, freq);
7577 if (!chan) {
7578 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307579 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307580 }
7581
7582 cfg80211_chandef_create(&chandef, chan, channel_type);
7583
7584 hdd_debug("orig width:%d channel_type:%d freq:%d",
7585 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7586 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007587 /*
7588 * Doing update after opening and starting pre-cac adapter will make
7589 * sure that driver won't do hardware mode change if there are any
7590 * initial hick-ups or issues in pre-cac adapter's configuration.
7591 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7592 * connection update should result in DBS mode
7593 */
7594 status = cds_update_and_wait_for_connection_update(
7595 ap_adapter->sessionId,
7596 pre_cac_chan,
7597 SIR_UPDATE_REASON_PRE_CAC);
7598 if (QDF_IS_STATUS_ERROR(status)) {
7599 hdd_err("error in moving to DBS mode");
7600 goto stop_close_pre_cac_adapter;
7601 }
7602
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307603
7604 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7605 if (0 != ret) {
7606 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307607 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307608 }
7609
7610 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7611 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007612 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307613 if (QDF_IS_STATUS_ERROR(status)) {
7614 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307615 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307616 }
7617
7618 /*
7619 * The pre cac status is set here. But, it would not be reset explicitly
7620 * anywhere, since after the pre cac success/failure, the pre cac
7621 * adapter itself would be removed.
7622 */
7623 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7624 if (0 != ret) {
7625 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307626 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307627 }
7628
7629 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7630 hdd_ap_ctx->operatingChannel);
7631 if (0 != ret) {
7632 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307633 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307634 }
7635
7636 ap_adapter->pre_cac_chan = pre_cac_chan;
7637
7638 return 0;
7639
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307640stop_close_pre_cac_adapter:
7641 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307642 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7643 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307644close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307645 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007646release_intf_addr_and_return_failure:
7647 /*
7648 * Release the interface address as the adapter
7649 * failed to start, if you don't release then next
7650 * adapter which is trying to come wouldn't get valid
7651 * mac address. Remember we have limited pool of mac addresses
7652 */
7653 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307654 return -EINVAL;
7655}
7656
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307657static const struct nla_policy
7658wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7659 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7660};
7661
Agrawal Ashish65634612016-08-18 13:24:32 +05307662static const struct nla_policy
7663wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7664 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7665 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7666};
7667
7668/**
7669 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7670 * @wiphy: Pointer to wireless phy
7671 * @wdev: Pointer to wireless device
7672 * @data: Pointer to data
7673 * @data_len: Length of @data
7674 *
7675 * This function parses the incoming NL vendor command data attributes and
7676 * updates the SAP context about channel_hint and DFS mode.
7677 * If channel_hint is set, SAP will choose that channel
7678 * as operating channel.
7679 *
7680 * If DFS mode is enabled, driver will include DFS channels
7681 * in ACS else driver will skip DFS channels.
7682 *
7683 * Return: 0 on success, negative errno on failure
7684 */
7685static int
7686__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7687 struct wireless_dev *wdev,
7688 const void *data, int data_len)
7689{
7690 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7691 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7692 int ret;
7693 struct acs_dfs_policy *acs_policy;
7694 int mode = DFS_MODE_NONE;
7695 int channel_hint = 0;
7696
7697 ENTER_DEV(wdev->netdev);
7698
7699 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7700 hdd_err("Command not allowed in FTM mode");
7701 return -EINVAL;
7702 }
7703
7704 ret = wlan_hdd_validate_context(hdd_ctx);
7705 if (0 != ret)
7706 return ret;
7707
7708 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7709 data, data_len,
7710 wlan_hdd_set_acs_dfs_config_policy)) {
7711 hdd_err("invalid attr");
7712 return -EINVAL;
7713 }
7714
7715 acs_policy = &hdd_ctx->acs_policy;
7716 /*
7717 * SCM sends this attribute to restrict SAP from choosing
7718 * DFS channels from ACS.
7719 */
7720 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7721 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7722
7723 if (!IS_DFS_MODE_VALID(mode)) {
7724 hdd_err("attr acs dfs mode is not valid");
7725 return -EINVAL;
7726 }
7727 acs_policy->acs_dfs_mode = mode;
7728
7729 /*
7730 * SCM sends this attribute to provide an active channel,
7731 * to skip redundant ACS between drivers, and save driver start up time
7732 */
7733 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7734 channel_hint = nla_get_u8(
7735 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7736
7737 if (!IS_CHANNEL_VALID(channel_hint)) {
7738 hdd_err("acs channel is not valid");
7739 return -EINVAL;
7740 }
7741 acs_policy->acs_channel = channel_hint;
7742
7743 return 0;
7744}
7745
7746/**
7747 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7748 * @wiphy: wiphy structure pointer
7749 * @wdev: Wireless device structure pointer
7750 * @data: Pointer to the data received
7751 * @data_len: Length of @data
7752 *
7753 * This function parses the incoming NL vendor command data attributes and
7754 * updates the SAP context about channel_hint and DFS mode.
7755 *
7756 * Return: 0 on success; errno on failure
7757 */
7758static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7759 struct wireless_dev *wdev,
7760 const void *data, int data_len)
7761{
7762 int ret;
7763
7764 cds_ssr_protect(__func__);
7765 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7766 cds_ssr_unprotect(__func__);
7767
7768 return ret;
7769}
7770
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307771/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307772 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7773 * @mode : cfg80211 dfs mode
7774 *
7775 * Return: return csr sta roam dfs mode else return NONE
7776 */
7777static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7778 enum dfs_mode mode)
7779{
7780 switch (mode) {
7781 case DFS_MODE_ENABLE:
7782 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7783 break;
7784 case DFS_MODE_DISABLE:
7785 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7786 break;
7787 case DFS_MODE_DEPRIORITIZE:
7788 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7789 break;
7790 default:
7791 hdd_err("STA Roam policy dfs mode is NONE");
7792 return CSR_STA_ROAM_POLICY_NONE;
7793 }
7794}
7795
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307796/*
7797 * hdd_get_sap_operating_band: Get current operating channel
7798 * for sap.
7799 * @hdd_ctx: hdd context
7800 *
7801 * Return : Corresponding band for SAP operating channel
7802 */
7803uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7804{
7805 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7806 QDF_STATUS status;
7807 hdd_adapter_t *adapter;
7808 uint8_t operating_channel = 0;
7809 uint8_t sap_operating_band = 0;
7810 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7811 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7812 adapter = adapter_node->pAdapter;
7813
7814 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7815 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7816 &next);
7817 adapter_node = next;
7818 continue;
7819 }
7820 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7821 if (IS_24G_CH(operating_channel))
7822 sap_operating_band = eCSR_BAND_24;
7823 else if (IS_5G_CH(operating_channel))
7824 sap_operating_band = eCSR_BAND_5G;
7825 else
7826 sap_operating_band = eCSR_BAND_ALL;
7827 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7828 &next);
bings373b99b2017-01-23 10:35:08 +08007829 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307830 }
7831 return sap_operating_band;
7832}
7833
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307834static const struct nla_policy
7835wlan_hdd_set_sta_roam_config_policy[
7836QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7837 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7838 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7839};
7840
7841/**
7842 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7843 * for station connection or roaming.
7844 * @wiphy: Pointer to wireless phy
7845 * @wdev: Pointer to wireless device
7846 * @data: Pointer to data
7847 * @data_len: Length of @data
7848 *
7849 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7850 * channels needs to be skipped in scanning or not.
7851 * If dfs_mode is disabled, driver will not scan DFS channels.
7852 * If skip_unsafe_channels is set, driver will skip unsafe channels
7853 * in Scanning.
7854 *
7855 * Return: 0 on success, negative errno on failure
7856 */
7857static int
7858__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7859 struct wireless_dev *wdev,
7860 const void *data, int data_len)
7861{
7862 struct net_device *dev = wdev->netdev;
7863 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7864 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7865 struct nlattr *tb[
7866 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7867 int ret;
7868 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7869 enum dfs_mode mode = DFS_MODE_NONE;
7870 bool skip_unsafe_channels = false;
7871 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307872 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307873
7874 ENTER_DEV(dev);
7875
7876 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7877 hdd_err("Command not allowed in FTM mode");
7878 return -EINVAL;
7879 }
7880
7881 ret = wlan_hdd_validate_context(hdd_ctx);
7882 if (0 != ret)
7883 return ret;
7884 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7885 data, data_len,
7886 wlan_hdd_set_sta_roam_config_policy)) {
7887 hdd_err("invalid attr");
7888 return -EINVAL;
7889 }
7890 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7891 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7892 if (!IS_DFS_MODE_VALID(mode)) {
7893 hdd_err("attr sta roam dfs mode policy is not valid");
7894 return -EINVAL;
7895 }
7896
7897 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7898
7899 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7900 skip_unsafe_channels = nla_get_u8(
7901 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307902 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307903 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307904 skip_unsafe_channels, adapter->sessionId,
7905 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307906
7907 if (!QDF_IS_STATUS_SUCCESS(status)) {
7908 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7909 return -EINVAL;
7910 }
7911 return 0;
7912}
7913
7914/**
7915 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7916 * connection and roaming for station.
7917 * @wiphy: wiphy structure pointer
7918 * @wdev: Wireless device structure pointer
7919 * @data: Pointer to the data received
7920 * @data_len: Length of @data
7921 *
7922 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7923 * channels needs to be skipped in scanning or not.
7924 * If dfs_mode is disabled, driver will not scan DFS channels.
7925 * If skip_unsafe_channels is set, driver will skip unsafe channels
7926 * in Scanning.
7927 * Return: 0 on success; errno on failure
7928 */
7929static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7930 struct wireless_dev *wdev,
7931 const void *data, int data_len)
7932{
7933 int ret;
7934
7935 cds_ssr_protect(__func__);
7936 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7937 cds_ssr_unprotect(__func__);
7938
7939 return ret;
7940}
7941
Agrawal Ashish467dde42016-09-08 18:44:22 +05307942#ifdef FEATURE_WLAN_CH_AVOID
7943/**
7944 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7945 * is on unsafe channel.
7946 * @wiphy: wiphy structure pointer
7947 * @wdev: Wireless device structure pointer
7948 * @data: Pointer to the data received
7949 * @data_len: Length of @data
7950 *
7951 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7952 * on any of unsafe channels.
7953 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7954 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7955 *
7956 * Return: 0 on success; errno on failure
7957 */
7958static int
7959__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7960 struct wireless_dev *wdev,
7961 const void *data, int data_len)
7962{
7963 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7964 int ret;
7965 uint16_t unsafe_channel_count;
7966 int unsafe_channel_index;
7967 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7968
7969 ENTER_DEV(wdev->netdev);
7970
7971 if (!qdf_ctx) {
7972 cds_err("qdf_ctx is NULL");
7973 return -EINVAL;
7974 }
7975
7976 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7977 hdd_err("Command not allowed in FTM mode");
7978 return -EINVAL;
7979 }
7980
7981 ret = wlan_hdd_validate_context(hdd_ctx);
7982 if (0 != ret)
7983 return ret;
7984 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7985 &(hdd_ctx->unsafe_channel_count),
7986 sizeof(hdd_ctx->unsafe_channel_list));
7987
7988 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7989 (uint16_t)NUM_CHANNELS);
7990 for (unsafe_channel_index = 0;
7991 unsafe_channel_index < unsafe_channel_count;
7992 unsafe_channel_index++) {
7993 hdd_info("Channel %d is not safe",
7994 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7995 }
7996 hdd_unsafe_channel_restart_sap(hdd_ctx);
7997 return 0;
7998}
7999
8000/**
8001 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8002 * is on unsafe channel.
8003 * @wiphy: wiphy structure pointer
8004 * @wdev: Wireless device structure pointer
8005 * @data: Pointer to the data received
8006 * @data_len: Length of @data
8007 *
8008 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8009 * on any of unsafe channels.
8010 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8011 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8012 *
8013 * Return: 0 on success; errno on failure
8014 */
8015static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8016 struct wireless_dev *wdev,
8017 const void *data, int data_len)
8018{
8019 int ret;
8020
8021 cds_ssr_protect(__func__);
8022 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8023 cds_ssr_unprotect(__func__);
8024
8025 return ret;
8026}
8027
8028#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308029/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308030 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8031 * SAP is on unsafe channel.
8032 * @wiphy: wiphy structure pointer
8033 * @wdev: Wireless device structure pointer
8034 * @data: Pointer to the data received
8035 * @data_len: Length of @data
8036 *
8037 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8038 * driver.
8039 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8040 * will initiate restart of sap.
8041 *
8042 * Return: 0 on success; errno on failure
8043 */
8044static int
8045__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8046 struct wireless_dev *wdev,
8047 const void *data, int data_len)
8048{
8049 struct net_device *ndev = wdev->netdev;
8050 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8051 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8052 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8053 uint8_t config_channel = 0;
8054 hdd_ap_ctx_t *ap_ctx;
8055 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308056 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308057
8058 ENTER();
8059
8060 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008061 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308062 return -EINVAL;
8063 }
8064
8065 ret = wlan_hdd_validate_context(hdd_ctx);
8066 if (0 != ret)
8067 return -EINVAL;
8068
8069 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8070 data, data_len,
8071 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008072 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308073 return -EINVAL;
8074 }
8075
8076 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8077 if (!test_bit(SOFTAP_BSS_STARTED,
8078 &hostapd_adapter->event_flags)) {
8079 hdd_err("SAP is not started yet. Restart sap will be invalid");
8080 return -EINVAL;
8081 }
8082
8083 config_channel =
8084 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8085
8086 if (!((IS_24G_CH(config_channel)) ||
8087 (IS_5G_CH(config_channel)))) {
8088 hdd_err("Channel %d is not valid to restart SAP",
8089 config_channel);
8090 return -ENOTSUPP;
8091 }
8092
8093 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8094 ap_ctx->sapConfig.channel = config_channel;
8095 ap_ctx->sapConfig.ch_params.ch_width =
8096 ap_ctx->sapConfig.ch_width_orig;
8097
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008098 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308099 ap_ctx->sapConfig.sec_ch,
8100 &ap_ctx->sapConfig.ch_params);
8101
8102 cds_restart_sap(hostapd_adapter);
8103 }
8104
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308105 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8106 uint32_t freq_len, i;
8107 uint32_t *freq;
8108 uint8_t chans[QDF_MAX_NUM_CHAN];
8109
8110 hdd_debug("setting mandatory freq/chan list");
8111
8112 freq_len = nla_len(
8113 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8114 sizeof(uint32_t);
8115
8116 if (freq_len > QDF_MAX_NUM_CHAN) {
8117 hdd_err("insufficient space to hold channels");
8118 return -ENOMEM;
8119 }
8120
8121 freq = nla_data(
8122 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8123
8124 hdd_debug("freq_len=%d", freq_len);
8125
8126 for (i = 0; i < freq_len; i++) {
8127 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8128 hdd_debug("freq[%d]=%d", i, freq[i]);
8129 }
8130
8131 status = cds_set_sap_mandatory_channels(chans, freq_len);
8132 if (QDF_IS_STATUS_ERROR(status))
8133 return -EINVAL;
8134 }
8135
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308136 return 0;
8137}
8138
8139/**
8140 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8141 * @wiphy: wiphy structure pointer
8142 * @wdev: Wireless device structure pointer
8143 * @data: Pointer to the data received
8144 * @data_len: Length of @data
8145 *
8146 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8147 * driver.
8148 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8149 * will initiate restart of sap.
8150 *
8151 * Return: 0 on success; errno on failure
8152 */
8153static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8154 struct wireless_dev *wdev,
8155 const void *data, int data_len)
8156{
8157 int ret;
8158
8159 cds_ssr_protect(__func__);
8160 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8161 wdev, data, data_len);
8162 cds_ssr_unprotect(__func__);
8163
8164 return ret;
8165}
8166
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308167#undef BPF_INVALID
8168#undef BPF_SET_RESET
8169#undef BPF_VERSION
8170#undef BPF_ID
8171#undef BPF_PACKET_SIZE
8172#undef BPF_CURRENT_OFFSET
8173#undef BPF_PROGRAM
8174#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308175
8176/**
8177 * define short names for the global vendor params
8178 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8179 */
8180#define PARAM_TOTAL_CMD_EVENT_WAKE \
8181 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8182#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8183 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8184#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8185 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8186#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8187 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8188#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8189 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8190#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8191 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8192#define PARAM_TOTAL_RX_DATA_WAKE \
8193 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8194#define PARAM_RX_UNICAST_CNT \
8195 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8196#define PARAM_RX_MULTICAST_CNT \
8197 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8198#define PARAM_RX_BROADCAST_CNT \
8199 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8200#define PARAM_ICMP_PKT \
8201 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8202#define PARAM_ICMP6_PKT \
8203 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8204#define PARAM_ICMP6_RA \
8205 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8206#define PARAM_ICMP6_NA \
8207 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8208#define PARAM_ICMP6_NS \
8209 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8210#define PARAM_ICMP4_RX_MULTICAST_CNT \
8211 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8212#define PARAM_ICMP6_RX_MULTICAST_CNT \
8213 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8214#define PARAM_OTHER_RX_MULTICAST_CNT \
8215 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308216#define PARAM_RSSI_BREACH_CNT \
8217 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8218#define PARAM_LOW_RSSI_CNT \
8219 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8220#define PARAM_GSCAN_CNT \
8221 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8222#define PARAM_PNO_COMPLETE_CNT \
8223 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8224#define PARAM_PNO_MATCH_CNT \
8225 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8226
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308227
8228
8229/**
8230 * hdd_send_wakelock_stats() - API to send wakelock stats
8231 * @ctx: context to be passed to callback
8232 * @data: data passed to callback
8233 *
8234 * This function is used to send wake lock stats to HAL layer
8235 *
8236 * Return: 0 on success, error number otherwise.
8237 */
8238static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8239 const struct sir_wake_lock_stats *data)
8240{
8241 struct sk_buff *skb;
8242 uint32_t nl_buf_len;
8243 uint32_t total_rx_data_wake, rx_multicast_cnt;
8244 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308245 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308246
8247 ENTER();
8248
8249 nl_buf_len = NLMSG_HDRLEN;
8250 nl_buf_len +=
8251 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8252 (NLMSG_HDRLEN + sizeof(uint32_t));
8253
8254 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8255
8256 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008257 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308258 return -ENOMEM;
8259 }
8260
Jeff Johnson64943bd2016-08-23 13:14:06 -07008261 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308262 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008263 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308264 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008265 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308266 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008267 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308268 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008269 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308270 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008271 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308272 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008273 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308274 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008275 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8276 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308277 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308278 hdd_info("wow_rssi_breach_wake_up_count %d",
8279 data->wow_rssi_breach_wake_up_count);
8280 hdd_info("wow_low_rssi_wake_up_count %d",
8281 data->wow_low_rssi_wake_up_count);
8282 hdd_info("wow_gscan_wake_up_count %d",
8283 data->wow_gscan_wake_up_count);
8284 hdd_info("wow_pno_complete_wake_up_count %d",
8285 data->wow_pno_complete_wake_up_count);
8286 hdd_info("wow_pno_match_wake_up_count %d",
8287 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308288
8289 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308290 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308291
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308292 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308293 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308294
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308295 rx_multicast_cnt =
8296 data->wow_ipv4_mcast_wake_up_count +
8297 ipv6_rx_multicast_addr_cnt;
8298
8299 total_rx_data_wake =
8300 data->wow_ucast_wake_up_count +
8301 data->wow_bcast_wake_up_count +
8302 rx_multicast_cnt;
8303
8304 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8305 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8306 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8307 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8308 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8309 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8310 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8311 total_rx_data_wake) ||
8312 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8313 data->wow_ucast_wake_up_count) ||
8314 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8315 rx_multicast_cnt) ||
8316 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8317 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308318 nla_put_u32(skb, PARAM_ICMP_PKT,
8319 data->wow_icmpv4_count) ||
8320 nla_put_u32(skb, PARAM_ICMP6_PKT,
8321 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308322 nla_put_u32(skb, PARAM_ICMP6_RA,
8323 data->wow_ipv6_mcast_ra_stats) ||
8324 nla_put_u32(skb, PARAM_ICMP6_NA,
8325 data->wow_ipv6_mcast_na_stats) ||
8326 nla_put_u32(skb, PARAM_ICMP6_NS,
8327 data->wow_ipv6_mcast_ns_stats) ||
8328 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8329 data->wow_ipv4_mcast_wake_up_count) ||
8330 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8331 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308332 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8333 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8334 data->wow_rssi_breach_wake_up_count) ||
8335 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8336 data->wow_low_rssi_wake_up_count) ||
8337 nla_put_u32(skb, PARAM_GSCAN_CNT,
8338 data->wow_gscan_wake_up_count) ||
8339 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8340 data->wow_pno_complete_wake_up_count) ||
8341 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8342 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008343 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308344 goto nla_put_failure;
8345 }
8346
8347 cfg80211_vendor_cmd_reply(skb);
8348
8349 EXIT();
8350 return 0;
8351
8352nla_put_failure:
8353 kfree_skb(skb);
8354 return -EINVAL;
8355}
8356
8357/**
8358 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8359 * @wiphy: wiphy pointer
8360 * @wdev: pointer to struct wireless_dev
8361 * @data: pointer to incoming NL vendor data
8362 * @data_len: length of @data
8363 *
8364 * This function parses the incoming NL vendor command data attributes and
8365 * invokes the SME Api and blocks on a completion variable.
8366 * WMA copies required data and invokes callback
8367 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8368 *
8369 * Return: 0 on success; error number otherwise.
8370 */
8371static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8372 struct wireless_dev *wdev,
8373 const void *data,
8374 int data_len)
8375{
8376 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8377 int status, ret;
8378 struct sir_wake_lock_stats wake_lock_stats;
8379 QDF_STATUS qdf_status;
8380
8381 ENTER();
8382
8383 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008384 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308385 return -EINVAL;
8386 }
8387
8388 status = wlan_hdd_validate_context(hdd_ctx);
8389 if (0 != status)
8390 return -EINVAL;
8391
8392 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8393 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008394 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308395 return -EINVAL;
8396 }
8397
8398 ret = hdd_send_wakelock_stats(hdd_ctx,
8399 &wake_lock_stats);
8400 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008401 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308402
8403 EXIT();
8404 return ret;
8405}
8406
8407/**
8408 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8409 * @wiphy: wiphy pointer
8410 * @wdev: pointer to struct wireless_dev
8411 * @data: pointer to incoming NL vendor data
8412 * @data_len: length of @data
8413 *
8414 * This function parses the incoming NL vendor command data attributes and
8415 * invokes the SME Api and blocks on a completion variable.
8416 * WMA copies required data and invokes callback
8417 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8418 *
8419 * Return: 0 on success; error number otherwise.
8420 */
8421static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8422 struct wireless_dev *wdev,
8423 const void *data, int data_len)
8424{
8425 int ret;
8426
8427 cds_ssr_protect(__func__);
8428 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8429 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008430 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308431
8432 return ret;
8433}
8434
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308435/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308436 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8437 * @wiphy: wiphy structure pointer
8438 * @wdev: Wireless device structure pointer
8439 * @data: Pointer to the data received
8440 * @data_len: Length of @data
8441 *
8442 * This function reads wmi max bus size and fill in the skb with
8443 * NL attributes and send up the NL event.
8444 * Return: 0 on success; errno on failure
8445 */
8446static int
8447__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8448 struct wireless_dev *wdev,
8449 const void *data, int data_len)
8450{
8451 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8452 int ret_val;
8453 struct sk_buff *skb;
8454 uint32_t nl_buf_len;
8455
8456 ENTER();
8457
8458 ret_val = wlan_hdd_validate_context(hdd_ctx);
8459 if (ret_val)
8460 return ret_val;
8461
8462 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8463 hdd_err("Command not allowed in FTM mode");
8464 return -EINVAL;
8465 }
8466
8467 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8468
8469 nl_buf_len = NLMSG_HDRLEN;
8470 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8471
8472 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8473 if (!skb) {
8474 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8475 return -ENOMEM;
8476 }
8477
8478 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8479 hdd_ctx->wmi_max_len)) {
8480 hdd_err("nla put failure");
8481 goto nla_put_failure;
8482 }
8483
8484 cfg80211_vendor_cmd_reply(skb);
8485
8486 EXIT();
8487
8488 return 0;
8489
8490nla_put_failure:
8491 kfree_skb(skb);
8492 return -EINVAL;
8493}
8494
8495/**
8496 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8497 * @wiphy: wiphy structure pointer
8498 * @wdev: Wireless device structure pointer
8499 * @data: Pointer to the data received
8500 * @data_len: Length of @data
8501 *
8502 * Return: 0 on success; errno on failure
8503 */
8504static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8505 struct wireless_dev *wdev,
8506 const void *data, int data_len)
8507{
8508 int ret;
8509
8510 cds_ssr_protect(__func__);
8511 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8512 cds_ssr_unprotect(__func__);
8513
8514 return ret;
8515}
8516
8517/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308518 *__wlan_hdd_cfg80211_setband() - set band
8519 * @wiphy: Pointer to wireless phy
8520 * @wdev: Pointer to wireless device
8521 * @data: Pointer to data
8522 * @data_len: Length of @data
8523 *
8524 * Return: 0 on success, negative errno on failure
8525 */
8526static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8527 struct wireless_dev *wdev,
8528 const void *data, int data_len)
8529{
8530 struct net_device *dev = wdev->netdev;
8531 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8532 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8533 int ret;
8534 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8535 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8536
8537 ENTER();
8538
8539 ret = wlan_hdd_validate_context(hdd_ctx);
8540 if (ret)
8541 return ret;
8542
8543 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8544 hdd_err(FL("Invalid ATTR"));
8545 return -EINVAL;
8546 }
8547
8548 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8549 hdd_err(FL("attr SETBAND_VALUE failed"));
8550 return -EINVAL;
8551 }
8552
8553 ret = hdd_set_band(dev,
8554 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8555
8556 EXIT();
8557 return ret;
8558}
8559
8560/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308561 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8562 * @adapter: hdd adapter
8563 * @channel: channel number
8564 *
8565 * return: QDF status based on success or failure
8566 */
8567static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8568 int channel, int chan_bw)
8569{
8570 if (QDF_STATUS_SUCCESS !=
8571 wlan_hdd_validate_operation_channel(adapter, channel))
8572 return QDF_STATUS_E_FAILURE;
8573 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8574 channel,
8575 PHY_SINGLE_CHANNEL_CENTERED))) {
8576 hdd_notice("channel %d is in nol", channel);
8577 return -EINVAL;
8578 }
8579
8580 if ((wlansap_is_channel_leaking_in_nol(
8581 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8582 channel, chan_bw))) {
8583 hdd_notice("channel %d is leaking in nol", channel);
8584 return -EINVAL;
8585 }
8586
8587 return 0;
8588
8589}
8590
Kapil Gupta8878ad92017-02-13 11:56:04 +05308591static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8592 tsap_Config_t *sap_config,
8593 struct hdd_vendor_chan_info *channel_list)
8594{
8595 sap_config->channel = channel_list->pri_ch;
8596
8597 sap_config->ch_params.center_freq_seg0 =
8598 channel_list->vht_seg0_center_ch;
8599 sap_config->ch_params.center_freq_seg1 =
8600 channel_list->vht_seg1_center_ch;
8601
8602 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8603 sap_config->ch_params.ch_width = channel_list->chan_width;
8604 if (sap_config->channel >= 36)
8605 sap_config->ch_width_orig =
8606 hdd_ctx->config->vhtChannelWidth;
8607 else
8608 sap_config->ch_width_orig =
8609 hdd_ctx->config->nChannelBondingMode24GHz ?
8610 eHT_CHANNEL_WIDTH_40MHZ :
8611 eHT_CHANNEL_WIDTH_20MHZ;
8612
8613 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8614 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8615 sap_config->acs_cfg.vht_seg0_center_ch =
8616 channel_list->vht_seg0_center_ch;
8617 sap_config->acs_cfg.vht_seg1_center_ch =
8618 channel_list->vht_seg1_center_ch;
8619 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8620}
8621
8622static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8623 uint8_t channel_cnt,
8624 struct hdd_vendor_chan_info *channel_list)
8625{
8626 tsap_Config_t *sap_config;
8627 hdd_ap_ctx_t *hdd_ap_ctx;
8628 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8629 QDF_STATUS status = QDF_STATUS_SUCCESS;
8630
8631 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8632 sap_config = &adapter->sessionCtx.ap.sapConfig;
8633
8634 if (QDF_TIMER_STATE_RUNNING ==
8635 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8636 ap.vendor_acs_timer)) {
8637 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8638 }
8639
8640 if (channel_list && channel_list->pri_ch == 0) {
8641 /* Check mode, set default channel */
8642 channel_list->pri_ch = 6;
8643 /*
8644 * sap_select_default_oper_chan(hdd_ctx->hHal,
8645 * sap_config->acs_cfg.hw_mode);
8646 */
8647 }
8648
8649 switch (reason) {
8650 /* SAP init case */
8651 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8652 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8653 /* Update Hostapd */
8654 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8655 break;
8656
8657 /* DFS detected on current channel */
8658 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8659 wlan_sap_update_next_channel(
8660 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8661 channel_list->pri_ch,
8662 channel_list->chan_width);
8663 status = sme_update_new_channel_event(
8664 WLAN_HDD_GET_HAL_CTX(adapter),
8665 adapter->sessionId);
8666 break;
8667
8668 /* LTE coex event on current channel */
8669 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8670 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8671 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8672 hdd_ap_ctx->sapConfig.ch_width_orig =
8673 channel_list->chan_width;
8674 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8675 break;
8676
8677 default:
8678 hdd_info("invalid reason for timer invoke");
8679 }
8680 qdf_mem_free(channel_list);
8681 EXIT();
8682 return status;
8683}
8684
8685/**
8686 * Define short name for vendor channel set config
8687 */
8688#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8689#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8690#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8691#define SET_CHAN_PRIMARY_CHANNEL \
8692 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8693#define SET_CHAN_SECONDARY_CHANNEL \
8694 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8695#define SET_CHAN_SEG0_CENTER_CHANNEL \
8696 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8697#define SET_CHAN_SEG1_CENTER_CHANNEL \
8698 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8699#define SET_CHAN_CHANNEL_WIDTH \
8700 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8701#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8702
8703/**
8704 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8705 * @channel_list: pointer to hdd_vendor_chan_info
8706 * @reason: channel change reason
8707 * @channel_cnt: channel count
8708 * @data: data
8709 * @data_len: data len
8710 *
8711 * Return: 0 on success, negative errno on failure
8712 */
8713static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8714 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8715 const void *data, int data_len)
8716{
8717 int rem, i = 0;
8718 struct nlattr *tb[SET_CHAN_MAX + 1];
8719 struct nlattr *tb2[SET_CHAN_MAX + 1];
8720 struct nlattr *curr_attr;
8721 struct hdd_vendor_chan_info *channel_list;
8722
8723 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8724 hdd_err("Invalid ATTR");
8725 return -EINVAL;
8726 }
8727
8728 if (tb[SET_CHAN_REASON])
8729 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8730
8731 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8732 *channel_cnt = nla_get_u8(tb[
8733 SET_CHAN_CHANNEL_COUNT]);
8734 hdd_info("channel count %d", *channel_cnt);
8735 }
8736
8737 if (!(*channel_cnt)) {
8738 hdd_err("channel count is %d", *channel_cnt);
8739 return -EINVAL;
8740 }
8741
8742 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8743 (*channel_cnt));
8744
8745 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8746 if (nla_parse(tb2,
8747 SET_CHAN_MAX,
8748 nla_data(curr_attr), nla_len(curr_attr),
8749 NULL)) {
8750 hdd_err("nla_parse failed");
8751 return -EINVAL;
8752 }
8753 /* Parse and Fetch allowed SSID list*/
8754 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8755 channel_list[i].pri_ch =
8756 nla_get_u8(
8757 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8758 }
8759 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8760 channel_list[i].ht_sec_ch =
8761 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8762 }
8763 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8764 channel_list[i].vht_seg0_center_ch =
8765 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8766 }
8767 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8768 channel_list[i].vht_seg1_center_ch =
8769 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8770 }
8771 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8772 channel_list[i].chan_width =
8773 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8774 }
8775 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8776 i, channel_list[i].pri_ch,
8777 channel_list[i].ht_sec_ch,
8778 channel_list[i].vht_seg0_center_ch,
8779 channel_list[i].vht_seg1_center_ch,
8780 channel_list[i].chan_width);
8781 i++;
8782 if (i > *channel_cnt)
8783 break;
8784 }
8785 *chan_list_ptr = channel_list;
8786
8787 return 0;
8788}
8789
8790/**
8791 * Undef short names for vendor set channel configuration
8792 */
8793#undef SET_CHAN_REASON
8794#undef SET_CHAN_CHANNEL_COUNT
8795#undef SET_CHAN_CHAN_LIST
8796#undef SET_CHAN_PRIMARY_CHANNEL
8797#undef SET_CHAN_SECONDARY_CHANNEL
8798#undef SET_CHAN_SEG0_CENTER_CHANNEL
8799#undef SET_CHAN_SEG1_CENTER_CHANNEL
8800#undef SET_CHAN_CHANNEL_WIDTH
8801#undef SET_CHAN_MAX
8802
8803/**
8804 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8805 * @wiphy: Pointer to wireless phy
8806 * @wdev: Pointer to wireless device
8807 * @data: Pointer to data
8808 * @data_len: Length of @data
8809 *
8810 * Return: 0 on success, negative errno on failure
8811 */
8812static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8813 struct wireless_dev *wdev,
8814 const void *data, int data_len)
8815{
8816 int ret_val;
8817 QDF_STATUS qdf_status;
8818 uint8_t channel_cnt = 0, reason = -1;
8819 struct hdd_vendor_chan_info *channel_list = NULL;
8820 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8821 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8822
8823 ENTER();
8824
8825 ret_val = wlan_hdd_validate_context(hdd_ctx);
8826 if (ret_val)
8827 return ret_val;
8828
8829 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8830 hdd_err("Command not allowed in FTM mode");
8831 return -EINVAL;
8832 }
8833
8834 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8835 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8836 else {
8837 hdd_err("already timeout happened for acs");
8838 return -EINVAL;
8839 }
8840
8841 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8842 &channel_cnt, data, data_len);
8843 if (ret_val)
8844 return ret_val;
8845
8846 /* Validate channel to be set */
8847 while (channel_cnt && channel_list) {
8848 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8849 channel_list->pri_ch,
8850 channel_list->chan_width);
8851 if (qdf_status == QDF_STATUS_SUCCESS)
8852 break;
8853 channel_cnt--;
8854 channel_list++;
8855 }
8856 if ((channel_cnt <= 0) || !channel_list) {
8857 hdd_err("no available channel/chanlist %p", channel_list);
8858 return -EINVAL;
8859 }
8860
8861 qdf_status = hdd_update_acs_channel(adapter, reason,
8862 channel_cnt, channel_list);
8863 return qdf_status_to_os_return(qdf_status);
8864}
8865
8866/**
8867 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8868 * @wiphy: Pointer to wireless phy
8869 * @wdev: Pointer to wireless device
8870 * @data: Pointer to data
8871 * @data_len: Length of @data
8872 *
8873 * Return: 0 on success, negative errno on failure
8874 */
8875static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8876 struct wireless_dev *wdev,
8877 const void *data, int data_len)
8878{
8879 int ret;
8880
8881 cds_ssr_protect(__func__);
8882 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8883 data_len);
8884 cds_ssr_protect(__func__);
8885
8886 return ret;
8887}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308888
8889/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308890 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8891 * @wiphy: wiphy structure pointer
8892 * @wdev: Wireless device structure pointer
8893 * @data: Pointer to the data received
8894 * @data_len: Length of @data
8895 *
8896 * Return: 0 on success; errno on failure
8897 */
8898static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8899 struct wireless_dev *wdev,
8900 const void *data, int data_len)
8901{
8902 int ret;
8903
8904 cds_ssr_protect(__func__);
8905 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8906 cds_ssr_unprotect(__func__);
8907
8908 return ret;
8909}
8910
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008911/**
8912 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8913 * @nl80211_value: Vendor command attribute value
8914 * @wmi_value: Pointer to return converted WMI return value
8915 *
8916 * Convert NL80211 vendor command value for SAR limit set to WMI value
8917 * Return: 0 on success, -1 on invalid value
8918 */
8919static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8920 u32 *wmi_value)
8921{
8922 int ret = 0;
8923
8924 switch (nl80211_value) {
8925 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8926 *wmi_value = WMI_SAR_FEATURE_OFF;
8927 break;
8928 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8929 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8930 break;
8931 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8932 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8933 break;
8934 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8935 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8936 break;
8937 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8938 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8939 break;
8940 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8941 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8942 break;
8943 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8944 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8945 break;
8946 default:
8947 ret = -1;
8948 }
8949 return ret;
8950}
8951
8952/**
8953 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8954 * @nl80211_value: Vendor command attribute value
8955 * @wmi_value: Pointer to return converted WMI return value
8956 *
8957 * Convert NL80211 vendor command value for SAR BAND to WMI value
8958 * Return: 0 on success, -1 on invalid value
8959 */
8960static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8961{
8962 int ret = 0;
8963
8964 switch (nl80211_value) {
8965 case NL80211_BAND_2GHZ:
8966 *wmi_value = WMI_SAR_2G_ID;
8967 break;
8968 case NL80211_BAND_5GHZ:
8969 *wmi_value = WMI_SAR_5G_ID;
8970 break;
8971 default:
8972 ret = -1;
8973 }
8974 return ret;
8975}
8976
8977/**
8978 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8979 * @nl80211_value: Vendor command attribute value
8980 * @wmi_value: Pointer to return converted WMI return value
8981 *
8982 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8983 * Return: 0 on success, -1 on invalid value
8984 */
8985static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8986 u32 *wmi_value)
8987{
8988 int ret = 0;
8989
8990 switch (nl80211_value) {
8991 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8992 *wmi_value = WMI_SAR_MOD_CCK;
8993 break;
8994 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8995 *wmi_value = WMI_SAR_MOD_OFDM;
8996 break;
8997 default:
8998 ret = -1;
8999 }
9000 return ret;
9001}
9002
9003
9004/**
9005 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9006 * @wiphy: Pointer to wireless phy
9007 * @wdev: Pointer to wireless device
9008 * @data: Pointer to data
9009 * @data_len: Length of @data
9010 *
9011 * This function is used to setup Specific Absorption Rate limit specs.
9012 *
9013 * Return: 0 on success, negative errno on failure
9014 */
9015static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9016 struct wireless_dev *wdev,
9017 const void *data, int data_len)
9018{
9019 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9020 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9021 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9022 *sar_spec_list;
9023 struct sar_limit_cmd_params sar_limit_cmd = {0};
9024 int ret = -EINVAL, i = 0, rem = 0;
9025
9026 ENTER();
9027
9028 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9029 hdd_err("Command not allowed in FTM mode");
9030 return -EPERM;
9031 }
9032
9033 if (wlan_hdd_validate_context(hdd_ctx))
9034 return -EINVAL;
9035
9036 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9037 data, data_len, NULL)) {
9038 hdd_err("Invalid SAR attributes");
9039 return -EINVAL;
9040 }
9041
9042 /* Vendor command manadates all SAR Specs in single call */
9043 sar_limit_cmd.commit_limits = 1;
9044 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9045 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9046 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9047 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9048 &sar_limit_cmd.sar_enable) < 0) {
9049 hdd_err("Invalid SAR Enable attr");
9050 goto fail;
9051 }
9052 }
9053 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9054
9055 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9056 sar_limit_cmd.num_limit_rows = nla_get_u32(
9057 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9058 hdd_info("attr sar num_limit_rows %d",
9059 sar_limit_cmd.num_limit_rows);
9060 }
9061 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9062 hdd_err("SAR Spec list exceed supported size");
9063 goto fail;
9064 }
9065 if (sar_limit_cmd.num_limit_rows == 0)
9066 goto send_sar_limits;
9067 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9068 struct sar_limit_cmd_row) *
9069 sar_limit_cmd.num_limit_rows);
9070 if (!sar_limit_cmd.sar_limit_row_list) {
9071 ret = -ENOMEM;
9072 goto fail;
9073 }
9074 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9075 hdd_err("Invalid SAR SPECs list");
9076 goto fail;
9077 }
9078
9079 nla_for_each_nested(sar_spec_list,
9080 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9081 if (i == sar_limit_cmd.num_limit_rows) {
9082 hdd_warn("SAR Cmd has excess SPECs in list");
9083 break;
9084 }
9085
9086 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9087 nla_data(sar_spec_list), nla_len(sar_spec_list),
9088 NULL)) {
9089 hdd_err("nla_parse failed for SAR Spec list");
9090 goto fail;
9091 }
9092 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9093 if (sar_spec[
9094 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9095 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9096 nla_get_u32(sar_spec[
9097 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9098 } else {
9099 hdd_err("SAR Spec does not have power limit value");
9100 goto fail;
9101 }
9102
9103 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9104 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9105 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9106 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9107 < 0) {
9108 hdd_err("Invalid SAR Band attr");
9109 goto fail;
9110 }
9111 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9112 WMI_SAR_BAND_ID_VALID_MASK;
9113 }
9114 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9115 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9116 nla_get_u32(sar_spec[
9117 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9118 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9119 WMI_SAR_CHAIN_ID_VALID_MASK;
9120 }
9121 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9122 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9123 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9124 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9125 < 0) {
9126 hdd_err("Invalid SAR Modulation attr");
9127 goto fail;
9128 }
9129 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9130 WMI_SAR_MOD_ID_VALID_MASK;
9131 }
9132 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9133 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9134 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9135 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9136 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9137 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9138 i++;
9139 }
9140
9141 if (i < sar_limit_cmd.num_limit_rows) {
9142 hdd_warn("SAR Cmd has less SPECs in list");
9143 sar_limit_cmd.num_limit_rows = i;
9144 }
9145
9146send_sar_limits:
9147 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9148 QDF_STATUS_SUCCESS)
9149 ret = 0;
9150fail:
9151 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9152 return ret;
9153}
9154
9155/**
9156 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9157 * @wiphy: Pointer to wireless phy
9158 * @wdev: Pointer to wireless device
9159 * @data: Pointer to data
9160 * @data_len: Length of @data
9161 *
9162 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9163 *
9164 * Return: 0 on success, negative errno on failure
9165 */
9166static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9167 struct wireless_dev *wdev,
9168 const void *data,
9169 int data_len)
9170{
9171 int ret;
9172
9173 cds_ssr_protect(__func__);
9174 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9175 data_len);
9176 cds_ssr_unprotect(__func__);
9177
9178 return ret;
9179}
9180
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309181static const struct
9182nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9183 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9184 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9185 .len = QDF_MAC_ADDR_SIZE},
9186};
9187
9188/**
9189 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9190 * @wiphy: Pointer to wireless phy
9191 * @wdev: Pointer to wireless device
9192 * @data: Pointer to data
9193 * @data_len: Length of @data
9194 *
9195 * This function is used to enable/disable roaming using vendor commands
9196 *
9197 * Return: 0 on success, negative errno on failure
9198 */
9199static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9200 struct wireless_dev *wdev,
9201 const void *data, int data_len)
9202{
9203 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9204 struct net_device *dev = wdev->netdev;
9205 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9206 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9207 uint32_t is_fast_roam_enabled;
9208 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309209 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309210
9211 ENTER_DEV(dev);
9212
9213 ret = wlan_hdd_validate_context(hdd_ctx);
9214 if (0 != ret)
9215 return ret;
9216
9217 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9218 hdd_err("Command not allowed in FTM mode");
9219 return -EINVAL;
9220 }
9221
9222 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9223 qca_wlan_vendor_attr);
9224 if (ret) {
9225 hdd_err("Invalid ATTR");
9226 return -EINVAL;
9227 }
9228
9229 /* Parse and fetch Enable flag */
9230 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9231 hdd_err("attr enable failed");
9232 return -EINVAL;
9233 }
9234
9235 is_fast_roam_enabled = nla_get_u32(
9236 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009237 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9238 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309239
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009240 if (!adapter->fast_roaming_allowed) {
9241 hdd_err("fast roaming not allowed on %s interface",
9242 adapter->dev->name);
9243 return -EINVAL;
9244 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309245 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309246 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009247 (is_fast_roam_enabled &&
9248 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309249 if (qdf_status != QDF_STATUS_SUCCESS)
9250 hdd_err("sme_config_fast_roaming failed with status=%d",
9251 qdf_status);
9252 ret = qdf_status_to_os_return(qdf_status);
9253
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309254 EXIT();
9255 return ret;
9256}
9257
9258/**
9259 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9260 * @wiphy: Pointer to wireless phy
9261 * @wdev: Pointer to wireless device
9262 * @data: Pointer to data
9263 * @data_len: Length of @data
9264 *
9265 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9266 *
9267 * Return: 0 on success, negative errno on failure
9268 */
9269static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9270 struct wireless_dev *wdev,
9271 const void *data, int data_len)
9272{
9273 int ret;
9274
9275 cds_ssr_protect(__func__);
9276 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9277 cds_ssr_unprotect(__func__);
9278
9279 return ret;
9280}
9281
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309282static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9283 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9284 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9285 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9286 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9287};
9288
9289/**
9290 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9291 * @wiphy: Pointer to wireless phy
9292 * @wdev: Pointer to wireless device
9293 * @data: Pointer to data
9294 * @data_len: Length of @data
9295 *
9296 * Return: 0 on success, negative errno on failure
9297 */
9298static int
9299__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9300 struct wireless_dev *wdev,
9301 const void *data,
9302 int data_len)
9303{
9304 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9305 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9306 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9307 struct nlattr *apth;
9308 int rem;
9309 int ret = 1;
9310 int print_idx = -1;
9311 int module_id = -1;
9312 int bit_mask = -1;
9313 int status;
9314
9315 ENTER();
9316
9317 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9318 hdd_err("Command not allowed in FTM mode");
9319 return -EINVAL;
9320 }
9321
9322 ret = wlan_hdd_validate_context(hdd_ctx);
9323 if (ret != 0)
9324 return -EINVAL;
9325
9326 print_idx = qdf_get_pidx();
9327 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9328 hdd_err("Invalid print controle object index");
9329 return -EINVAL;
9330 }
9331
9332 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9333 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9334 hdd_err("Invalid attr");
9335 return -EINVAL;
9336 }
9337
9338 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9339 hdd_err("attr trace level param failed");
9340 return -EINVAL;
9341 }
9342
9343 nla_for_each_nested(apth,
9344 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9345 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9346 nla_data(apth), nla_len(apth), NULL)) {
9347 hdd_err("Invalid attr");
9348 return -EINVAL;
9349 }
9350
9351 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9352 hdd_err("attr Module ID failed");
9353 return -EINVAL;
9354 }
9355 module_id = nla_get_u32
9356 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9357
9358 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9359 hdd_err("attr Verbose mask failed");
9360 return -EINVAL;
9361 }
9362 bit_mask = nla_get_u32
9363 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9364
9365 status = hdd_qdf_trace_enable(module_id, bit_mask);
9366
9367 if (status != 0)
9368 hdd_err("can not set verbose mask %d for the category %d",
9369 bit_mask, module_id);
9370 }
9371
9372 EXIT();
9373 return ret;
9374}
9375
9376/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309377 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9378 * @wiphy: Pointer to wireless phy
9379 * @wdev: Pointer to wireless device
9380 * @data: Pointer to data
9381 * @data_len: Length of @data
9382 *
9383 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9384 *
9385 * Return: 0 on success, negative errno on failure
9386 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309387
9388static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9389 struct wireless_dev *wdev,
9390 const void *data,
9391 int data_len)
9392{
9393 int ret;
9394
9395 cds_ssr_protect(__func__);
9396 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9397 cds_ssr_unprotect(__func__);
9398
9399 return ret;
9400}
9401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009402const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9403 {
9404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309407 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009408 .doit = is_driver_dfs_capable
9409 },
9410
9411#ifdef WLAN_FEATURE_NAN
9412 {
9413 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9414 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9415 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9416 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9417 .doit = wlan_hdd_cfg80211_nan_request
9418 },
9419#endif
9420
9421#ifdef WLAN_FEATURE_STATS_EXT
9422 {
9423 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9424 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9425 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9426 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9427 .doit = wlan_hdd_cfg80211_stats_ext_request
9428 },
9429#endif
9430#ifdef FEATURE_WLAN_EXTSCAN
9431 {
9432 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9433 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9434 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9435 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9436 .doit = wlan_hdd_cfg80211_extscan_start
9437 },
9438 {
9439 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9440 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9441 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9442 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9443 .doit = wlan_hdd_cfg80211_extscan_stop
9444 },
9445 {
9446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9447 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9449 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9450 },
9451 {
9452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9455 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9456 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9457 },
9458 {
9459 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9460 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9461 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9462 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9463 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9464 },
9465 {
9466 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9467 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9468 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9469 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9470 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9471 },
9472 {
9473 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9474 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9475 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9476 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9477 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9478 },
9479 {
9480 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9481 .info.subcmd =
9482 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9483 .flags =
9484 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9485 WIPHY_VENDOR_CMD_NEED_RUNNING,
9486 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9487 },
9488 {
9489 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9490 .info.subcmd =
9491 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9492 .flags =
9493 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9494 WIPHY_VENDOR_CMD_NEED_RUNNING,
9495 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9496 },
9497 {
9498 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9499 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9500 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9501 WIPHY_VENDOR_CMD_NEED_NETDEV |
9502 WIPHY_VENDOR_CMD_NEED_RUNNING,
9503 .doit = wlan_hdd_cfg80211_set_epno_list
9504 },
9505#endif /* FEATURE_WLAN_EXTSCAN */
9506
9507#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9508 {
9509 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9510 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9511 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9512 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9513 .doit = wlan_hdd_cfg80211_ll_stats_clear
9514 },
9515
9516 {
9517 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9518 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9519 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9520 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9521 .doit = wlan_hdd_cfg80211_ll_stats_set
9522 },
9523
9524 {
9525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9526 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9527 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9528 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9529 .doit = wlan_hdd_cfg80211_ll_stats_get
9530 },
9531#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9532#ifdef FEATURE_WLAN_TDLS
9533 {
9534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9537 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9538 .doit = wlan_hdd_cfg80211_exttdls_enable
9539 },
9540 {
9541 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9542 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9543 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9544 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9545 .doit = wlan_hdd_cfg80211_exttdls_disable
9546 },
9547 {
9548 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9549 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9550 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9551 .doit = wlan_hdd_cfg80211_exttdls_get_status
9552 },
9553#endif
9554 {
9555 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9556 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9558 .doit = wlan_hdd_cfg80211_get_supported_features
9559 },
9560 {
9561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9564 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9565 },
9566 {
9567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9568 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9569 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309570 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009571 },
9572 {
9573 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9574 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9575 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9576 WIPHY_VENDOR_CMD_NEED_NETDEV,
9577 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9578 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009579 {
9580 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9581 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9582 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9583 WIPHY_VENDOR_CMD_NEED_NETDEV,
9584 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9585 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009586 {
9587 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309588 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9589 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9590 WIPHY_VENDOR_CMD_NEED_NETDEV |
9591 WIPHY_VENDOR_CMD_NEED_RUNNING,
9592 .doit = hdd_cfg80211_get_station_cmd
9593 },
9594 {
9595 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009596 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9597 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9598 WIPHY_VENDOR_CMD_NEED_NETDEV |
9599 WIPHY_VENDOR_CMD_NEED_RUNNING,
9600 .doit = wlan_hdd_cfg80211_do_acs
9601 },
9602
9603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9607 WIPHY_VENDOR_CMD_NEED_NETDEV,
9608 .doit = wlan_hdd_cfg80211_get_features
9609 },
9610#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9611 {
9612 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9613 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9614 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9615 WIPHY_VENDOR_CMD_NEED_NETDEV |
9616 WIPHY_VENDOR_CMD_NEED_RUNNING,
9617 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9618 },
9619#endif
9620#ifdef FEATURE_WLAN_EXTSCAN
9621 {
9622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9625 WIPHY_VENDOR_CMD_NEED_NETDEV |
9626 WIPHY_VENDOR_CMD_NEED_RUNNING,
9627 .doit = wlan_hdd_cfg80211_set_passpoint_list
9628 },
9629 {
9630 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9631 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9632 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9633 WIPHY_VENDOR_CMD_NEED_NETDEV |
9634 WIPHY_VENDOR_CMD_NEED_RUNNING,
9635 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9636 },
9637 {
9638 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9639 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9640 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9641 WIPHY_VENDOR_CMD_NEED_NETDEV |
9642 WIPHY_VENDOR_CMD_NEED_RUNNING,
9643 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9644 },
9645 {
9646 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9647 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9648 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9649 WIPHY_VENDOR_CMD_NEED_NETDEV |
9650 WIPHY_VENDOR_CMD_NEED_RUNNING,
9651 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9652 },
9653#endif /* FEATURE_WLAN_EXTSCAN */
9654 {
9655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9656 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9657 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9658 WIPHY_VENDOR_CMD_NEED_NETDEV,
9659 .doit = wlan_hdd_cfg80211_get_wifi_info
9660 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009661#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009662 {
9663 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9664 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9665 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9666 WIPHY_VENDOR_CMD_NEED_NETDEV |
9667 WIPHY_VENDOR_CMD_NEED_RUNNING,
9668 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9669 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009670#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009671 {
9672 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9673 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9674 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9675 WIPHY_VENDOR_CMD_NEED_NETDEV,
9676 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9677 },
9678 {
9679 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9680 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9681 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9682 WIPHY_VENDOR_CMD_NEED_NETDEV,
9683 .doit = wlan_hdd_cfg80211_wifi_logger_start
9684 },
9685 {
9686 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9687 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9688 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9689 WIPHY_VENDOR_CMD_NEED_NETDEV,
9690 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9691 },
9692 {
9693 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9694 .info.subcmd =
9695 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9696 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9697 WIPHY_VENDOR_CMD_NEED_NETDEV |
9698 WIPHY_VENDOR_CMD_NEED_RUNNING,
9699 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9700 },
9701 {
9702 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9703 .info.subcmd =
9704 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9705 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9706 WIPHY_VENDOR_CMD_NEED_NETDEV |
9707 WIPHY_VENDOR_CMD_NEED_RUNNING,
9708 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9709 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009710#ifdef WLAN_FEATURE_TSF
9711 {
9712 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9713 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9714 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9715 WIPHY_VENDOR_CMD_NEED_NETDEV |
9716 WIPHY_VENDOR_CMD_NEED_RUNNING,
9717 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9718 },
9719#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009720#ifdef FEATURE_WLAN_TDLS
9721 {
9722 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9723 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9724 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9725 WIPHY_VENDOR_CMD_NEED_NETDEV |
9726 WIPHY_VENDOR_CMD_NEED_RUNNING,
9727 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9728 },
9729#endif
9730#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9731 {
9732 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9733 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9734 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9735 WIPHY_VENDOR_CMD_NEED_NETDEV |
9736 WIPHY_VENDOR_CMD_NEED_RUNNING,
9737 .doit = wlan_hdd_cfg80211_offloaded_packets
9738 },
9739#endif
9740 {
9741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9742 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9743 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9744 WIPHY_VENDOR_CMD_NEED_NETDEV |
9745 WIPHY_VENDOR_CMD_NEED_RUNNING,
9746 .doit = wlan_hdd_cfg80211_monitor_rssi
9747 },
9748 {
9749 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309750 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9751 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9752 WIPHY_VENDOR_CMD_NEED_NETDEV |
9753 WIPHY_VENDOR_CMD_NEED_RUNNING,
9754 .doit = wlan_hdd_cfg80211_set_ns_offload
9755 },
9756 {
9757 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9759 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9760 WIPHY_VENDOR_CMD_NEED_NETDEV |
9761 WIPHY_VENDOR_CMD_NEED_RUNNING,
9762 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9763 },
9764#ifdef WLAN_FEATURE_MEMDUMP
9765 {
9766 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9767 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9769 WIPHY_VENDOR_CMD_NEED_NETDEV |
9770 WIPHY_VENDOR_CMD_NEED_RUNNING,
9771 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9772 },
9773#endif /* WLAN_FEATURE_MEMDUMP */
9774 {
9775 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9776 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9777 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9778 WIPHY_VENDOR_CMD_NEED_NETDEV |
9779 WIPHY_VENDOR_CMD_NEED_RUNNING,
9780 .doit = wlan_hdd_cfg80211_vendor_scan
9781 },
9782
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309783 /* Vendor abort scan */
9784 {
9785 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9786 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9787 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9788 WIPHY_VENDOR_CMD_NEED_NETDEV |
9789 WIPHY_VENDOR_CMD_NEED_RUNNING,
9790 .doit = wlan_hdd_vendor_abort_scan
9791 },
9792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009793 /* OCB commands */
9794 {
9795 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9796 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9797 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9798 WIPHY_VENDOR_CMD_NEED_NETDEV |
9799 WIPHY_VENDOR_CMD_NEED_RUNNING,
9800 .doit = wlan_hdd_cfg80211_ocb_set_config
9801 },
9802 {
9803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9804 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9805 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9806 WIPHY_VENDOR_CMD_NEED_NETDEV |
9807 WIPHY_VENDOR_CMD_NEED_RUNNING,
9808 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9809 },
9810 {
9811 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9812 .info.subcmd =
9813 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9815 WIPHY_VENDOR_CMD_NEED_NETDEV |
9816 WIPHY_VENDOR_CMD_NEED_RUNNING,
9817 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9818 },
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9821 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9822 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9823 WIPHY_VENDOR_CMD_NEED_NETDEV |
9824 WIPHY_VENDOR_CMD_NEED_RUNNING,
9825 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9826 },
9827 {
9828 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9829 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9830 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9831 WIPHY_VENDOR_CMD_NEED_NETDEV |
9832 WIPHY_VENDOR_CMD_NEED_RUNNING,
9833 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9834 },
9835 {
9836 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9837 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9838 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9839 WIPHY_VENDOR_CMD_NEED_NETDEV |
9840 WIPHY_VENDOR_CMD_NEED_RUNNING,
9841 .doit = wlan_hdd_cfg80211_dcc_get_stats
9842 },
9843 {
9844 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9845 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9846 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9847 WIPHY_VENDOR_CMD_NEED_NETDEV |
9848 WIPHY_VENDOR_CMD_NEED_RUNNING,
9849 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9850 },
9851 {
9852 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9853 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9854 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9855 WIPHY_VENDOR_CMD_NEED_NETDEV |
9856 WIPHY_VENDOR_CMD_NEED_RUNNING,
9857 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9858 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309859 {
9860 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9861 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9862 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9863 WIPHY_VENDOR_CMD_NEED_NETDEV |
9864 WIPHY_VENDOR_CMD_NEED_RUNNING,
9865 .doit = wlan_hdd_cfg80211_get_link_properties
9866 },
Peng Xu278d0122015-09-24 16:34:17 -07009867 {
Peng Xud2220962016-07-11 17:59:17 -07009868 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009869 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9870 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9871 WIPHY_VENDOR_CMD_NEED_NETDEV |
9872 WIPHY_VENDOR_CMD_NEED_RUNNING,
9873 .doit = wlan_hdd_cfg80211_set_ota_test
9874 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009875#ifdef FEATURE_LFR_SUBNET_DETECTION
9876 {
9877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9880 WIPHY_VENDOR_CMD_NEED_NETDEV |
9881 WIPHY_VENDOR_CMD_NEED_RUNNING,
9882 .doit = wlan_hdd_cfg80211_set_gateway_params
9883 },
9884#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009885 {
Peng Xud2220962016-07-11 17:59:17 -07009886 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009887 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9888 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9889 WIPHY_VENDOR_CMD_NEED_NETDEV |
9890 WIPHY_VENDOR_CMD_NEED_RUNNING,
9891 .doit = wlan_hdd_cfg80211_txpower_scale
9892 },
9893 {
9894 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9895 .info.subcmd =
9896 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9898 WIPHY_VENDOR_CMD_NEED_NETDEV |
9899 WIPHY_VENDOR_CMD_NEED_RUNNING,
9900 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9901 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309902 {
9903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9904 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9905 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9906 WIPHY_VENDOR_CMD_NEED_NETDEV |
9907 WIPHY_VENDOR_CMD_NEED_RUNNING,
9908 .doit = wlan_hdd_cfg80211_bpf_offload
9909 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309910 {
9911 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309912 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9913 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9914 WIPHY_VENDOR_CMD_NEED_NETDEV |
9915 WIPHY_VENDOR_CMD_NEED_RUNNING,
9916 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9917 },
9918 {
9919 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309920 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9921 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9922 WIPHY_VENDOR_CMD_NEED_NETDEV |
9923 WIPHY_VENDOR_CMD_NEED_RUNNING,
9924 .doit = wlan_hdd_cfg80211_sta_roam_policy
9925 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309926#ifdef FEATURE_WLAN_CH_AVOID
9927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9929 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9931 WIPHY_VENDOR_CMD_NEED_NETDEV |
9932 WIPHY_VENDOR_CMD_NEED_RUNNING,
9933 .doit = wlan_hdd_cfg80211_avoid_freq
9934 },
9935#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309936 {
9937 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309938 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9939 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9940 WIPHY_VENDOR_CMD_NEED_NETDEV |
9941 WIPHY_VENDOR_CMD_NEED_RUNNING,
9942 .doit = wlan_hdd_cfg80211_sap_configuration_set
9943 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009944 {
Peng Xu4225c152016-07-14 21:18:14 -07009945 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009946 .info.subcmd =
9947 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9948 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9949 WIPHY_VENDOR_CMD_NEED_NETDEV |
9950 WIPHY_VENDOR_CMD_NEED_RUNNING,
9951 .doit = wlan_hdd_cfg80211_p2p_lo_start
9952 },
9953 {
9954 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9955 .info.subcmd =
9956 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9958 WIPHY_VENDOR_CMD_NEED_NETDEV |
9959 WIPHY_VENDOR_CMD_NEED_RUNNING,
9960 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9961 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309962 {
9963 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9964 .info.subcmd =
9965 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9966 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9967 WIPHY_VENDOR_CMD_NEED_NETDEV |
9968 WIPHY_VENDOR_CMD_NEED_RUNNING,
9969 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9970 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009971#ifdef WLAN_FEATURE_NAN_DATAPATH
9972 {
9973 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9974 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9975 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9976 WIPHY_VENDOR_CMD_NEED_NETDEV |
9977 WIPHY_VENDOR_CMD_NEED_RUNNING,
9978 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9979 },
9980#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309981 {
9982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9985 WIPHY_VENDOR_CMD_NEED_NETDEV |
9986 WIPHY_VENDOR_CMD_NEED_RUNNING,
9987 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9988 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309989 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9991 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9992 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9993 WIPHY_VENDOR_CMD_NEED_NETDEV |
9994 WIPHY_VENDOR_CMD_NEED_RUNNING,
9995 .doit = wlan_hdd_cfg80211_get_bus_size
9996 },
9997 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309998 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9999 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10000 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10001 WIPHY_VENDOR_CMD_NEED_NETDEV |
10002 WIPHY_VENDOR_CMD_NEED_RUNNING,
10003 .doit = wlan_hdd_cfg80211_update_vendor_channel
10004 },
10005 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010006 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10007 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10008 WIPHY_VENDOR_CMD_NEED_NETDEV |
10009 WIPHY_VENDOR_CMD_NEED_RUNNING,
10010 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010011 },
10012 {
10013 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10014 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10015 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10016 WIPHY_VENDOR_CMD_NEED_NETDEV |
10017 WIPHY_VENDOR_CMD_NEED_RUNNING,
10018 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010019 },
10020#ifdef WLAN_FEATURE_DISA
10021 {
10022 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10023 .info.subcmd =
10024 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10025 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10026 WIPHY_VENDOR_CMD_NEED_NETDEV |
10027 WIPHY_VENDOR_CMD_NEED_RUNNING,
10028 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10029 },
10030#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010031#ifdef FEATURE_WLAN_TDLS
10032 {
10033 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10034 .info.subcmd =
10035 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10036 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10037 WIPHY_VENDOR_CMD_NEED_NETDEV |
10038 WIPHY_VENDOR_CMD_NEED_RUNNING,
10039 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010040 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010041#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010042 {
10043 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10044 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10045 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10046 WIPHY_VENDOR_CMD_NEED_RUNNING,
10047 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10048 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010049 {
10050 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10051 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10052 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10053 WIPHY_VENDOR_CMD_NEED_NETDEV |
10054 WIPHY_VENDOR_CMD_NEED_RUNNING,
10055 .doit = wlan_hdd_cfg80211_set_trace_level
10056 },
10057
Paul Zhang3a210c52016-12-08 10:18:12 +080010058#ifdef WLAN_UMAC_CONVERGENCE
10059 COMMON_VENDOR_COMMANDS
10060#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061};
10062
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010063#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10064 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10065 defined(FEATURE_WLAN_SCAN_PNO)
10066/**
10067 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10068 * @wiphy: pointer to wiphy
10069 * @config: pointer to config
10070 *
10071 * Return: None
10072 */
10073static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10074 struct hdd_config *config)
10075{
10076 if (config->configPNOScanSupport) {
10077 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10078 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10079 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10080 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10081 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10082 if (config->max_sched_scan_plan_interval)
10083 wiphy->max_sched_scan_plan_interval =
10084 config->max_sched_scan_plan_interval;
10085 if (config->max_sched_scan_plan_iterations)
10086 wiphy->max_sched_scan_plan_iterations =
10087 config->max_sched_scan_plan_iterations;
10088 }
10089}
10090#else
10091static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10092 struct hdd_config *config)
10093{
10094}
10095#endif
10096
10097
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010098/**
10099 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10100 * @priv_size: Size of the hdd context.
10101 *
10102 * Allocate wiphy context and hdd context.
10103 *
10104 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010105 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010106hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010107{
10108 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010109 hdd_context_t *hdd_ctx;
10110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010111 ENTER();
10112
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010113 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10114
10115 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010116 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 return NULL;
10118 }
10119
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010120 hdd_ctx = wiphy_priv(wiphy);
10121
10122 hdd_ctx->wiphy = wiphy;
10123
10124 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010125}
10126
10127/*
10128 * FUNCTION: wlan_hdd_cfg80211_update_band
10129 * This function is called from the supplicant through a
10130 * private ioctl to change the band value
10131 */
10132int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10133{
10134 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010135 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136
10137 ENTER();
10138
Dustin Browna30892e2016-10-12 17:28:36 -070010139 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010141 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010142 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010143
10144 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10145 struct ieee80211_supported_band *band = wiphy->bands[i];
10146
10147 channelEnabledState =
10148 cds_get_channel_state(band->channels[j].
10149 hw_value);
10150
Dustin Browna30892e2016-10-12 17:28:36 -070010151 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010152 /* 5G only */
10153#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10154 /* Enable Social channels for P2P */
10155 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10156 (band->channels[j].center_freq)
10157 && CHANNEL_STATE_ENABLE ==
10158 channelEnabledState)
10159 band->channels[j].flags &=
10160 ~IEEE80211_CHAN_DISABLED;
10161 else
10162#endif
10163 band->channels[j].flags |=
10164 IEEE80211_CHAN_DISABLED;
10165 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010166 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167 eCSR_BAND_24 == eBand) {
10168 /* 2G only */
10169 band->channels[j].flags |=
10170 IEEE80211_CHAN_DISABLED;
10171 continue;
10172 }
10173
Amar Singhal6842e8f2016-02-23 16:30:32 -080010174 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010175 band->channels[j].flags &=
10176 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010177 }
10178 }
10179 return 0;
10180}
10181
Peng Xuacfdda12017-02-06 16:15:38 -080010182#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183/*
10184 * FUNCTION: wlan_hdd_cfg80211_init
10185 * This function is called by hdd_wlan_startup()
10186 * during initialization.
10187 * This function is used to initialize and register wiphy structure.
10188 */
10189int wlan_hdd_cfg80211_init(struct device *dev,
10190 struct wiphy *wiphy, struct hdd_config *pCfg)
10191{
10192 int i, j;
10193 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10194
10195 ENTER();
10196
10197 /* Now bind the underlying wlan device with wiphy */
10198 set_wiphy_dev(wiphy, dev);
10199
10200 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010202#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10203 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010204 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010205#else
10206 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010207 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010208#endif
10209
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010210 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10211 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10212 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10213#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10214 | WIPHY_FLAG_4ADDR_STATION
10215#endif
10216 | WIPHY_FLAG_OFFCHAN_TX;
10217
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010218#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10219 wiphy->wowlan = &wowlan_support_cfg80211_init;
10220#else
10221 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10222 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10223 wiphy->wowlan.pattern_min_len = 1;
10224 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10225#endif
10226
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010227 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010228#ifdef FEATURE_WLAN_ESE
10229 || pCfg->isEseIniFeatureEnabled
10230#endif
10231 ) {
10232 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10233 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010234#ifdef FEATURE_WLAN_TDLS
10235 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10236 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10237#endif
10238
10239 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10240
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010241#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10242 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10243#endif
10244
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010245 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010246
10247#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010248 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010249#endif
10250
10251 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010252 * driver can still register regulatory callback and
10253 * it will get regulatory settings in wiphy->band[], but
10254 * driver need to determine what to do with both
10255 * regulatory settings
10256 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257
10258 wiphy->reg_notifier = hdd_reg_notifier;
10259
10260#if defined QCA_WIFI_FTM
10261}
10262#endif
10263
10264 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10265
10266 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10267
10268 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10269
Arun Khandavallifae92942016-08-01 13:31:08 +053010270 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10271 | BIT(NL80211_IFTYPE_ADHOC)
10272 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10273 | BIT(NL80211_IFTYPE_P2P_GO)
10274 | BIT(NL80211_IFTYPE_AP)
10275 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276
Arun Khandavallifae92942016-08-01 13:31:08 +053010277 if (pCfg->advertiseConcurrentOperation) {
10278 if (pCfg->enableMCC) {
10279 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010280
Arun Khandavallifae92942016-08-01 13:31:08 +053010281 for (i = 0;
10282 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10283 i++) {
10284 if (!pCfg->allowMCCGODiffBI)
10285 wlan_hdd_iface_combination[i].
10286 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010287 }
10288 }
10289 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010290 ARRAY_SIZE(wlan_hdd_iface_combination);
10291 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010292 }
10293
10294 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010295 * on ini values
10296 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010297 if (!pCfg->ShortGI20MhzEnable) {
10298 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10299 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010300 }
10301
10302 if (!pCfg->ShortGI40MhzEnable) {
10303 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10304 }
10305
10306 if (!pCfg->nChannelBondingMode5GHz) {
10307 wlan_hdd_band_5_ghz.ht_cap.cap &=
10308 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10309 }
10310
Abhishek Singhf512bf32016-05-04 16:47:46 +053010311 /*
10312 * In case of static linked driver at the time of driver unload,
10313 * module exit doesn't happens. Module cleanup helps in cleaning
10314 * of static memory.
10315 * If driver load happens statically, at the time of driver unload,
10316 * wiphy flags don't get reset because of static memory.
10317 * It's better not to store channel in static memory.
10318 */
Dustin Browna30892e2016-10-12 17:28:36 -070010319 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10320 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010321 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010322 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010323 hdd_err("Not enough memory to allocate channels");
10324 return -ENOMEM;
10325 }
Dustin Browna30892e2016-10-12 17:28:36 -070010326 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010327 &hdd_channels_2_4_ghz[0],
10328 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010329 if ((hdd_is_5g_supported(pHddCtx)) &&
10330 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10331 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10332 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10333 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010334 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10335 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010336 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010337 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010338 hdd_err("Not enough memory to allocate channels");
10339 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010340 bands[NL80211_BAND_2GHZ]->channels);
10341 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010342 return -ENOMEM;
10343 }
Dustin Browna30892e2016-10-12 17:28:36 -070010344 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010345 &hdd_channels_5_ghz[0],
10346 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010347 }
10348
Dustin Browna30892e2016-10-12 17:28:36 -070010349 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010350
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010351 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010352 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010353
10354 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10355 struct ieee80211_supported_band *band = wiphy->bands[i];
10356
Dustin Browna30892e2016-10-12 17:28:36 -070010357 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010358 eCSR_BAND_5G == pCfg->nBandCapability) {
10359 /* 5G only */
10360#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10361 /* Enable social channels for P2P */
10362 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10363 (band->channels[j].center_freq))
10364 band->channels[j].flags &=
10365 ~IEEE80211_CHAN_DISABLED;
10366 else
10367#endif
10368 band->channels[j].flags |=
10369 IEEE80211_CHAN_DISABLED;
10370 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010371 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 eCSR_BAND_24 == pCfg->nBandCapability) {
10373 /* 2G only */
10374 band->channels[j].flags |=
10375 IEEE80211_CHAN_DISABLED;
10376 continue;
10377 }
10378 }
10379 }
10380 /*Initialise the supported cipher suite details */
10381 wiphy->cipher_suites = hdd_cipher_suites;
10382 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10383
10384 /*signal strength in mBm (100*dBm) */
10385 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10386 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10387
Anurag Chouhan6d760662016-02-20 16:05:43 +053010388 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010389 wiphy->n_vendor_commands =
10390 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10391 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10392
10393 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10394 wiphy->n_vendor_events =
10395 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10396 }
10397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010398 if (pCfg->enableDFSMasterCap) {
10399 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10400 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010401
10402 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10403
10404#ifdef QCA_HT_2040_COEX
10405 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10406#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010407 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010408
10409#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10410 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10411 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10412 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10413 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10414#endif
10415
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010416 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010417 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010418
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010419 EXIT();
10420 return 0;
10421}
10422
Abhishek Singhf512bf32016-05-04 16:47:46 +053010423/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010424 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10425 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010426 *
10427 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010428 * memory allocated in wlan_hdd_cfg80211_init also
10429 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010430 *
10431 * Return: void
10432 */
10433void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10434{
10435 int i;
10436
Dustin Browna30892e2016-10-12 17:28:36 -070010437 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010438 if (NULL != wiphy->bands[i] &&
10439 (NULL != wiphy->bands[i]->channels)) {
10440 qdf_mem_free(wiphy->bands[i]->channels);
10441 wiphy->bands[i]->channels = NULL;
10442 }
10443 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010444 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010445}
10446
Yingying Tang80e15f32016-09-27 18:23:01 +080010447/**
10448 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10449 * @hdd_ctx: HDD context
10450 *
10451 * this function will update capabilities for supported bands
10452 *
10453 * Return: void
10454 */
10455static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10456{
10457 uint32_t val32;
10458 uint16_t val16;
10459 tSirMacHTCapabilityInfo *ht_cap_info;
10460 QDF_STATUS status;
10461
10462 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10463 if (QDF_STATUS_SUCCESS != status) {
10464 hdd_err("could not get HT capability info");
10465 val32 = 0;
10466 }
10467 val16 = (uint16_t)val32;
10468 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10469
10470 if (ht_cap_info->txSTBC == true) {
10471 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10472 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10473 IEEE80211_HT_CAP_TX_STBC;
10474 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10475 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10476 IEEE80211_HT_CAP_TX_STBC;
10477 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010478
10479 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10480 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10481 vht_cap.vht_supported = 0;
10482 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10483 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10484 vht_cap.vht_supported = 0;
10485 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10486 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010487}
10488
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010489/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010490 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010491 * initialization. In wlan_hdd_cfg80211_init, only the
10492 * default values will be initialized. The final initialization
10493 * of all required members can be done here.
10494 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010495void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010496{
Yingying Tang80e15f32016-09-27 18:23:01 +080010497 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10498
10499 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010500}
10501
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010502/**
10503 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10504 * @cfg: hdd cfg
10505 *
10506 * this function update 11n mode in hdd cfg
10507 *
10508 * Return: void
10509 */
10510void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10511{
10512 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10513 hdd_notice("support 11ac");
10514 } else {
10515 hdd_notice("not support 11ac");
10516 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10517 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10518 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10519 cfg->sap_p2p_11ac_override = 0;
10520 }
10521 }
10522}
10523
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010524/* In this function we are registering wiphy. */
10525int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10526{
10527 ENTER();
10528 /* Register our wiphy dev with cfg80211 */
10529 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010530 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010531 return -EIO;
10532 }
10533
10534 EXIT();
10535 return 0;
10536}
10537
10538/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010539 * HDD function to update wiphy capability based on target offload status.
10540 *
10541 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10542 * capability even before downloading firmware to the target. In discrete
10543 * case, host will get know certain offload capability (say sched_scan
10544 * caps) only after downloading firmware to the target and target boots up.
10545 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10546 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010547 */
10548void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10549{
10550#ifdef FEATURE_WLAN_SCAN_PNO
10551 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10552 struct hdd_config *pCfg = pHddCtx->config;
10553
10554 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10555 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010556 * have PNO support.
10557 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010558 if (!pCfg->PnoOffload) {
10559 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10560 wiphy->max_sched_scan_ssids = 0;
10561 wiphy->max_match_sets = 0;
10562 wiphy->max_sched_scan_ie_len = 0;
10563 }
10564#endif
10565}
10566
10567/* This function registers for all frame which supplicant is interested in */
10568void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10569{
10570 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10571 /* Register for all P2P action, public action etc frames */
10572 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10573
10574 ENTER();
10575
Abhishek Singh7996eb72015-12-30 17:24:02 +053010576 /* Register frame indication call back */
10577 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10578
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010579 /* Register for p2p ack indication */
10580 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010582 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010583 * initialized. Once we will move to 2.6.37 kernel, in which we have
10584 * frame register ops, we will move this code as a part of that
10585 */
10586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010587 /* GAS Initial Request */
10588 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10589 (uint8_t *) GAS_INITIAL_REQ,
10590 GAS_INITIAL_REQ_SIZE);
10591
10592 /* GAS Initial Response */
10593 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10594 (uint8_t *) GAS_INITIAL_RSP,
10595 GAS_INITIAL_RSP_SIZE);
10596
10597 /* GAS Comeback Request */
10598 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10599 (uint8_t *) GAS_COMEBACK_REQ,
10600 GAS_COMEBACK_REQ_SIZE);
10601
10602 /* GAS Comeback Response */
10603 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10604 (uint8_t *) GAS_COMEBACK_RSP,
10605 GAS_COMEBACK_RSP_SIZE);
10606
10607 /* P2P Public Action */
10608 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10609 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10610 P2P_PUBLIC_ACTION_FRAME_SIZE);
10611
10612 /* P2P Action */
10613 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10614 (uint8_t *) P2P_ACTION_FRAME,
10615 P2P_ACTION_FRAME_SIZE);
10616
10617 /* WNM BSS Transition Request frame */
10618 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10619 (uint8_t *) WNM_BSS_ACTION_FRAME,
10620 WNM_BSS_ACTION_FRAME_SIZE);
10621
10622 /* WNM-Notification */
10623 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10624 (uint8_t *) WNM_NOTIFICATION_FRAME,
10625 WNM_NOTIFICATION_FRAME_SIZE);
10626}
10627
10628void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10629{
10630 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10631 /* Register for all P2P action, public action etc frames */
10632 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10633
10634 ENTER();
10635
10636 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010637 * initialized. Once we will move to 2.6.37 kernel, in which we have
10638 * frame register ops, we will move this code as a part of that
10639 */
10640
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010641 /* GAS Initial Request */
10642
10643 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10644 (uint8_t *) GAS_INITIAL_REQ,
10645 GAS_INITIAL_REQ_SIZE);
10646
10647 /* GAS Initial Response */
10648 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10649 (uint8_t *) GAS_INITIAL_RSP,
10650 GAS_INITIAL_RSP_SIZE);
10651
10652 /* GAS Comeback Request */
10653 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10654 (uint8_t *) GAS_COMEBACK_REQ,
10655 GAS_COMEBACK_REQ_SIZE);
10656
10657 /* GAS Comeback Response */
10658 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10659 (uint8_t *) GAS_COMEBACK_RSP,
10660 GAS_COMEBACK_RSP_SIZE);
10661
10662 /* P2P Public Action */
10663 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10664 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10665 P2P_PUBLIC_ACTION_FRAME_SIZE);
10666
10667 /* P2P Action */
10668 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10669 (uint8_t *) P2P_ACTION_FRAME,
10670 P2P_ACTION_FRAME_SIZE);
10671
10672 /* WNM-Notification */
10673 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10674 (uint8_t *) WNM_NOTIFICATION_FRAME,
10675 WNM_NOTIFICATION_FRAME_SIZE);
10676}
10677
10678#ifdef FEATURE_WLAN_WAPI
10679void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10680 const uint8_t *mac_addr, const uint8_t *key,
10681 int key_Len)
10682{
10683 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10684 tCsrRoamSetKey setKey;
10685 bool isConnected = true;
10686 int status = 0;
10687 uint32_t roamId = 0xFF;
10688 uint8_t *pKeyPtr = NULL;
10689 int n = 0;
10690
Jeff Johnson46b40792016-06-29 14:03:14 -070010691 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010692 hdd_device_mode_to_string(pAdapter->device_mode),
10693 pAdapter->device_mode);
10694
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010695 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010696 setKey.keyId = key_index; /* Store Key ID */
10697 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10698 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10699 setKey.paeRole = 0; /* the PAE role */
10700 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010701 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010702 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010703 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 }
10705 setKey.keyLength = key_Len;
10706 pKeyPtr = setKey.Key;
10707 memcpy(pKeyPtr, key, key_Len);
10708
Jeff Johnson46b40792016-06-29 14:03:14 -070010709 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010710 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010711 hdd_notice("WAPI KEY Data[%d]:%02x ",
10712 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010713
10714 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10715 if (isConnected) {
10716 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10717 pAdapter->sessionId, &setKey, &roamId);
10718 }
10719 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010720 hdd_err("sme_roam_set_key returned ERROR status= %d",
10721 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010722 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10723 }
10724}
10725#endif /* FEATURE_WLAN_WAPI */
10726
10727uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10728 uint8_t eid)
10729{
10730 int left = length;
10731 uint8_t *ptr = (uint8_t *)ies_ptr;
10732 uint8_t elem_id, elem_len;
10733
10734 while (left >= 2) {
10735 elem_id = ptr[0];
10736 elem_len = ptr[1];
10737 left -= 2;
10738 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010739 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010740 eid, elem_len, left);
10741 return NULL;
10742 }
10743 if (elem_id == eid) {
10744 return ptr;
10745 }
10746
10747 left -= elem_len;
10748 ptr += (elem_len + 2);
10749 }
10750 return NULL;
10751}
10752
10753/*
10754 * FUNCTION: wlan_hdd_validate_operation_channel
10755 * called by wlan_hdd_cfg80211_start_bss() and
10756 * wlan_hdd_set_channel()
10757 * This function validates whether given channel is part of valid
10758 * channel list.
10759 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010760QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010761 int channel)
10762{
10763
10764 uint32_t num_ch = 0;
10765 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10766 u32 indx = 0;
10767 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10768 uint8_t fValidChannel = false, count = 0;
10769 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10770
10771 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10772
10773 if (hdd_pConfig_ini->sapAllowAllChannel) {
10774 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010775 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010776 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 fValidChannel = true;
10778 break;
10779 }
10780 }
10781 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010782 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010783 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010784 }
10785 } else {
10786 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10787 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010788 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010789 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010790 }
10791 for (indx = 0; indx < num_ch; indx++) {
10792 if (channel == valid_ch[indx]) {
10793 break;
10794 }
10795 }
10796
10797 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010798 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010799 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010800 }
10801 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010802 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010803
10804}
10805
10806#ifdef DHCP_SERVER_OFFLOAD
10807static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10808{
10809 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10810 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10811 uint8_t numEntries = 0;
10812 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10813 uint8_t num;
10814 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010815 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010817 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818 return;
10819 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010820 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10821 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10822 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10823 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10824 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10825 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010826 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827 goto end;
10828 }
10829 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010830 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 goto end;
10832 }
10833 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010834 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010835 goto end;
10836 }
10837 for (num = 0; num < numEntries; num++) {
10838 temp = srv_ip[num];
10839 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10840 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010841 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010843 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010844 goto end;
10845 }
Jeff Johnson77848112016-06-29 14:52:06 -070010846 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010848 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 return;
10850}
10851#endif /* DHCP_SERVER_OFFLOAD */
10852
10853static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10854 struct net_device *dev,
10855 struct bss_parameters *params)
10856{
10857 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10858 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10859 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010860 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861
10862 ENTER();
10863
Anurag Chouhan6d760662016-02-20 16:05:43 +053010864 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010865 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 return -EINVAL;
10867 }
10868
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010869 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10870 hdd_err("invalid session id: %d", pAdapter->sessionId);
10871 return -EINVAL;
10872 }
10873
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010874 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010875 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10876 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010877 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010878 hdd_device_mode_to_string(pAdapter->device_mode),
10879 pAdapter->device_mode, params->ap_isolate);
10880
10881 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10882 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010883 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010885
Krunal Sonib4326f22016-03-10 13:05:51 -080010886 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10887 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010888 return -EOPNOTSUPP;
10889 }
10890
10891 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010892 * want to update this parameter
10893 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 if (-1 != params->ap_isolate) {
10895 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10896 !!params->ap_isolate;
10897
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010898 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899 pAdapter->sessionId,
10900 pAdapter->sessionCtx.
10901 ap.
10902 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010903 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010904 ret = -EINVAL;
10905 }
10906 }
10907
10908 EXIT();
10909 return ret;
10910}
10911
Krunal Soni8c37e322016-02-03 16:08:37 -080010912/**
10913 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10914 * @ndev: pointer to net device provided by supplicant
10915 * @type: type of the interface, upper layer wanted to change
10916 *
10917 * Upper layer provides the new interface mode that needs to be changed
10918 * for given net device
10919 *
10920 * Return: success or failure in terms of integer value
10921 */
10922static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923 enum nl80211_iftype type)
10924{
Krunal Soni8c37e322016-02-03 16:08:37 -080010925 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10926 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10927 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010928 hdd_wext_state_t *wext;
10929 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010930 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931
10932 ENTER();
10933
Krunal Soni8c37e322016-02-03 16:08:37 -080010934 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010935 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010936 return 0;
10937 }
10938
10939 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010940 hdd_stop_adapter(hdd_ctx, adapter, true);
10941 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010942 wdev->iftype = type;
10943 /*Check for sub-string p2p to confirm its a p2p interface */
10944 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010945 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010946 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010947 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010948 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010949 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010951 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010952 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010953 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010954 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010955 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10956 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010957 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10958 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010959 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010960 adapter->scan_info.scanAddIE.length;
10961 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010962 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010963 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10964 wext->roamProfile.phyMode =
10965 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10966 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 EXIT();
10968 return status;
10969}
10970
10971static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10972 struct net_device *dev,
10973 struct bss_parameters *params)
10974{
10975 int ret;
10976
10977 cds_ssr_protect(__func__);
10978 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10979 cds_ssr_unprotect(__func__);
10980
10981 return ret;
10982}
10983
10984/* FUNCTION: wlan_hdd_change_country_code_cd
10985 * to wait for contry code completion
10986 */
10987void *wlan_hdd_change_country_code_cb(void *pAdapter)
10988{
10989 hdd_adapter_t *call_back_pAdapter = pAdapter;
10990 complete(&call_back_pAdapter->change_country_code);
10991 return NULL;
10992}
10993
Rajeev Kumar98edb772016-01-19 12:42:19 -080010994/**
10995 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10996 * @wiphy: Pointer to the wiphy structure
10997 * @ndev: Pointer to the net device
10998 * @type: Interface type
10999 * @flags: Flags for change interface
11000 * @params: Pointer to change interface parameters
11001 *
11002 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011003 */
11004static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11005 struct net_device *ndev,
11006 enum nl80211_iftype type,
11007 u32 *flags,
11008 struct vif_params *params)
11009{
11010 struct wireless_dev *wdev;
11011 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11012 hdd_context_t *pHddCtx;
11013 tCsrRoamProfile *pRoamProfile = NULL;
11014 eCsrRoamBssType LastBSSType;
11015 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011016 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011017 int status;
11018
11019 ENTER();
11020
Anurag Chouhan6d760662016-02-20 16:05:43 +053011021 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011022 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011023 return -EINVAL;
11024 }
11025
11026 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11027 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011028 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011029 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011030
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011031 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011032 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11033 pAdapter->sessionId, type));
11034
Jeff Johnson77848112016-06-29 14:52:06 -070011035 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011036 pAdapter->device_mode, type);
11037
Arun Khandavallifae92942016-08-01 13:31:08 +053011038 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11039 if (status) {
11040 hdd_err("Failed to start modules");
11041 return -EINVAL;
11042 }
11043
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011044 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11046 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011047 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011048 return -EINVAL;
11049 }
11050
11051 pConfig = pHddCtx->config;
11052 wdev = ndev->ieee80211_ptr;
11053
11054 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011055 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056
Nitesh Shahe6359752017-02-23 19:57:50 +053011057 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011058 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11059 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11060 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11061 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011062 hdd_wext_state_t *pWextState =
11063 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11064
11065 pRoamProfile = &pWextState->roamProfile;
11066 LastBSSType = pRoamProfile->BSSType;
11067
11068 switch (type) {
11069 case NL80211_IFTYPE_STATION:
11070 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011071 case NL80211_IFTYPE_ADHOC:
11072 if (type == NL80211_IFTYPE_ADHOC) {
11073 wlan_hdd_tdls_exit(pAdapter);
11074 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011075 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011076 }
11077 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11078 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011079 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011080 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011081 if (hdd_start_adapter(pAdapter)) {
11082 hdd_err("Failed to start adapter :%d",
11083 pAdapter->device_mode);
11084 return -EINVAL;
11085 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011086 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 case NL80211_IFTYPE_AP:
11088 case NL80211_IFTYPE_P2P_GO:
11089 {
Jeff Johnson77848112016-06-29 14:52:06 -070011090 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011091 (type ==
11092 NL80211_IFTYPE_AP) ? "SoftAP" :
11093 "P2pGo");
11094
11095 /* Cancel any remain on channel for GO mode */
11096 if (NL80211_IFTYPE_P2P_GO == type) {
11097 wlan_hdd_cancel_existing_remain_on_channel
11098 (pAdapter);
11099 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011100
Arun Khandavallifae92942016-08-01 13:31:08 +053011101 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011102 /* De-init the adapter */
11103 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11104 memset(&pAdapter->sessionCtx, 0,
11105 sizeof(pAdapter->sessionCtx));
11106 pAdapter->device_mode =
11107 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011108 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11109 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110
11111 /*
11112 * Fw will take care incase of concurrency
11113 */
11114
Krunal Sonib4326f22016-03-10 13:05:51 -080011115 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011116 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011117 /* To meet Android requirements create
11118 * a randomized MAC address of the
11119 * form 02:1A:11:Fx:xx:xx
11120 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011121 get_random_bytes(&ndev->dev_addr[3], 3);
11122 ndev->dev_addr[0] = 0x02;
11123 ndev->dev_addr[1] = 0x1A;
11124 ndev->dev_addr[2] = 0x11;
11125 ndev->dev_addr[3] |= 0xF0;
11126 memcpy(pAdapter->macAddressCurrent.
11127 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011128 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129 pr_info("wlan: Generated HotSpot BSSID "
11130 MAC_ADDRESS_STR "\n",
11131 MAC_ADDR_ARRAY(ndev->dev_addr));
11132 }
11133
11134 hdd_set_ap_ops(pAdapter->dev);
11135
Arun Khandavallifae92942016-08-01 13:31:08 +053011136 if (hdd_start_adapter(pAdapter)) {
11137 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011138 return -EINVAL;
11139 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011140 /* Interface type changed update in wiphy structure */
11141 if (wdev) {
11142 wdev->iftype = type;
11143 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011144 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011145 return -EINVAL;
11146 }
11147 goto done;
11148 }
11149
11150 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011151 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152 type);
11153 return -EOPNOTSUPP;
11154 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011155 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11156 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 switch (type) {
11158 case NL80211_IFTYPE_STATION:
11159 case NL80211_IFTYPE_P2P_CLIENT:
11160 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011161 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11162 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011163 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011164 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011165 if (hdd_start_adapter(pAdapter)) {
11166 hdd_err("Failed to start adapter :%d",
11167 pAdapter->device_mode);
11168 return -EINVAL;
11169 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170 goto done;
11171
11172 case NL80211_IFTYPE_AP:
11173 case NL80211_IFTYPE_P2P_GO:
11174 wdev->iftype = type;
11175 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011176 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 goto done;
11178
11179 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011180 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011181 type);
11182 return -EOPNOTSUPP;
11183 }
11184 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011185 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186 pAdapter->device_mode);
11187 return -EOPNOTSUPP;
11188 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011189done:
11190 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011191 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011192
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011193 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011194
11195 EXIT();
11196 return 0;
11197}
11198
Rajeev Kumar98edb772016-01-19 12:42:19 -080011199/**
11200 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11201 * @wiphy: Pointer to the wiphy structure
11202 * @ndev: Pointer to the net device
11203 * @type: Interface type
11204 * @flags: Flags for change interface
11205 * @params: Pointer to change interface parameters
11206 *
11207 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011208 */
11209static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11210 struct net_device *ndev,
11211 enum nl80211_iftype type,
11212 u32 *flags,
11213 struct vif_params *params)
11214{
11215 int ret;
11216
11217 cds_ssr_protect(__func__);
11218 ret =
11219 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11220 cds_ssr_unprotect(__func__);
11221
11222 return ret;
11223}
11224
11225#ifdef FEATURE_WLAN_TDLS
11226static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11227 int index, uint8_t match)
11228{
11229 int i;
11230 for (i = 0; i < index; i++) {
11231 if (arr[i] == match)
11232 return true;
11233 }
11234 return false;
11235}
11236#endif
11237
11238/**
11239 * __wlan_hdd_change_station() - change station
11240 * @wiphy: Pointer to the wiphy structure
11241 * @dev: Pointer to the net device.
11242 * @mac: bssid
11243 * @params: Pointer to station parameters
11244 *
11245 * Return: 0 for success, error number on failure.
11246 */
11247#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11248static int __wlan_hdd_change_station(struct wiphy *wiphy,
11249 struct net_device *dev,
11250 const uint8_t *mac,
11251 struct station_parameters *params)
11252#else
11253static int __wlan_hdd_change_station(struct wiphy *wiphy,
11254 struct net_device *dev,
11255 uint8_t *mac,
11256 struct station_parameters *params)
11257#endif
11258{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011259 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11261 hdd_context_t *pHddCtx;
11262 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011263 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264#ifdef FEATURE_WLAN_TDLS
11265 tCsrStaParams StaParams = { 0 };
11266 uint8_t isBufSta = 0;
11267 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011268 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011269#endif
11270 int ret;
11271
11272 ENTER();
11273
Anurag Chouhan6d760662016-02-20 16:05:43 +053011274 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011275 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011276 return -EINVAL;
11277 }
11278
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011279 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011280 TRACE_CODE_HDD_CHANGE_STATION,
11281 pAdapter->sessionId, params->listen_interval));
11282
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011283 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11284 hdd_err("invalid session id: %d", pAdapter->sessionId);
11285 return -EINVAL;
11286 }
11287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011288 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11289 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011290 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011291 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011292
11293 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11294
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011295 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011296
Krunal Sonib4326f22016-03-10 13:05:51 -080011297 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11298 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011299 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11300 status =
11301 hdd_softap_change_sta_state(pAdapter,
11302 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011303 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011305 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011306 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011307 return -EINVAL;
11308 }
11309 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011310 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11311 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312#ifdef FEATURE_WLAN_TDLS
11313 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011314
11315 if (cds_is_sub_20_mhz_enabled()) {
11316 hdd_err("TDLS not allowed with sub 20 MHz");
11317 return -EINVAL;
11318 }
11319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011320 StaParams.capability = params->capability;
11321 StaParams.uapsd_queues = params->uapsd_queues;
11322 StaParams.max_sp = params->max_sp;
11323
11324 /* Convert (first channel , number of channels) tuple to
11325 * the total list of channels. This goes with the assumption
11326 * that if the first channel is < 14, then the next channels
11327 * are an incremental of 1 else an incremental of 4 till the number
11328 * of channels.
11329 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011330 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011331 if (0 != params->supported_channels_len) {
11332 int i = 0, j = 0, k = 0, no_of_channels = 0;
11333 int num_unique_channels;
11334 int next;
11335 for (i = 0;
11336 i < params->supported_channels_len
11337 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11338 int wifi_chan_index;
11339 if (!wlan_hdd_is_duplicate_channel
11340 (StaParams.supported_channels, j,
11341 params->supported_channels[i])) {
11342 StaParams.
11343 supported_channels[j] =
11344 params->
11345 supported_channels[i];
11346 } else {
11347 continue;
11348 }
11349 wifi_chan_index =
11350 ((StaParams.supported_channels[j] <=
11351 HDD_CHANNEL_14) ? 1 : 4);
11352 no_of_channels =
11353 params->supported_channels[i + 1];
11354
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011355 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 -080011356 StaParams.
11357 supported_channels[j],
11358 wifi_chan_index,
11359 no_of_channels);
11360 for (k = 1; k <= no_of_channels &&
11361 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11362 k++) {
11363 next =
11364 StaParams.
11365 supported_channels[j] +
11366 wifi_chan_index;
11367 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11368 StaParams.
11369 supported_channels[j
11370 +
11371 1]
11372 = next;
11373 } else {
11374 continue;
11375 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011376 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 j + 1,
11378 StaParams.
11379 supported_channels[j +
11380 1]);
11381 j += 1;
11382 }
11383 }
11384 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011385 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011387 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011388 StaParams.
11389 supported_channels[i]);
11390 }
11391 if (MAX_CHANNEL < num_unique_channels)
11392 num_unique_channels = MAX_CHANNEL;
11393 StaParams.supported_channels_len =
11394 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011395 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 StaParams.supported_channels_len);
11397 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011398 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 params->supported_oper_classes,
11400 params->supported_oper_classes_len);
11401 StaParams.supported_oper_classes_len =
11402 params->supported_oper_classes_len;
11403
11404 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011405 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 params->ext_capab,
11407 sizeof(StaParams.extn_capability));
11408
11409 if (NULL != params->ht_capa) {
11410 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011411 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011412 sizeof(tSirHTCap));
11413 }
11414
11415 StaParams.supported_rates_len =
11416 params->supported_rates_len;
11417
11418 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11419 * The supported_rates array , for all the structures propogating till Add Sta
11420 * to the firmware has to be modified , if the supplicant (ieee80211) is
11421 * modified to send more rates.
11422 */
11423
11424 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11425 */
11426 if (StaParams.supported_rates_len >
11427 SIR_MAC_MAX_SUPP_RATES)
11428 StaParams.supported_rates_len =
11429 SIR_MAC_MAX_SUPP_RATES;
11430
11431 if (0 != StaParams.supported_rates_len) {
11432 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011433 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011434 params->supported_rates,
11435 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011436 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437 StaParams.supported_rates_len);
11438 for (i = 0; i < StaParams.supported_rates_len;
11439 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011440 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011441 StaParams.supported_rates[i]);
11442 }
11443
11444 if (NULL != params->vht_capa) {
11445 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011446 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447 params->vht_capa,
11448 sizeof(tSirVHTCap));
11449 }
11450
11451 if (0 != params->ext_capab_len) {
11452 /*Define A Macro : TODO Sunil */
11453 if ((1 << 4) & StaParams.extn_capability[3]) {
11454 isBufSta = 1;
11455 }
11456 /* TDLS Channel Switching Support */
11457 if ((1 << 6) & StaParams.extn_capability[3]) {
11458 isOffChannelSupported = 1;
11459 }
11460 }
11461
Nitesh Shah99934ac2016-09-05 15:54:08 +053011462 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011463 (params->ht_capa || params->vht_capa ||
11464 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011465 is_qos_wmm_sta = true;
11466
11467 hdd_notice("%s: TDLS Peer is QOS capable"
11468 " is_qos_wmm_sta= %d HTcapPresent = %d",
11469 __func__, is_qos_wmm_sta,
11470 StaParams.htcap_present);
11471
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011473 &StaParams,
11474 isBufSta,
11475 isOffChannelSupported,
11476 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011477 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011478 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011479 return -EINVAL;
11480 }
11481
11482 status =
11483 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11484 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011485 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011486 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011487 return -EINVAL;
11488 }
11489 }
11490#endif
11491 }
11492 EXIT();
11493 return ret;
11494}
11495
11496/**
11497 * wlan_hdd_change_station() - cfg80211 change station handler function
11498 * @wiphy: Pointer to the wiphy structure
11499 * @dev: Pointer to the net device.
11500 * @mac: bssid
11501 * @params: Pointer to station parameters
11502 *
11503 * This is the cfg80211 change station handler function which invokes
11504 * the internal function @__wlan_hdd_change_station with
11505 * SSR protection.
11506 *
11507 * Return: 0 for success, error number on failure.
11508 */
11509#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11510static int wlan_hdd_change_station(struct wiphy *wiphy,
11511 struct net_device *dev,
11512 const u8 *mac,
11513 struct station_parameters *params)
11514#else
11515static int wlan_hdd_change_station(struct wiphy *wiphy,
11516 struct net_device *dev,
11517 u8 *mac,
11518 struct station_parameters *params)
11519#endif
11520{
11521 int ret;
11522
11523 cds_ssr_protect(__func__);
11524 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11525 cds_ssr_unprotect(__func__);
11526
11527 return ret;
11528}
11529
11530/*
11531 * FUNCTION: __wlan_hdd_cfg80211_add_key
11532 * This function is used to initialize the key information
11533 */
11534static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11535 struct net_device *ndev,
11536 u8 key_index, bool pairwise,
11537 const u8 *mac_addr,
11538 struct key_params *params)
11539{
11540 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11541 tCsrRoamSetKey setKey;
11542 int status;
11543 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011544 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011545 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011546 hdd_context_t *pHddCtx;
11547 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11548
11549 ENTER();
11550
Anurag Chouhan6d760662016-02-20 16:05:43 +053011551 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011552 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011553 return -EINVAL;
11554 }
11555
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011556 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11557 hdd_err("invalid session id: %d", pAdapter->sessionId);
11558 return -EINVAL;
11559 }
11560
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011561 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11563 pAdapter->sessionId, params->key_len));
11564 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11565 status = wlan_hdd_validate_context(pHddCtx);
11566
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011567 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011568 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011570 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011571 hdd_device_mode_to_string(pAdapter->device_mode),
11572 pAdapter->device_mode);
11573
11574 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011575 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011576
11577 return -EINVAL;
11578 }
11579
11580 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011581 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011582
11583 return -EINVAL;
11584 }
11585
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011586 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587
11588 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011589 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590 setKey.keyId = key_index;
11591 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011592 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011593
11594 switch (params->cipher) {
11595 case WLAN_CIPHER_SUITE_WEP40:
11596 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11597 break;
11598
11599 case WLAN_CIPHER_SUITE_WEP104:
11600 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11601 break;
11602
11603 case WLAN_CIPHER_SUITE_TKIP:
11604 {
11605 u8 *pKey = &setKey.Key[0];
11606 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11607
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011608 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011610 /* Supplicant sends the 32bytes key in this order
11611 *
11612 * |--------------|----------|----------|
11613 * | Tk1 |TX-MIC | RX Mic |
11614 * |--------------|----------|----------|
11615 * <---16bytes---><--8bytes--><--8bytes-->
11616 *
11617 * Sme expects the 32 bytes key to be in the below order
11618 *
11619 * |--------------|----------|----------|
11620 * | Tk1 |RX-MIC | TX Mic |
11621 * |--------------|----------|----------|
11622 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623 */
11624 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011625 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011626
11627 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011628 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011629
11630 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011631 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632
11633 break;
11634 }
11635
11636 case WLAN_CIPHER_SUITE_CCMP:
11637 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11638 break;
11639
11640#ifdef FEATURE_WLAN_WAPI
11641 case WLAN_CIPHER_SUITE_SMS4:
11642 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011643 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011644 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11645 mac_addr, params->key,
11646 params->key_len);
11647 return 0;
11648 }
11649#endif
11650
11651#ifdef FEATURE_WLAN_ESE
11652 case WLAN_CIPHER_SUITE_KRK:
11653 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11654 break;
11655#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11656 case WLAN_CIPHER_SUITE_BTK:
11657 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11658 break;
11659#endif
11660#endif
11661
11662#ifdef WLAN_FEATURE_11W
11663 case WLAN_CIPHER_SUITE_AES_CMAC:
11664 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11665 break;
11666#endif
11667
11668 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011669 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011670 return -EOPNOTSUPP;
11671 }
11672
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011673 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011674
11675 if (!pairwise) {
11676 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011677 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011678 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011679 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680 } else {
11681 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011682 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011683 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011684 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011685 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011686 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 /* if a key is already installed, block all subsequent ones */
11688 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011689 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011690 return 0;
11691 }
11692
11693 setKey.keyDirection = eSIR_TX_RX;
11694 /*Set the group key */
11695 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11696 pAdapter->sessionId, &setKey, &roamId);
11697
11698 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011699 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011700 return -EINVAL;
11701 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011702 /* Save the keys here and call sme_roam_set_key for setting
11703 * the PTK after peer joins the IBSS network
11704 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011705 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011706 &setKey, sizeof(tCsrRoamSetKey));
11707
11708 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11709 return status;
11710 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011711 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11712 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11714 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011715 status = wlansap_set_key_sta(
11716 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011717 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011718 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 __LINE__, status);
11720 }
11721 }
11722
11723 /* Save the key in ap ctx for use on START_BASS and restart */
11724 if (pairwise ||
11725 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11726 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011727 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011728 sizeof(tCsrRoamSetKey));
11729 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011730 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011731 sizeof(tCsrRoamSetKey));
11732
Krunal Sonib4326f22016-03-10 13:05:51 -080011733 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11734 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011735 hdd_wext_state_t *pWextState =
11736 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11737 hdd_station_ctx_t *pHddStaCtx =
11738 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11739
11740 if (!pairwise) {
11741 /* set group key */
11742 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011743 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744 __func__, __LINE__);
11745 hdd_perform_roam_set_key_complete(pAdapter);
11746 }
11747 }
11748
11749 pWextState->roamProfile.Keys.KeyLength[key_index] =
11750 (u8) params->key_len;
11751
11752 pWextState->roamProfile.Keys.defaultIndex = key_index;
11753
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011754 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755 KeyMaterial[key_index][0], params->key,
11756 params->key_len);
11757
11758 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11759
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011760 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11762 setKey.keyDirection);
11763
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011764 /* The supplicant may attempt to set the PTK once
11765 * pre-authentication is done. Save the key in the
11766 * UMAC and include it in the ADD BSS request
11767 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011768 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011770 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011771 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011772 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011773 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011774 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775 return -EINVAL;
11776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011777
11778 /* issue set key request to SME */
11779 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11780 pAdapter->sessionId, &setKey, &roamId);
11781
11782 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011783 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 pHddStaCtx->roam_info.roamingState =
11785 HDD_ROAM_STATE_NONE;
11786 return -EINVAL;
11787 }
11788
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011789 /* in case of IBSS as there was no information
11790 * available about WEP keys during IBSS join, group
11791 * key intialized with NULL key, so re-initialize
11792 * group key with correct value
11793 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011794 if ((eCSR_BSS_TYPE_START_IBSS ==
11795 pWextState->roamProfile.BSSType)
11796 &&
11797 !((IW_AUTH_KEY_MGMT_802_1X ==
11798 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11799 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11800 pHddStaCtx->conn_info.authType)
11801 )
11802 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11803 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11804 )
11805 ) {
11806 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011807 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011808
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011809 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011810 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11811 setKey.keyDirection);
11812
11813 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11814 pAdapter->sessionId, &setKey,
11815 &roamId);
11816
11817 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011818 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011819 pHddStaCtx->roam_info.roamingState =
11820 HDD_ROAM_STATE_NONE;
11821 return -EINVAL;
11822 }
11823 }
11824 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011825 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 return 0;
11827}
11828
11829static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11830 struct net_device *ndev,
11831 u8 key_index, bool pairwise,
11832 const u8 *mac_addr,
11833 struct key_params *params)
11834{
11835 int ret;
11836 cds_ssr_protect(__func__);
11837 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11838 mac_addr, params);
11839 cds_ssr_unprotect(__func__);
11840
11841 return ret;
11842}
11843
11844/*
11845 * FUNCTION: __wlan_hdd_cfg80211_get_key
11846 * This function is used to get the key information
11847 */
11848static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11849 struct net_device *ndev,
11850 u8 key_index, bool pairwise,
11851 const u8 *mac_addr, void *cookie,
11852 void (*callback)(void *cookie,
11853 struct key_params *)
11854 )
11855{
11856 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11857 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11858 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11859 struct key_params params;
11860
11861 ENTER();
11862
Anurag Chouhan6d760662016-02-20 16:05:43 +053011863 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011864 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865 return -EINVAL;
11866 }
11867
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011868 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011869 hdd_device_mode_to_string(pAdapter->device_mode),
11870 pAdapter->device_mode);
11871
11872 memset(&params, 0, sizeof(params));
11873
11874 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011875 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 key_index);
11877 return -EINVAL;
11878 }
11879
11880 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11881 case eCSR_ENCRYPT_TYPE_NONE:
11882 params.cipher = IW_AUTH_CIPHER_NONE;
11883 break;
11884
11885 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11886 case eCSR_ENCRYPT_TYPE_WEP40:
11887 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11888 break;
11889
11890 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11891 case eCSR_ENCRYPT_TYPE_WEP104:
11892 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11893 break;
11894
11895 case eCSR_ENCRYPT_TYPE_TKIP:
11896 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11897 break;
11898
11899 case eCSR_ENCRYPT_TYPE_AES:
11900 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11901 break;
11902
11903 default:
11904 params.cipher = IW_AUTH_CIPHER_NONE;
11905 break;
11906 }
11907
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011908 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011909 TRACE_CODE_HDD_CFG80211_GET_KEY,
11910 pAdapter->sessionId, params.cipher));
11911
11912 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11913 params.seq_len = 0;
11914 params.seq = NULL;
11915 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11916 callback(cookie, &params);
11917
11918 EXIT();
11919 return 0;
11920}
11921
11922static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11923 struct net_device *ndev,
11924 u8 key_index, bool pairwise,
11925 const u8 *mac_addr, void *cookie,
11926 void (*callback)(void *cookie,
11927 struct key_params *)
11928 )
11929{
11930 int ret;
11931
11932 cds_ssr_protect(__func__);
11933 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11934 mac_addr, cookie, callback);
11935 cds_ssr_unprotect(__func__);
11936
11937 return ret;
11938}
11939
11940/**
11941 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11942 * @wiphy: wiphy interface context
11943 * @ndev: pointer to net device
11944 * @key_index: Key index used in 802.11 frames
11945 * @unicast: true if it is unicast key
11946 * @multicast: true if it is multicast key
11947 *
11948 * This function is required for cfg80211_ops API.
11949 * It is used to delete the key information
11950 * Underlying hardware implementation does not have API to delete the
11951 * encryption key. It is automatically deleted when the peer is
11952 * removed. Hence this function currently does nothing.
11953 * Future implementation may interprete delete key operation to
11954 * replacing the key with a random junk value, effectively making it
11955 * useless.
11956 *
11957 * Return: status code, always 0.
11958 */
11959
11960static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11961 struct net_device *ndev,
11962 u8 key_index,
11963 bool pairwise, const u8 *mac_addr)
11964{
11965 EXIT();
11966 return 0;
11967}
11968
11969/**
11970 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11971 * @wiphy: Pointer to wiphy structure.
11972 * @dev: Pointer to net_device structure.
11973 * @key_index: key index
11974 * @pairwise: pairwise
11975 * @mac_addr: mac address
11976 *
11977 * This is the cfg80211 delete key handler function which invokes
11978 * the internal function @__wlan_hdd_cfg80211_del_key with
11979 * SSR protection.
11980 *
11981 * Return: 0 for success, error number on failure.
11982 */
11983static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11984 struct net_device *dev,
11985 u8 key_index,
11986 bool pairwise, const u8 *mac_addr)
11987{
11988 int ret;
11989
11990 cds_ssr_protect(__func__);
11991 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11992 pairwise, mac_addr);
11993 cds_ssr_unprotect(__func__);
11994
11995 return ret;
11996}
11997
11998/*
11999 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12000 * This function is used to set the default tx key index
12001 */
12002static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12003 struct net_device *ndev,
12004 u8 key_index,
12005 bool unicast, bool multicast)
12006{
12007 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12008 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12009 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12010 hdd_context_t *pHddCtx;
12011 int status;
12012
12013 ENTER();
12014
Anurag Chouhan6d760662016-02-20 16:05:43 +053012015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012016 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012017 return -EINVAL;
12018 }
12019
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012020 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12021 hdd_err("invalid session id: %d", pAdapter->sessionId);
12022 return -EINVAL;
12023 }
12024
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012025 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012026 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12027 pAdapter->sessionId, key_index));
12028
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012029 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 hdd_device_mode_to_string(pAdapter->device_mode),
12031 pAdapter->device_mode, key_index);
12032
12033 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012034 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012035 return -EINVAL;
12036 }
12037
12038 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12039 status = wlan_hdd_validate_context(pHddCtx);
12040
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012041 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012042 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043
Krunal Sonib4326f22016-03-10 13:05:51 -080012044 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12045 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012046 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12047 pHddStaCtx->conn_info.ucEncryptionType) &&
12048 (eCSR_ENCRYPT_TYPE_AES !=
12049 pHddStaCtx->conn_info.ucEncryptionType)) {
12050 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012051 * then update the default key index
12052 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012053
12054 tCsrRoamSetKey setKey;
12055 uint32_t roamId = 0xFF;
12056 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12057
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012058 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012059
12060 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012061 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 setKey.keyId = key_index;
12063 setKey.keyLength = Keys->KeyLength[key_index];
12064
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012065 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012066 &Keys->KeyMaterial[key_index][0],
12067 Keys->KeyLength[key_index]);
12068
12069 setKey.keyDirection = eSIR_TX_RX;
12070
Anurag Chouhanc5548422016-02-24 18:33:27 +053012071 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072 &pHddStaCtx->conn_info.bssId);
12073
12074 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12075 pWextState->roamProfile.EncryptionType.
12076 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012077 /* In the case of dynamic wep
12078 * supplicant hardcodes DWEP type to
12079 * eCSR_ENCRYPT_TYPE_WEP104 even
12080 * though ap is configured for WEP-40
12081 * encryption. In this canse the key
12082 * length is 5 but the encryption type
12083 * is 104 hence checking the key
12084 * lenght(5) and encryption type(104)
12085 * and switching encryption type to 40
12086 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087 pWextState->roamProfile.EncryptionType.
12088 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12089 pWextState->roamProfile.mcEncryptionType.
12090 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12091 }
12092
12093 setKey.encType =
12094 pWextState->roamProfile.EncryptionType.
12095 encryptionType[0];
12096
12097 /* Issue set key request */
12098 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12099 pAdapter->sessionId, &setKey,
12100 &roamId);
12101
12102 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012103 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012104 status);
12105 return -EINVAL;
12106 }
12107 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012108 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012109 /* In SoftAp mode setting key direction for default mode */
12110 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12111 pWextState->roamProfile.EncryptionType.encryptionType[0])
12112 && (eCSR_ENCRYPT_TYPE_AES !=
12113 pWextState->roamProfile.EncryptionType.
12114 encryptionType[0])) {
12115 /* Saving key direction for default key index to TX default */
12116 hdd_ap_ctx_t *pAPCtx =
12117 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12118 pAPCtx->wepKey[key_index].keyDirection =
12119 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012120 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012121 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012122 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 }
12124 }
12125
12126 EXIT();
12127 return status;
12128}
12129
12130static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12131 struct net_device *ndev,
12132 u8 key_index,
12133 bool unicast, bool multicast)
12134{
12135 int ret;
12136 cds_ssr_protect(__func__);
12137 ret =
12138 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12139 multicast);
12140 cds_ssr_unprotect(__func__);
12141
12142 return ret;
12143}
12144
Abhishek Singhc9941602016-08-09 16:06:22 +053012145/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012146 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12147 * interface that BSS might have been lost.
12148 * @pAdapter: adaptor
12149 * @bssid: bssid which might have been lost
12150 *
12151 * Return: bss which is unlinked from kernel cache
12152 */
12153struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12154 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155{
12156 struct net_device *dev = pAdapter->dev;
12157 struct wireless_dev *wdev = dev->ieee80211_ptr;
12158 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012159 struct cfg80211_bss *bss = NULL;
12160
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012161 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012162 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012163 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012164 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012165 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012166 hdd_info("cfg80211_unlink_bss called for BSSID "
12167 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012168 cfg80211_unlink_bss(wiphy, bss);
12169 }
12170 return bss;
12171}
12172
Abhishek Singhc9941602016-08-09 16:06:22 +053012173
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174/**
12175 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12176 * @pAdapter: Pointer to adapter
12177 * @bss_desc: Pointer to bss descriptor
12178 *
12179 * This function is used to inform the BSS details to nl80211 interface.
12180 *
12181 * Return: struct cfg80211_bss pointer
12182 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012183struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12184 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185{
12186 /*
12187 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12188 * already exists in bss data base of cfg80211 for that particular BSS
12189 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12190 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12191 * As of now there is no possibility to get the mgmt(probe response)
12192 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12193 * and passing to cfg80211_inform_bss_frame.
12194 */
12195 struct net_device *dev = pAdapter->dev;
12196 struct wireless_dev *wdev = dev->ieee80211_ptr;
12197 struct wiphy *wiphy = wdev->wiphy;
12198 int chan_no = bss_desc->channelId;
12199#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12200 qcom_ie_age *qie_age = NULL;
12201 int ie_length =
12202 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12203#else
12204 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12205#endif
12206 const char *ie =
12207 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12208 unsigned int freq;
12209 struct ieee80211_channel *chan;
12210 struct ieee80211_mgmt *mgmt = NULL;
12211 struct cfg80211_bss *bss_status = NULL;
12212 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12213 int rssi = 0;
12214 hdd_context_t *pHddCtx;
12215 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012216 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012217 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012218
12219 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12220 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012221 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012222 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012224 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012225 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012226 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012227 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012228 return NULL;
12229 }
12230
12231 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12232
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012234 * Instead it wants a monotonic increasing value
12235 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012236 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012237 mgmt->u.probe_resp.timestamp =
12238 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012239
12240 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12241 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12242
12243#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12244 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12245 /* Assuming this is the last IE, copy at the end */
12246 ie_length -= sizeof(qcom_ie_age);
12247 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12248 qie_age->element_id = QCOM_VENDOR_IE_ID;
12249 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12250 qie_age->oui_1 = QCOM_OUI1;
12251 qie_age->oui_2 = QCOM_OUI2;
12252 qie_age->oui_3 = QCOM_OUI3;
12253 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012254 /*
12255 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12256 * all bss related timestamp is in units of ms. Due to this when scan
12257 * results are sent to lowi the scan age is high.To address this,
12258 * send age in units of 1/10 ms.
12259 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012260 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012261 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012262 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012263 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12264 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012265 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12266 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012267#endif
12268
12269 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12270 if (bss_desc->fProbeRsp) {
12271 mgmt->frame_control |=
12272 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12273 } else {
12274 mgmt->frame_control |=
12275 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12276 }
12277
12278 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012279 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280 freq =
12281 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012282 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012283 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012284 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285 freq =
12286 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012287 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012289 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012290 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012291 return NULL;
12292 }
12293
12294 chan = __ieee80211_get_channel(wiphy, freq);
12295 /* When the band is changed on the fly using the GUI, three things are done
12296 * 1. scan abort
12297 * 2. flush scan results from cache
12298 * 3. update the band with the new band user specified (refer to the
12299 * hdd_set_band_helper function) as part of the scan abort, message will be
12300 * queued to PE and we proceed with flushing and changinh the band.
12301 * PE will stop the scanning further and report back the results what ever
12302 * it had till now by calling the call back function.
12303 * if the time between update band and scandone call back is sufficient
12304 * enough the band change reflects in SME, SME validates the channels
12305 * and discards the channels correponding to previous band and calls back
12306 * with zero bss results. but if the time between band update and scan done
12307 * callback is very small then band change will not reflect in SME and SME
12308 * reports to HDD all the channels correponding to previous band.this is due
12309 * to race condition.but those channels are invalid to the new band and so
12310 * this function __ieee80211_get_channel will return NULL.Each time we
12311 * report scan result with this pointer null warning kernel trace is printed.
12312 * if the scan results contain large number of APs continuosly kernel
12313 * warning trace is printed and it will lead to apps watch dog bark.
12314 * So drop the bss and continue to next bss.
12315 */
12316 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012317 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12318 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012319 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 return NULL;
12321 }
12322
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012323 /* Based on .ini configuration, raw rssi can be reported for bss.
12324 * Raw rssi is typically used for estimating power.
12325 */
12326
12327 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12328 bss_desc->rssi;
12329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012331 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012332
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012333 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012335 (int)(rssi / 100),
12336 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012337
12338 bss_status =
12339 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
12340 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012341 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012342 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 return bss_status;
12344}
12345
12346/**
12347 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12348 * @pAdapter: Pointer to adapter
12349 * @pRoamInfo: Pointer to roam info
12350 *
12351 * This function is used to update the BSS data base of CFG8011
12352 *
12353 * Return: struct cfg80211_bss pointer
12354 */
12355struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12356 tCsrRoamInfo *pRoamInfo)
12357{
12358 tCsrRoamConnectedProfile roamProfile;
12359 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12360 struct cfg80211_bss *bss = NULL;
12361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012362 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12363 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12364
12365 if (NULL != roamProfile.pBssDesc) {
12366 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12367 roamProfile.pBssDesc);
12368
12369 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012370 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012372 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012374 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012375 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012376 return bss;
12377}
12378/**
12379 * wlan_hdd_cfg80211_update_bss() - update bss
12380 * @wiphy: Pointer to wiphy
12381 * @pAdapter: Pointer to adapter
12382 * @scan_time: scan request timestamp
12383 *
12384 * Return: zero if success, non-zero otherwise
12385 */
12386int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12387 hdd_adapter_t *pAdapter,
12388 uint32_t scan_time)
12389{
12390 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12391 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012392 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012393 tScanResultHandle pResult;
12394 struct cfg80211_bss *bss_status = NULL;
12395 hdd_context_t *pHddCtx;
12396 int ret;
12397
12398 ENTER();
12399
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012400 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12401 hdd_err("invalid session id: %d", pAdapter->sessionId);
12402 return -EINVAL;
12403 }
12404
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012405 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12407 NO_SESSION, pAdapter->sessionId));
12408
12409 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12410 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012411 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012412 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012413
12414 /* start getting scan results and populate cgf80211 BSS database */
12415 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12416
12417 /* no scan results */
12418 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012419 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012420 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012421 }
12422
12423 pScanResult = sme_scan_result_get_first(hHal, pResult);
12424
12425 while (pScanResult) {
12426 /*
12427 * - cfg80211_inform_bss() is not updating ie field of bss
12428 * entry if entry already exists in bss data base of cfg80211
12429 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12430 * to update thebss entry instead of cfg80211_inform_bss,
12431 * But this call expects mgmt packet as input. As of now
12432 * there is no possibility to get the mgmt(probe response)
12433 * frame from PE, converting bss_desc to
12434 * ieee80211_mgmt(probe response) and passing to c
12435 * fg80211_inform_bss_frame.
12436 * - Update BSS only if beacon timestamp is later than
12437 * scan request timestamp.
12438 */
12439 if ((scan_time == 0) ||
12440 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012441 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012442 bss_status =
12443 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12444 &pScanResult->BssDescriptor);
12445
12446 if (NULL == bss_status) {
12447 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12448 } else {
12449 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012450 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012451 bss_status);
12452 }
12453 } else {
12454 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12455 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12456 }
12457 pScanResult = sme_scan_result_get_next(hHal, pResult);
12458 }
12459
12460 sme_scan_result_purge(hHal, pResult);
12461 /*
12462 * For SAP mode, scan is invoked by hostapd during SAP start
12463 * if hostapd is restarted, we need to flush previous scan
12464 * result so that it will reflect environment change
12465 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012466 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012467#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12468 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12469#endif
12470 )
12471 sme_scan_flush_result(hHal);
12472
12473 EXIT();
12474 return 0;
12475}
12476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477/**
12478 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12479 * @pAdapter: Pointer to adapter
12480 * @pRoamInfo: Pointer to roam info
12481 * @index: Index
12482 * @preauth: Preauth flag
12483 *
12484 * This function is used to notify the supplicant of a new PMKSA candidate.
12485 *
12486 * Return: 0 for success, non-zero for failure
12487 */
12488int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12489 tCsrRoamInfo *pRoamInfo,
12490 int index, bool preauth)
12491{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492 struct net_device *dev = pAdapter->dev;
12493 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12494
12495 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012496 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012497
12498 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012499 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 return -EINVAL;
12501 }
12502
12503 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012504 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012505 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12506 cfg80211_pmksa_candidate_notify(dev, index,
12507 pRoamInfo->bssid.bytes,
12508 preauth, GFP_KERNEL);
12509 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012510 return 0;
12511}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012512
12513#ifdef FEATURE_WLAN_LFR_METRICS
12514/**
12515 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12516 * @pAdapter: Pointer to adapter
12517 * @pRoamInfo: Pointer to roam info
12518 *
12519 * 802.11r/LFR metrics reporting function to report preauth initiation
12520 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012521 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 */
12523#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012524QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012525 tCsrRoamInfo *pRoamInfo)
12526{
12527 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12528 union iwreq_data wrqu;
12529
12530 ENTER();
12531
12532 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012533 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012534 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012535 }
12536
12537 /* create the event */
12538 memset(&wrqu, 0, sizeof(wrqu));
12539 memset(metrics_notification, 0, sizeof(metrics_notification));
12540
12541 wrqu.data.pointer = metrics_notification;
12542 wrqu.data.length = scnprintf(metrics_notification,
12543 sizeof(metrics_notification),
12544 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12545 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12546
12547 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12548 metrics_notification);
12549
12550 EXIT();
12551
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012552 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012553}
12554
12555/**
12556 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12557 * @pAdapter: Pointer to adapter
12558 * @pRoamInfo: Pointer to roam info
12559 * @preauth_status: Preauth status
12560 *
12561 * 802.11r/LFR metrics reporting function to report handover initiation
12562 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012563 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012564 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012565QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012566wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12567 tCsrRoamInfo *pRoamInfo,
12568 bool preauth_status)
12569{
12570 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12571 union iwreq_data wrqu;
12572
12573 ENTER();
12574
12575 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012576 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012577 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012578 }
12579
12580 /* create the event */
12581 memset(&wrqu, 0, sizeof(wrqu));
12582 memset(metrics_notification, 0, sizeof(metrics_notification));
12583
12584 scnprintf(metrics_notification, sizeof(metrics_notification),
12585 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12586 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12587
12588 if (1 == preauth_status)
12589 strlcat(metrics_notification, " true",
12590 sizeof(metrics_notification));
12591 else
12592 strlcat(metrics_notification, " false",
12593 sizeof(metrics_notification));
12594
12595 wrqu.data.pointer = metrics_notification;
12596 wrqu.data.length = strlen(metrics_notification);
12597
12598 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12599 metrics_notification);
12600
12601 EXIT();
12602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012603 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012604}
12605
12606/**
12607 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12608 * @pAdapter: Pointer to adapter
12609 * @pRoamInfo: Pointer to roam info
12610 *
12611 * 802.11r/LFR metrics reporting function to report handover initiation
12612 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012613 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012614 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012615QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012616 tCsrRoamInfo *pRoamInfo)
12617{
12618 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12619 union iwreq_data wrqu;
12620
12621 ENTER();
12622
12623 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012624 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012625 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012626 }
12627
12628 /* create the event */
12629 memset(&wrqu, 0, sizeof(wrqu));
12630 memset(metrics_notification, 0, sizeof(metrics_notification));
12631
12632 wrqu.data.pointer = metrics_notification;
12633 wrqu.data.length = scnprintf(metrics_notification,
12634 sizeof(metrics_notification),
12635 "QCOM: LFR_PREAUTH_HANDOVER "
12636 MAC_ADDRESS_STR,
12637 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12638
12639 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12640 metrics_notification);
12641
12642 EXIT();
12643
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012644 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012645}
12646#endif
12647
12648/**
12649 * hdd_select_cbmode() - select channel bonding mode
12650 * @pAdapter: Pointer to adapter
12651 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012652 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012653 *
12654 * Return: none
12655 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012656void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12657 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012658{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012659 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012660 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012661 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012662
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012663 /*
12664 * CDS api expects secondary channel for calculating
12665 * the channel params
12666 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012667 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012668 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12669 if (operationChannel >= 1 && operationChannel <= 5)
12670 sec_ch = operationChannel + 4;
12671 else if (operationChannel >= 6 && operationChannel <= 13)
12672 sec_ch = operationChannel - 4;
12673 }
12674
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012675 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012676 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012677
12678 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012679 eHddDot11Mode hdd_dot11_mode;
12680 uint8_t iniDot11Mode =
12681 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12682
12683 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12684 switch (iniDot11Mode) {
12685 case eHDD_DOT11_MODE_AUTO:
12686 case eHDD_DOT11_MODE_11ac:
12687 case eHDD_DOT11_MODE_11ac_ONLY:
12688 if (sme_is_feature_supported_by_fw(DOT11AC))
12689 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12690 else
12691 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12692 break;
12693 case eHDD_DOT11_MODE_11n:
12694 case eHDD_DOT11_MODE_11n_ONLY:
12695 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12696 break;
12697 default:
12698 hdd_dot11_mode = iniDot11Mode;
12699 break;
12700 }
12701 ch_info->channel_width = ch_params->ch_width;
12702 ch_info->phy_mode =
12703 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012704 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012705 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012706 hdd_info("ch_info width %d, phymode %d channel %d",
12707 ch_info->channel_width, ch_info->phy_mode,
12708 ch_info->channel);
12709 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710}
12711
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012712/**
12713 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12714 * @adapter: STA adapter
12715 * @roam_profile: STA roam profile
12716 *
12717 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12718 *
12719 * Return: false if sta-sap conc is not allowed, else return true
12720 */
12721static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12722 tCsrRoamProfile *roam_profile)
12723{
12724 hdd_context_t *hdd_ctx;
12725 hdd_adapter_t *ap_adapter;
12726 hdd_ap_ctx_t *hdd_ap_ctx;
12727 hdd_hostapd_state_t *hostapd_state;
12728 uint8_t channel = 0;
12729 QDF_STATUS status;
12730
12731 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12732 if (!hdd_ctx) {
12733 hdd_err("HDD context is NULL");
12734 return true;
12735 }
12736
12737 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12738 /* probably no sap running, no handling required */
12739 if (ap_adapter == NULL)
12740 return true;
12741
12742 /*
12743 * sap is not in started state, so it is fine to go ahead with sta.
12744 * if sap is currently doing CAC then don't allow sta to go further.
12745 */
12746 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12747 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12748 return true;
12749
12750 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12751 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12752 return false;
12753 }
12754
12755 /*
12756 * log and return error, if we allow STA to go through, we don't
12757 * know what is going to happen better stop sta connection
12758 */
12759 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12760 if (NULL == hdd_ap_ctx) {
12761 hdd_err("AP context not found");
12762 return false;
12763 }
12764
12765 /* sap is on non-dfs channel, nothing to handle */
12766 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12767 hdd_info("sap is on non-dfs channel, sta is allowed");
12768 return true;
12769 }
12770 /*
12771 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012772 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012773 */
12774 status = cds_get_channel_from_scan_result(adapter,
12775 roam_profile, &channel);
12776
Nitesh Shah59774522016-09-16 15:14:21 +053012777 /*
12778 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12779 * channels for roaming case.
12780 */
12781 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12782 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12783 return true;
12784 }
12785
12786 /*
12787 * If channel is 0 or DFS then better to call pcl and find out the
12788 * best channel. If channel is non-dfs 5 GHz then better move SAP
12789 * to STA's channel to make scc, so we have room for 3port MCC
12790 * scenario.
12791 */
12792 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012793 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12794 true);
12795
12796 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12797 qdf_event_reset(&hostapd_state->qdf_event);
12798 status = wlansap_set_channel_change_with_csa(
12799 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12800 hdd_ap_ctx->sapConfig.ch_width_orig);
12801
12802 if (QDF_STATUS_SUCCESS != status) {
12803 hdd_err("Set channel with CSA IE failed, can't allow STA");
12804 return false;
12805 }
12806
12807 /*
12808 * wait here for SAP to finish the channel switch. When channel
12809 * switch happens, SAP sends few beacons with CSA_IE. After
12810 * successfully Transmission of those beacons, it will move its
12811 * state from started to disconnected and move to new channel.
12812 * once it moves to new channel, sap again moves its state
12813 * machine from disconnected to started and set this event.
12814 * wait for 10 secs to finish this.
12815 */
12816 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12817 if (!QDF_IS_STATUS_SUCCESS(status)) {
12818 hdd_err("wait for qdf_event failed, STA not allowed!!");
12819 return false;
12820 }
12821
12822 return true;
12823}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824
Krunal Soni31949422016-07-29 17:17:53 -070012825/**
12826 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012827 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012828 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012829 * @ssid_len: Length of ssid
12830 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012831 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012832 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012833 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 *
12835 * This function is used to start the association process
12836 *
12837 * Return: 0 for success, non-zero for failure
12838 */
Krunal Soni31949422016-07-29 17:17:53 -070012839static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012840 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012841 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012842 u8 operatingChannel,
12843 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012844{
12845 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012846 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012847 hdd_wext_state_t *pWextState;
12848 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012849 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012850 uint32_t roamId;
12851 tCsrRoamProfile *pRoamProfile;
12852 eCsrAuthType RSNAuthType;
12853 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012854 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012855
12856 ENTER();
12857
12858 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12859 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012860 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012861
12862 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012863 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012864 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012865
12866 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012867 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012868 status = -EINVAL;
12869 goto ret_status;
12870 }
12871
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +053012872 if (true == cds_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012873 hdd_err("Connection refused: conn in progress");
12874 status = -EINVAL;
12875 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012876 }
12877
12878 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012879 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12880 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012881
12882 if (pRoamProfile) {
12883 hdd_station_ctx_t *pHddStaCtx;
12884 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12885
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012886 /* Restart the opportunistic timer
12887 *
12888 * If hw_mode_change_in_progress is true, then wait
12889 * till firmware sends the callback for hw_mode change.
12890 *
12891 * Else set connect_in_progress as true and proceed.
12892 */
12893 cds_restart_opportunistic_timer(false);
12894 if (cds_is_hw_mode_change_in_progress()) {
12895 status = qdf_wait_for_connection_update();
12896 if (!QDF_IS_STATUS_SUCCESS(status)) {
12897 hdd_err("qdf wait for event failed!!");
12898 status = -EINVAL;
12899 goto ret_status;
12900 }
12901 }
12902 cds_set_connection_in_progress(true);
12903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 if (HDD_WMM_USER_MODE_NO_QOS ==
12905 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12906 /*QoS not enabled in cfg file */
12907 pRoamProfile->uapsd_mask = 0;
12908 } else {
12909 /*QoS enabled, update uapsd mask from cfg file */
12910 pRoamProfile->uapsd_mask =
12911 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12912 }
12913
12914 pRoamProfile->SSIDs.numOfSSIDs = 1;
12915 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012916 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012918 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012919 ssid, ssid_len);
12920
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012921 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012922 /* cleanup bssid hint */
12923 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12924 QDF_MAC_ADDR_SIZE);
12925 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12926 QDF_MAC_ADDR_SIZE);
12927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012928 if (bssid) {
12929 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012930 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012931 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012932 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012933 /*
12934 * Save BSSID in seperate variable as
12935 * pRoamProfile's BSSID is getting zeroed out in the
12936 * association process. In case of join failure
12937 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012938 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012939 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012940 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012941 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012942 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012943 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12944 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012945 /*
12946 * Save BSSID in a separate variable as
12947 * pRoamProfile's BSSID is getting zeroed out in the
12948 * association process. In case of join failure
12949 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012950 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012951 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012952 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012953 hdd_info("bssid_hint is given by upper layer %pM",
12954 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955 }
12956
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012957 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 pRoamProfile->SSIDs.SSIDList->SSID.length,
12959 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12960 operatingChannel);
12961
12962 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12963 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012964 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12966 }
12967#ifdef FEATURE_WLAN_WAPI
12968 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012969 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 switch (pAdapter->wapi_info.wapiAuthMode) {
12971 case WAPI_AUTH_MODE_PSK:
12972 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012973 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 pAdapter->wapi_info.wapiAuthMode);
12975 pRoamProfile->AuthType.authType[0] =
12976 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12977 break;
12978 }
12979 case WAPI_AUTH_MODE_CERT:
12980 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012981 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 pAdapter->wapi_info.wapiAuthMode);
12983 pRoamProfile->AuthType.authType[0] =
12984 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12985 break;
12986 }
12987 } /* End of switch */
12988 if (pAdapter->wapi_info.wapiAuthMode ==
12989 WAPI_AUTH_MODE_PSK
12990 || pAdapter->wapi_info.wapiAuthMode ==
12991 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012992 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993 pRoamProfile->AuthType.numEntries = 1;
12994 pRoamProfile->EncryptionType.numEntries = 1;
12995 pRoamProfile->EncryptionType.encryptionType[0] =
12996 eCSR_ENCRYPT_TYPE_WPI;
12997 pRoamProfile->mcEncryptionType.numEntries = 1;
12998 pRoamProfile->mcEncryptionType.
12999 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13000 }
13001 }
Krunal Soni31949422016-07-29 17:17:53 -070013002#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013003 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004 pRoamProfile->csrPersona = pAdapter->device_mode;
13005
13006 if (operatingChannel) {
13007 pRoamProfile->ChannelInfo.ChannelList =
13008 &operatingChannel;
13009 pRoamProfile->ChannelInfo.numOfChannels = 1;
13010 } else {
13011 pRoamProfile->ChannelInfo.ChannelList = NULL;
13012 pRoamProfile->ChannelInfo.numOfChannels = 0;
13013 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013014 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015 && operatingChannel) {
13016 /*
13017 * Need to post the IBSS power save parameters
13018 * to WMA. WMA will configure this parameters
13019 * to firmware if power save is enabled by the
13020 * firmware.
13021 */
13022 status = hdd_set_ibss_power_save_params(pAdapter);
13023
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013024 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013025 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013026 status = -EINVAL;
13027 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013029 pRoamProfile->ch_params.ch_width =
13030 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013031 /*
13032 * In IBSS mode while operating in 2.4 GHz,
13033 * the device supports only 20 MHz.
13034 */
13035 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13036 pRoamProfile->ch_params.ch_width =
13037 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013038 hdd_select_cbmode(pAdapter, operatingChannel,
13039 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 }
Abhishek Singh99bce862016-06-20 15:10:51 +053013041 /*
13042 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13043 * or pmf=2 is an explicit configuration in the supplicant
13044 * configuration, drop the connection request.
13045 */
13046 if (pWextState->roamProfile.MFPEnabled &&
13047 !(pWextState->roamProfile.MFPRequired ||
13048 pWextState->roamProfile.MFPCapable)) {
13049 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13050 pWextState->roamProfile.MFPEnabled,
13051 pWextState->roamProfile.MFPRequired,
13052 pWextState->roamProfile.MFPCapable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013054 status = -EINVAL;
13055 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056 }
13057
Krunal Soni31949422016-07-29 17:17:53 -070013058 /*
13059 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013060 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013061 * enhancements, the supplicant is not issuing the scan command
13062 * now. So the unicast frames which are sent from the host are
13063 * not having the additional IEs. If it is P2P CLIENT and there
13064 * is no additional IE present in roamProfile, then use the
13065 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066 */
13067
Krunal Sonib4326f22016-03-10 13:05:51 -080013068 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013069 (!pRoamProfile->pAddIEScan)) {
13070 pRoamProfile->pAddIEScan =
13071 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13072 pRoamProfile->nAddIEScanLength =
13073 pAdapter->scan_info.scanAddIE.length;
13074 }
13075 /*
13076 * When policy manager is enabled from ini file, we shouldn't
13077 * check for other concurrency rules.
13078 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013079 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013080 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013081 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013082 pAdapter, pRoamProfile, &roamId)) {
13083 status = 0;
13084 goto conn_failure;
13085 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 }
13087
Krunal Soni3091bcc2016-06-23 12:28:21 -070013088 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013089 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13090 pRoamProfile))) {
13091 hdd_err("sap-sta conc will fail, can't allow sta");
13092 hdd_conn_set_connection_state(pAdapter,
13093 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013094 status = -ENOMEM;
13095 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013096 }
13097
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013098 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013099 if (!sme_config) {
13100 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013101 hdd_conn_set_connection_state(pAdapter,
13102 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013103 status = -ENOMEM;
13104 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 sme_get_config_param(pHddCtx->hHal, sme_config);
13107 /* These values are not sessionized. So, any change in these SME
13108 * configs on an older or parallel interface will affect the
13109 * cb mode. So, restoring the default INI params before starting
13110 * interfaces such as sta, cli etc.,
13111 */
13112 sme_config->csrConfig.channelBondingMode5GHz =
13113 pHddCtx->config->nChannelBondingMode5GHz;
13114 sme_config->csrConfig.channelBondingMode24GHz =
13115 pHddCtx->config->nChannelBondingMode24GHz;
13116 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013117 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013118 /*
13119 * Change conn_state to connecting before sme_roam_connect(),
13120 * because sme_roam_connect() has a direct path to call
13121 * hdd_sme_roam_callback(), which will change the conn_state
13122 * If direct path, conn_state will be accordingly changed to
13123 * NotConnected or Associated by either
13124 * hdd_association_completion_handler() or
13125 * hdd_dis_connect_handler() in sme_RoamCallback()if
13126 * sme_RomConnect is to be queued,
13127 * Connecting state will remain until it is completed.
13128 *
13129 * If connection state is not changed, connection state will
13130 * remain in eConnectionState_NotConnected state.
13131 * In hdd_association_completion_handler, "hddDisconInProgress"
13132 * is set to true if conn state is
13133 * eConnectionState_NotConnected.
13134 * If "hddDisconInProgress" is set to true then cfg80211 layer
13135 * is not informed of connect result indication which
13136 * is an issue.
13137 */
13138 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013139 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013140 hdd_conn_set_connection_state(pAdapter,
13141 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013142
Komal Seelama89be8d2016-09-29 11:09:26 +053013143 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13144 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013145 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013146 pAdapter->sessionId, pRoamProfile,
13147 &roamId);
13148
Rajeev Kumard31e1542017-01-13 14:37:42 -080013149 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013150 (QDF_STA_MODE == pAdapter->device_mode ||
13151 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013152 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013153 "qdf_status %d. -> NotConnected",
13154 pAdapter->sessionId, qdf_status);
13155 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013156 /* change back to NotAssociated */
13157 hdd_conn_set_connection_state(pAdapter,
13158 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013159 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13160 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 }
13162
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013163 /* Reset connect_in_progress */
13164 cds_set_connection_in_progress(false);
13165
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013166 pRoamProfile->ChannelInfo.ChannelList = NULL;
13167 pRoamProfile->ChannelInfo.numOfChannels = 0;
13168
Nitesh Shah044fd672016-10-13 18:53:25 +053013169 if ((QDF_STA_MODE == pAdapter->device_mode)
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013170 && wma_is_current_hwmode_dbs() &&
13171 !wma_is_hw_dbs_2x2_capable()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013172 cds_get_channel_from_scan_result(pAdapter,
13173 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013174 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013175 if (channel)
13176 cds_checkn_update_hw_mode_single_mac_mode
13177 (channel);
13178 }
13179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013181 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013182 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013184 goto ret_status;
13185
13186conn_failure:
13187 /* Reset connect_in_progress */
13188 cds_set_connection_in_progress(false);
13189
13190ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013191 EXIT();
13192 return status;
13193}
13194
13195/**
13196 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13197 * @pAdapter: Pointer to adapter
13198 * @auth_type: Auth type
13199 *
13200 * This function is used to set the authentication type (OPEN/SHARED).
13201 *
13202 * Return: 0 for success, non-zero for failure
13203 */
13204static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13205 enum nl80211_auth_type auth_type)
13206{
13207 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13208 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13209
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013210 /*set authentication type */
13211 switch (auth_type) {
13212 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013213 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013214 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13215 break;
13216
13217 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013218 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013219 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013220 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13221 break;
13222
13223 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013224 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013225 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13226 break;
13227#ifdef FEATURE_WLAN_ESE
13228 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013229 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13231 break;
13232#endif
13233
13234 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013235 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013236 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13237 return -EINVAL;
13238 }
13239
13240 pWextState->roamProfile.AuthType.authType[0] =
13241 pHddStaCtx->conn_info.authType;
13242 return 0;
13243}
13244
13245/**
13246 * wlan_hdd_set_akm_suite() - set key management type
13247 * @pAdapter: Pointer to adapter
13248 * @key_mgmt: Key management type
13249 *
13250 * This function is used to set the key mgmt type(PSK/8021x).
13251 *
13252 * Return: 0 for success, non-zero for failure
13253 */
13254static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13255{
13256 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13259#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13260 /*set key mgmt type */
13261 switch (key_mgmt) {
13262 case WLAN_AKM_SUITE_PSK:
13263 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013264 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013265 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013266 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13267 break;
13268
13269 case WLAN_AKM_SUITE_8021X_SHA256:
13270 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013272 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013273 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13274 break;
13275#ifdef FEATURE_WLAN_ESE
13276#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13277#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13278 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013279 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013280 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13281 break;
13282#endif
13283#ifndef WLAN_AKM_SUITE_OSEN
13284#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13285#endif
13286 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013287 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013288 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13289 break;
13290
13291 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013292 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013293 return -EINVAL;
13294
13295 }
13296 return 0;
13297}
13298
13299/**
13300 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13301 * @pAdapter: Pointer to adapter
13302 * @cipher: Cipher type
13303 * @ucast: Unicast flag
13304 *
13305 * This function is used to set the encryption type
13306 * (NONE/WEP40/WEP104/TKIP/CCMP).
13307 *
13308 * Return: 0 for success, non-zero for failure
13309 */
13310static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13311 u32 cipher, bool ucast)
13312{
13313 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13314 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13315 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013317 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013318 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013319 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13320 } else {
13321
13322 /*set encryption method */
13323 switch (cipher) {
13324 case IW_AUTH_CIPHER_NONE:
13325 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13326 break;
13327
13328 case WLAN_CIPHER_SUITE_WEP40:
13329 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13330 break;
13331
13332 case WLAN_CIPHER_SUITE_WEP104:
13333 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13334 break;
13335
13336 case WLAN_CIPHER_SUITE_TKIP:
13337 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13338 break;
13339
13340 case WLAN_CIPHER_SUITE_CCMP:
13341 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13342 break;
13343#ifdef FEATURE_WLAN_WAPI
13344 case WLAN_CIPHER_SUITE_SMS4:
13345 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13346 break;
13347#endif
13348
13349#ifdef FEATURE_WLAN_ESE
13350 case WLAN_CIPHER_SUITE_KRK:
13351 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13352 break;
13353#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13354 case WLAN_CIPHER_SUITE_BTK:
13355 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13356 break;
13357#endif
13358#endif
13359 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013360 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013361 return -EOPNOTSUPP;
13362 }
13363 }
13364
13365 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013366 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013367 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13368 pWextState->roamProfile.EncryptionType.numEntries = 1;
13369 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13370 encryptionType;
13371 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013372 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013373 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13374 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13375 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13376 encryptionType;
13377 }
13378
13379 return 0;
13380}
13381
13382/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013383 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13384 * @wext_state: Pointer to wext state
13385 * @gen_ie: Pointer to IE data
13386 * @len: length of IE data
13387 *
13388 * Return: 0 for success, non-zero for failure
13389 */
13390static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13391 const uint8_t *gen_ie, uint16_t len)
13392{
13393 uint16_t cur_add_ie_len =
13394 wext_state->assocAddIE.length;
13395
13396 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13397 (wext_state->assocAddIE.length + len)) {
13398 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13399 QDF_ASSERT(0);
13400 return -ENOMEM;
13401 }
13402 memcpy(wext_state->assocAddIE.addIEdata +
13403 cur_add_ie_len, gen_ie, len);
13404 wext_state->assocAddIE.length += len;
13405
13406 wext_state->roamProfile.pAddIEAssoc =
13407 wext_state->assocAddIE.addIEdata;
13408 wext_state->roamProfile.nAddIEAssocLength =
13409 wext_state->assocAddIE.length;
13410 return 0;
13411}
13412
13413/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414 * wlan_hdd_cfg80211_set_ie() - set IEs
13415 * @pAdapter: Pointer to adapter
13416 * @ie: Pointer ot ie
13417 * @ie: IE length
13418 *
13419 * Return: 0 for success, non-zero for failure
13420 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013421static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013422 size_t ie_len)
13423{
13424 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13425 const uint8_t *genie = ie;
13426 uint16_t remLen = ie_len;
13427#ifdef FEATURE_WLAN_WAPI
13428 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13429 u16 *tmp;
13430 uint16_t akmsuiteCount;
13431 int *akmlist;
13432#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013433 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013434
13435 /* clear previous assocAddIE */
13436 pWextState->assocAddIE.length = 0;
13437 pWextState->roamProfile.bWPSAssociation = false;
13438 pWextState->roamProfile.bOSENAssociation = false;
13439
13440 while (remLen >= 2) {
13441 uint16_t eLen = 0;
13442 uint8_t elementId;
13443 elementId = *genie++;
13444 eLen = *genie++;
13445 remLen -= 2;
13446
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013447 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448
13449 switch (elementId) {
13450 case DOT11F_EID_WPA:
13451 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 -070013452 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013453 return -EINVAL;
13454 } else if (0 ==
13455 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13456 uint16_t curAddIELen =
13457 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013458 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459
13460 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13461 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013462 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013463 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464 return -ENOMEM;
13465 }
13466 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13467 memcpy(pWextState->assocAddIE.addIEdata +
13468 curAddIELen, genie - 2, eLen + 2);
13469 pWextState->assocAddIE.length += eLen + 2;
13470
13471 pWextState->roamProfile.bWPSAssociation = true;
13472 pWextState->roamProfile.pAddIEAssoc =
13473 pWextState->assocAddIE.addIEdata;
13474 pWextState->roamProfile.nAddIEAssocLength =
13475 pWextState->assocAddIE.length;
13476 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013477 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013478 memset(pWextState->WPARSNIE, 0,
13479 MAX_WPA_RSN_IE_LEN);
13480 memcpy(pWextState->WPARSNIE, genie - 2,
13481 (eLen + 2));
13482 pWextState->roamProfile.pWPAReqIE =
13483 pWextState->WPARSNIE;
13484 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13485 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13486 P2P_OUI_TYPE_SIZE))) {
13487 uint16_t curAddIELen =
13488 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013489 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013490
13491 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13492 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013493 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013494 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013495 return -ENOMEM;
13496 }
13497 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13498 memcpy(pWextState->assocAddIE.addIEdata +
13499 curAddIELen, genie - 2, eLen + 2);
13500 pWextState->assocAddIE.length += eLen + 2;
13501
13502 pWextState->roamProfile.pAddIEAssoc =
13503 pWextState->assocAddIE.addIEdata;
13504 pWextState->roamProfile.nAddIEAssocLength =
13505 pWextState->assocAddIE.length;
13506 }
13507#ifdef WLAN_FEATURE_WFD
13508 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13509 WFD_OUI_TYPE_SIZE)) &&
13510 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013511 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013512 pAdapter->device_mode)) {
13513 uint16_t curAddIELen =
13514 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013515 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013516
13517 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13518 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013519 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013520 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013521 return -ENOMEM;
13522 }
13523 /* WFD IE is saved to Additional IE ; it should
13524 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013525 * WFD IE
13526 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 memcpy(pWextState->assocAddIE.addIEdata +
13528 curAddIELen, genie - 2, eLen + 2);
13529 pWextState->assocAddIE.length += eLen + 2;
13530
13531 pWextState->roamProfile.pAddIEAssoc =
13532 pWextState->assocAddIE.addIEdata;
13533 pWextState->roamProfile.nAddIEAssocLength =
13534 pWextState->assocAddIE.length;
13535 }
13536#endif
13537 /* Appending HS 2.0 Indication Element in Assiciation Request */
13538 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13539 HS20_OUI_TYPE_SIZE))) {
13540 uint16_t curAddIELen =
13541 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013542 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013543
13544 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13545 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013546 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013547 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013548 return -ENOMEM;
13549 }
13550 memcpy(pWextState->assocAddIE.addIEdata +
13551 curAddIELen, genie - 2, eLen + 2);
13552 pWextState->assocAddIE.length += eLen + 2;
13553
13554 pWextState->roamProfile.pAddIEAssoc =
13555 pWextState->assocAddIE.addIEdata;
13556 pWextState->roamProfile.nAddIEAssocLength =
13557 pWextState->assocAddIE.length;
13558 }
13559 /* Appending OSEN Information Element in Assiciation Request */
13560 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13561 OSEN_OUI_TYPE_SIZE))) {
13562 uint16_t curAddIELen =
13563 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013564 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565
13566 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13567 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013568 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013569 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013570 return -ENOMEM;
13571 }
13572 memcpy(pWextState->assocAddIE.addIEdata +
13573 curAddIELen, genie - 2, eLen + 2);
13574 pWextState->assocAddIE.length += eLen + 2;
13575
13576 pWextState->roamProfile.bOSENAssociation = true;
13577 pWextState->roamProfile.pAddIEAssoc =
13578 pWextState->assocAddIE.addIEdata;
13579 pWextState->roamProfile.nAddIEAssocLength =
13580 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013581 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13582 MBO_OUI_TYPE_SIZE))){
13583 hdd_info("Set MBO IE(len %d)", eLen + 2);
13584 status = wlan_hdd_add_assoc_ie(pWextState,
13585 genie - 2, eLen + 2);
13586 if (status)
13587 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 } else {
13589 uint16_t add_ie_len =
13590 pWextState->assocAddIE.length;
13591
13592 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13593
13594 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13595 (pWextState->assocAddIE.length + eLen)) {
13596 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013597 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598 return -ENOMEM;
13599 }
13600
13601 memcpy(pWextState->assocAddIE.addIEdata +
13602 add_ie_len, genie - 2, eLen + 2);
13603 pWextState->assocAddIE.length += eLen + 2;
13604
13605 pWextState->roamProfile.pAddIEAssoc =
13606 pWextState->assocAddIE.addIEdata;
13607 pWextState->roamProfile.nAddIEAssocLength =
13608 pWextState->assocAddIE.length;
13609 }
13610 break;
13611 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013612 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013613 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13614 memcpy(pWextState->WPARSNIE, genie - 2,
13615 (eLen + 2));
13616 pWextState->roamProfile.pRSNReqIE =
13617 pWextState->WPARSNIE;
13618 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13619 break;
13620 /*
13621 * Appending Extended Capabilities with Interworking bit set
13622 * in Assoc Req.
13623 *
13624 * In assoc req this EXT Cap will only be taken into account if
13625 * interworkingService bit is set to 1. Currently
13626 * driver is only interested in interworkingService capability
13627 * from supplicant. If in future any other EXT Cap info is
13628 * required from supplicat, it needs to be handled while
13629 * sending Assoc Req in LIM.
13630 */
13631 case DOT11F_EID_EXTCAP:
13632 {
13633 uint16_t curAddIELen =
13634 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013635 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013636
13637 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13638 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013639 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013640 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013641 return -ENOMEM;
13642 }
13643 memcpy(pWextState->assocAddIE.addIEdata +
13644 curAddIELen, genie - 2, eLen + 2);
13645 pWextState->assocAddIE.length += eLen + 2;
13646
13647 pWextState->roamProfile.pAddIEAssoc =
13648 pWextState->assocAddIE.addIEdata;
13649 pWextState->roamProfile.nAddIEAssocLength =
13650 pWextState->assocAddIE.length;
13651 break;
13652 }
13653#ifdef FEATURE_WLAN_WAPI
13654 case WLAN_EID_WAPI:
13655 /* Setting WAPI Mode to ON=1 */
13656 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013657 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013658 tmp = (u16 *) ie;
13659 tmp = tmp + 2; /* Skip element Id and Len, Version */
13660 akmsuiteCount = WPA_GET_LE16(tmp);
13661 tmp = tmp + 1;
13662 akmlist = (int *)(tmp);
13663 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13664 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13665 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013666 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013667 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013668 return -EINVAL;
13669 }
13670
13671 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013672 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013673 pAdapter->wapi_info.wapiAuthMode =
13674 WAPI_AUTH_MODE_PSK;
13675 }
13676 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013677 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013678 pAdapter->wapi_info.wapiAuthMode =
13679 WAPI_AUTH_MODE_CERT;
13680 }
13681 break;
13682#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013683 case DOT11F_EID_SUPPOPERATINGCLASSES:
13684 {
13685 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13686 status = wlan_hdd_add_assoc_ie(pWextState,
13687 genie - 2, eLen + 2);
13688 if (status)
13689 return status;
13690 break;
13691 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013692 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013693 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013694 /* when Unknown IE is received we break
13695 * and continue to the next IE in the buffer
13696 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013697 break;
13698 }
13699 genie += eLen;
13700 remLen -= eLen;
13701 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 return 0;
13703}
13704
13705/**
13706 * hdd_is_wpaie_present() - check for WPA ie
13707 * @ie: Pointer to ie
13708 * @ie_len: Ie length
13709 *
13710 * Parse the received IE to find the WPA IE
13711 *
13712 * Return: true if wpa ie is found else false
13713 */
13714static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13715{
13716 uint8_t eLen = 0;
13717 uint16_t remLen = ie_len;
13718 uint8_t elementId = 0;
13719
13720 while (remLen >= 2) {
13721 elementId = *ie++;
13722 eLen = *ie++;
13723 remLen -= 2;
13724 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013725 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 return false;
13727 }
13728 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13729 /* OUI - 0x00 0X50 0XF2
13730 * WPA Information Element - 0x01
13731 * WPA version - 0x01
13732 */
13733 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13734 return true;
13735 }
13736 ie += eLen;
13737 remLen -= eLen;
13738 }
13739 return false;
13740}
13741
13742/**
13743 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13744 * @pAdapter: Pointer to adapter
13745 * @req: Pointer to security parameters
13746 *
13747 * Return: 0 for success, non-zero for failure
13748 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013749static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13750 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013751{
13752 int status = 0;
13753 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13754 ENTER();
13755
13756 /*set wpa version */
13757 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13758
13759 if (req->crypto.wpa_versions) {
13760 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13761 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13762 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13763 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13764 }
13765 }
13766
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013767 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013768
13769 /*set authentication type */
13770 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13771
13772 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013773 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013774 return status;
13775 }
13776
13777 /*set key mgmt type */
13778 if (req->crypto.n_akm_suites) {
13779 status =
13780 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13781 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013782 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013783 return status;
13784 }
13785 }
13786
13787 /*set pairwise cipher type */
13788 if (req->crypto.n_ciphers_pairwise) {
13789 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13790 req->crypto.
13791 ciphers_pairwise[0],
13792 true);
13793 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013794 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013795 return status;
13796 }
13797 } else {
13798 /*Reset previous cipher suite to none */
13799 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13800 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013801 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013802 return status;
13803 }
13804 }
13805
13806 /*set group cipher type */
13807 status =
13808 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13809 false);
13810
13811 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013812 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013813 return status;
13814 }
13815#ifdef WLAN_FEATURE_11W
13816 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13817#endif
13818
13819 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13820 if (req->ie_len) {
13821 status =
13822 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13823 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013824 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013825 return status;
13826 }
13827 }
13828
13829 /*incase of WEP set default key information */
13830 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013831 u8 key_len = req->key_len;
13832 u8 key_idx = req->key_idx;
13833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13835 || (WLAN_CIPHER_SUITE_WEP104 ==
13836 req->crypto.ciphers_pairwise[0])
13837 ) {
13838 if (IW_AUTH_KEY_MGMT_802_1X
13839 ==
13840 (pWextState->
13841 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013842 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013843 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013844 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013845
Jeff Johnson68755312017-02-10 11:46:55 -080013846 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13847 && (CSR_MAX_NUM_KEY > key_idx)) {
13848 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13849 key_idx, key_len);
13850 qdf_mem_copy(&pWextState->roamProfile.
13851 Keys.
13852 KeyMaterial[key_idx][0],
13853 req->key, key_len);
13854 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013856 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013857 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013858 }
13859 }
13860 }
13861
13862 return status;
13863}
13864
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013865int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013866{
13867 unsigned long rc;
13868 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013869 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013870
13871 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13872
Jeff Johnson9edf9572016-10-03 15:24:49 -070013873 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013874 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13875 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13876 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013877 hdd_conn_set_connection_state(pAdapter,
13878 eConnectionState_Disconnecting);
13879 /* Issue disconnect to CSR */
13880 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013881
13882 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13883 pAdapter->sessionId,
13884 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13885 /*
13886 * Wait here instead of returning directly, this will block the
13887 * next connect command and allow processing of the scan for
13888 * ssid and the previous connect command in CSR. Else we might
13889 * hit some race conditions leading to SME and HDD out of sync.
13890 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013891 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013892 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13893 } else if (0 != status) {
13894 hdd_err("csrRoamDisconnect failure, returned %d",
13895 (int)status);
13896 pHddStaCtx->staDebugState = status;
13897 result = -EINVAL;
13898 goto disconnected;
13899 }
13900
13901 rc = wait_for_completion_timeout(
13902 &pAdapter->disconnect_comp_var,
13903 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013904 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013905 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13906 pAdapter->sessionId, pHddStaCtx->staDebugState);
13907 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908 }
13909 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013910 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013912 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013913 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013914 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013915 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013916 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917 }
13918 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013919disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013920 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13921 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922}
13923
13924/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013925 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13926 * @adapter: Pointer to the HDD adapter
13927 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013928 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013929 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013930 * This function will start reassociation if prev_bssid is set and bssid/
13931 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013932 *
Naveen Rawat07332902016-07-27 09:13:17 -070013933 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013934 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013935#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13936 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013937static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13938 struct cfg80211_connect_params *req,
13939 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013940{
Naveen Rawat07332902016-07-27 09:13:17 -070013941 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013942 const uint8_t *bssid = NULL;
13943 uint16_t channel = 0;
13944
13945 if (req->bssid)
13946 bssid = req->bssid;
13947 else if (req->bssid_hint)
13948 bssid = req->bssid_hint;
13949
13950 if (req->channel)
13951 channel = req->channel->hw_value;
13952 else if (req->channel_hint)
13953 channel = req->channel_hint->hw_value;
13954
13955 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013956 reassoc = true;
13957 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013958 channel, MAC_ADDR_ARRAY(bssid));
13959 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013960 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013961 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013962 }
Naveen Rawat07332902016-07-27 09:13:17 -070013963 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013964}
13965#else
Naveen Rawat07332902016-07-27 09:13:17 -070013966static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13967 struct cfg80211_connect_params *req,
13968 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013969{
Naveen Rawat07332902016-07-27 09:13:17 -070013970 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013971}
13972#endif
13973
13974/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13976 * @wiphy: Pointer to wiphy
13977 * @dev: Pointer to network device
13978 * @req: Pointer to cfg80211 connect request
13979 *
13980 * This function is used to start the association process
13981 *
13982 * Return: 0 for success, non-zero for failure
13983 */
13984static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13985 struct net_device *ndev,
13986 struct cfg80211_connect_params *req)
13987{
13988 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013989 u16 channel;
13990#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13991 const u8 *bssid_hint = req->bssid_hint;
13992#else
13993 const u8 *bssid_hint = NULL;
13994#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13996 hdd_context_t *pHddCtx;
13997
13998 ENTER();
13999
Anurag Chouhan6d760662016-02-20 16:05:43 +053014000 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014001 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014002 return -EINVAL;
14003 }
14004
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014005 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14006 hdd_err("invalid session id: %d", pAdapter->sessionId);
14007 return -EINVAL;
14008 }
14009
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014010 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 TRACE_CODE_HDD_CFG80211_CONNECT,
14012 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014013 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014014 hdd_device_mode_to_string(pAdapter->device_mode),
14015 pAdapter->device_mode);
14016
Krunal Sonib4326f22016-03-10 13:05:51 -080014017 if (pAdapter->device_mode != QDF_STA_MODE &&
14018 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014019 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020 hdd_device_mode_to_string(pAdapter->device_mode),
14021 pAdapter->device_mode);
14022 return -EINVAL;
14023 }
14024
14025 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14026 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014027 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 return -EINVAL;
14029 }
14030
14031 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014032 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014034
Naveen Rawat07332902016-07-27 09:13:17 -070014035 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014036 return status;
14037
Agrawal Ashishf156e942016-08-04 14:54:47 +053014038 /* Try disconnecting if already in connected state */
14039 status = wlan_hdd_try_disconnect(pAdapter);
14040 if (0 > status) {
14041 hdd_err("Failed to disconnect the existing connection");
14042 return -EALREADY;
14043 }
14044
14045 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014047 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014048 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014049 pAdapter->device_mode),
14050 req->channel->hw_value, HW_MODE_20_MHZ)) {
14051 hdd_err("This concurrency combination is not allowed");
14052 return -ECONNREFUSED;
14053 }
14054 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014055 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014056 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014057 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14058 hdd_err("This concurrency combination is not allowed");
14059 return -ECONNREFUSED;
14060 }
14061 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014062
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014063 /*initialise security parameters */
14064 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14065
14066 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014067 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068 return status;
14069 }
14070
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014071 if (req->channel)
14072 channel = req->channel->hw_value;
14073 else
14074 channel = 0;
14075 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14076 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014077 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014078 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014079 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014080 return status;
14081 }
14082 EXIT();
14083 return status;
14084}
14085
14086/**
14087 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14088 * @wiphy: Pointer to wiphy
14089 * @dev: Pointer to network device
14090 * @req: Pointer to cfg80211 connect request
14091 *
14092 * Return: 0 for success, non-zero for failure
14093 */
14094static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14095 struct net_device *ndev,
14096 struct cfg80211_connect_params *req)
14097{
14098 int ret;
14099 cds_ssr_protect(__func__);
14100 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14101 cds_ssr_unprotect(__func__);
14102
14103 return ret;
14104}
14105
14106/**
14107 * wlan_hdd_disconnect() - hdd disconnect api
14108 * @pAdapter: Pointer to adapter
14109 * @reason: Disconnect reason code
14110 *
14111 * This function is used to issue a disconnect request to SME
14112 *
14113 * Return: 0 for success, non-zero for failure
14114 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014115static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014116{
14117 int status, result = 0;
14118 unsigned long rc;
14119 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14120 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014121 eConnectionState prev_conn_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014122
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014123 ENTER();
14124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014125 status = wlan_hdd_validate_context(pHddCtx);
14126
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014127 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014128 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014129
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014130 prev_conn_state = pHddStaCtx->conn_info.connState;
14131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014132 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014133 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
14135 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014136 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014137 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14138 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14139
14140 /*issue disconnect */
14141
14142 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14143 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014144 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14145 prev_conn_state != eConnectionState_Connecting) {
14146 hdd_notice("status = %d, already disconnected", status);
14147 result = 0;
14148 goto disconnected;
14149 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14150 /*
14151 * Wait here instead of returning directly, this will block the
14152 * next connect command and allow processing of the scan for
14153 * ssid and the previous connect command in CSR. Else we might
14154 * hit some race conditions leading to SME and HDD out of sync.
14155 */
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014156 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014157 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014158 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 (int)status);
14160 pHddStaCtx->staDebugState = status;
14161 result = -EINVAL;
14162 goto disconnected;
14163 }
14164 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14165 msecs_to_jiffies
14166 (WLAN_WAIT_TIME_DISCONNECT));
14167
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014168 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014169 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170 result = -ETIMEDOUT;
14171 }
14172disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014173 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14174#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14175 /* Sending disconnect event to userspace for kernel version < 3.11
14176 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14177 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014178 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014179 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14180 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181#endif
14182
14183 return result;
14184}
14185
14186/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014187 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14188 * @reason: ieee80211 reason code.
14189 *
14190 * This utility function helps log string conversion of reason code.
14191 *
14192 * Return: string conversion of reason code, if match found;
14193 * "Unknown" otherwise.
14194 */
14195static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14196{
14197 switch (reason) {
14198 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14199 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14200 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14201 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14202 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14203 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14204 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14205 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14206 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14207 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14208 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14209 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14210 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14211 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14212 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14213 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14214 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14215 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14216 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14217 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14218 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14219 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14220 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14221 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14222 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14223 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14224 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14225 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14226 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14227 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14228 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14229 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14230 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14231 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14232 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14233 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14234 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14235 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14236 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14237 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14238 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14239 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14240 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14241 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14242 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14243 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14244 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14245 default:
14246 return "Unknown";
14247 }
14248}
14249
14250/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014251 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14252 * @wiphy: Pointer to wiphy
14253 * @dev: Pointer to network device
14254 * @reason: Disconnect reason code
14255 *
14256 * This function is used to issue a disconnect request to SME
14257 *
14258 * Return: 0 for success, non-zero for failure
14259 */
14260static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14261 struct net_device *dev, u16 reason)
14262{
14263 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14264 int status;
14265 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14266 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14267#ifdef FEATURE_WLAN_TDLS
14268 uint8_t staIdx;
14269#endif
14270
14271 ENTER();
14272
Anurag Chouhan6d760662016-02-20 16:05:43 +053014273 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014274 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014275 return -EINVAL;
14276 }
14277
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014278 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14279 hdd_err("invalid session id: %d", pAdapter->sessionId);
14280 return -EINVAL;
14281 }
14282
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014283 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014284 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14285 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014286 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287 hdd_device_mode_to_string(pAdapter->device_mode),
14288 pAdapter->device_mode, reason);
14289
14290 status = wlan_hdd_validate_context(pHddCtx);
14291
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080014292 if (hdd_is_roaming_in_progress()) {
14293 hdd_err("Roaming In Progress. Ignore!!!");
14294 return -EAGAIN;
14295 }
14296
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014297 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014298 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299
14300 /* Issue disconnect request to SME, if station is in connected state */
14301 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14302 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14303 eCsrRoamDisconnectReason reasonCode =
14304 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14305 hdd_scaninfo_t *pScanInfo;
14306
14307 switch (reason) {
14308 case WLAN_REASON_MIC_FAILURE:
14309 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14310 break;
14311
14312 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14313 case WLAN_REASON_DISASSOC_AP_BUSY:
14314 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14315 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14316 break;
14317
14318 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14319 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14320 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14321 break;
14322
14323 case WLAN_REASON_DEAUTH_LEAVING:
14324 reasonCode =
14325 pHddCtx->config->
14326 gEnableDeauthToDisassocMap ?
14327 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14328 eCSR_DISCONNECT_REASON_DEAUTH;
14329 break;
14330 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14331 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14332 break;
14333 default:
14334 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14335 break;
14336 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014337 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014338 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339 pScanInfo = &pAdapter->scan_info;
14340 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014341 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014343 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 eCSR_SCAN_ABORT_DEFAULT);
14345 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014346 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347#ifdef FEATURE_WLAN_TDLS
14348 /* First clean up the tdls peers if any */
14349 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14350 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14351 pAdapter->sessionId)
14352 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14353 uint8_t *mac;
14354 mac =
14355 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014356 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14357 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014358 pHddCtx->tdlsConnInfo[staIdx].staId,
14359 pAdapter->sessionId,
14360 MAC_ADDR_ARRAY(mac));
14361 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14362 (pAdapter),
14363 pAdapter->sessionId, mac);
14364 }
14365 }
14366#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014367 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014368 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014369 hdd_info("Disconnect request from user space with reason: %s",
14370 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014371 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14372 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014373 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014374 return -EINVAL;
14375 }
14376 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014377 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014378 pHddStaCtx->conn_info.connState);
14379 }
14380
14381 return status;
14382}
14383
14384/**
14385 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14386 * @wiphy: Pointer to wiphy
14387 * @dev: Pointer to network device
14388 * @reason: Disconnect reason code
14389 *
14390 * Return: 0 for success, non-zero for failure
14391 */
14392static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14393 struct net_device *dev, u16 reason)
14394{
14395 int ret;
14396 cds_ssr_protect(__func__);
14397 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14398 cds_ssr_unprotect(__func__);
14399
14400 return ret;
14401}
14402
14403/**
14404 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14405 * @pAdapter: Pointer to adapter
14406 * @param: Pointer to IBSS parameters
14407 *
14408 * This function is used to initialize the security settings in IBSS mode
14409 *
14410 * Return: 0 for success, non-zero for failure
14411 */
14412static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14413 struct cfg80211_ibss_params
14414 *params)
14415{
14416 int status = 0;
14417 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14418 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14419 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14420
14421 ENTER();
14422
14423 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014424 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014425 pHddStaCtx->ibss_enc_key_installed = 0;
14426
14427 if (params->ie_len && (NULL != params->ie)) {
14428 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14429 params->ie_len, WLAN_EID_RSN)) {
14430 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14431 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14432 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14433 tDot11fIEWPA dot11WPAIE;
14434 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14435 u8 *ie;
14436
14437 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14438 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14439 params->ie_len,
14440 DOT11F_EID_WPA);
14441 if (NULL != ie) {
14442 pWextState->wpaVersion =
14443 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014444 /* Unpack the WPA IE
14445 * Skip past the EID byte and length byte
14446 * and four byte WiFi OUI
14447 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014448 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14449 &ie[2 + 4],
14450 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014451 /* Extract the multicast cipher, the
14452 * encType for unicast cipher for
14453 * wpa-none is none
14454 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014455 encryptionType =
14456 hdd_translate_wpa_to_csr_encryption_type
14457 (dot11WPAIE.multicast_cipher);
14458 }
14459 }
14460
14461 status =
14462 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14463 params->ie_len);
14464
14465 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014466 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467 return status;
14468 }
14469 }
14470
14471 pWextState->roamProfile.AuthType.authType[0] =
14472 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14473
14474 if (params->privacy) {
14475 /* Security enabled IBSS, At this time there is no information
14476 * available about the security paramters, so initialise the
14477 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14478 * The correct security parameters will be updated later in
14479 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14480 * set inorder enable privacy bit in beacons
14481 */
14482
14483 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14484 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014485 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14487 pWextState->roamProfile.EncryptionType.numEntries = 1;
14488 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14489 encryptionType;
14490 return status;
14491}
14492
14493/**
14494 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14495 * @wiphy: Pointer to wiphy
14496 * @dev: Pointer to network device
14497 * @param: Pointer to IBSS join parameters
14498 *
14499 * This function is used to create/join an IBSS network
14500 *
14501 * Return: 0 for success, non-zero for failure
14502 */
14503static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14504 struct net_device *dev,
14505 struct cfg80211_ibss_params *params)
14506{
14507 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14508 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14509 tCsrRoamProfile *pRoamProfile;
14510 int status;
14511 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14512 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014513 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515
14516 ENTER();
14517
Anurag Chouhan6d760662016-02-20 16:05:43 +053014518 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014519 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520 return -EINVAL;
14521 }
14522
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014523 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14524 hdd_err("invalid session id: %d", pAdapter->sessionId);
14525 return -EINVAL;
14526 }
14527
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014528 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014529 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14530 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014531 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014532 hdd_device_mode_to_string(pAdapter->device_mode),
14533 pAdapter->device_mode);
14534
14535 status = wlan_hdd_validate_context(pHddCtx);
14536
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014537 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014539
14540 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014541 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014542 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14543 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14544 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14545 int indx;
14546
14547 /* Get channel number */
14548 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014549 params->
14550 chandef.
14551 chan->
14552 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014553
14554 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14555 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014556 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014557 return -EOPNOTSUPP;
14558 }
14559
14560 for (indx = 0; indx < numChans; indx++) {
14561 if (channelNum == validChan[indx]) {
14562 break;
14563 }
14564 }
14565 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014566 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 return -EINVAL;
14568 }
14569 }
14570
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014571 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 HW_MODE_20_MHZ)) {
14573 hdd_err("This concurrency combination is not allowed");
14574 return -ECONNREFUSED;
14575 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014576
Krunal Soni3091bcc2016-06-23 12:28:21 -070014577 status = qdf_reset_connection_update();
14578 if (!QDF_IS_STATUS_SUCCESS(status))
14579 hdd_err("ERR: clear event failed");
14580
14581 status = cds_current_connections_update(pAdapter->sessionId,
14582 channelNum,
14583 SIR_UPDATE_REASON_JOIN_IBSS);
14584 if (QDF_STATUS_E_FAILURE == status) {
14585 hdd_err("ERROR: connections update failed!!");
14586 return -EINVAL;
14587 }
14588
14589 if (QDF_STATUS_SUCCESS == status) {
14590 status = qdf_wait_for_connection_update();
14591 if (!QDF_IS_STATUS_SUCCESS(status)) {
14592 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014593 return -EINVAL;
14594 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014595 }
14596
14597 /*Try disconnecting if already in connected state */
14598 status = wlan_hdd_try_disconnect(pAdapter);
14599 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014600 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014601 return -EALREADY;
14602 }
14603
14604 pRoamProfile = &pWextState->roamProfile;
14605
14606 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014607 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 return -EINVAL;
14609 }
14610
14611 /* enable selected protection checks in IBSS mode */
14612 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14613
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014614 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14616 pHddCtx->config->
14617 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014618 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014619 }
14620
14621 /* BSSID is provided by upper layers hence no need to AUTO generate */
14622 if (NULL != params->bssid) {
14623 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014624 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014625 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014626 return -EIO;
14627 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014628 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014629 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14630 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014631 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014632 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014633 return -EIO;
14634 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014635 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014636 }
14637 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14638 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14639 pRoamProfile->beaconInterval = params->beacon_interval;
14640 else {
14641 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014642 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014643 params->beacon_interval, pRoamProfile->beaconInterval);
14644 }
14645
14646 /* Set Channel */
14647 if (channelNum) {
14648 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014649 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014650 pRoamProfile->ChannelInfo.numOfChannels = 1;
14651 pHddStaCtx->conn_info.operationChannel = channelNum;
14652 pRoamProfile->ChannelInfo.ChannelList =
14653 &pHddStaCtx->conn_info.operationChannel;
14654 }
14655
14656 /* Initialize security parameters */
14657 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14658 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014659 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014660 return status;
14661 }
14662
14663 /* Issue connect start */
14664 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14665 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014666 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014667 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014668 operationChannel,
14669 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014670
14671 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014672 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014673 return status;
14674 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014675 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014676 return 0;
14677}
14678
14679/**
14680 * wlan_hdd_cfg80211_join_ibss() - join ibss
14681 * @wiphy: Pointer to wiphy
14682 * @dev: Pointer to network device
14683 * @param: Pointer to IBSS join parameters
14684 *
14685 * This function is used to create/join an IBSS network
14686 *
14687 * Return: 0 for success, non-zero for failure
14688 */
14689static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14690 struct net_device *dev,
14691 struct cfg80211_ibss_params *params)
14692{
14693 int ret = 0;
14694
14695 cds_ssr_protect(__func__);
14696 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14697 cds_ssr_unprotect(__func__);
14698
14699 return ret;
14700}
14701
14702/**
14703 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14704 * @wiphy: Pointer to wiphy
14705 * @dev: Pointer to network device
14706 *
14707 * This function is used to leave an IBSS network
14708 *
14709 * Return: 0 for success, non-zero for failure
14710 */
14711static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14712 struct net_device *dev)
14713{
14714 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14715 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14716 tCsrRoamProfile *pRoamProfile;
14717 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14718 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014719 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014720 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014721 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722
14723 ENTER();
14724
Anurag Chouhan6d760662016-02-20 16:05:43 +053014725 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014726 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014727 return -EINVAL;
14728 }
14729
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014730 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14731 hdd_err("invalid session id: %d", pAdapter->sessionId);
14732 return -EINVAL;
14733 }
14734
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014735 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14737 pAdapter->sessionId,
14738 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14739 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014740 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014741 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014742
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014743 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014744 hdd_device_mode_to_string(pAdapter->device_mode),
14745 pAdapter->device_mode);
14746 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014747 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748 return -EIO;
14749 }
14750
14751 pRoamProfile = &pWextState->roamProfile;
14752
14753 /* Issue disconnect only if interface type is set to IBSS */
14754 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014755 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014756 return -EINVAL;
14757 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014758 /* Clearing add IE of beacon */
14759 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14760 sizeof(tSirMacAddr));
14761 updateIE.smeSessionId = pAdapter->sessionId;
14762 updateIE.ieBufferlength = 0;
14763 updateIE.pAdditionIEBuffer = NULL;
14764 updateIE.append = true;
14765 updateIE.notify = true;
14766 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14767 &updateIE,
14768 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014769 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014770 }
14771
14772 /* Reset WNI_CFG_PROBE_RSP Flags */
14773 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014774
14775 /* Issue Disconnect request */
14776 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14777 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14778 pAdapter->sessionId,
14779 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014780 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014781 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014782 hal_status);
14783 return -EAGAIN;
14784 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014785
14786 /* wait for mc thread to cleanup and then return to upper stack
14787 * so by the time upper layer calls the change interface, we are
14788 * all set to proceed further
14789 */
14790 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14791 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14792 if (!rc) {
14793 hdd_err("Failed to disconnect, timed out");
14794 return -ETIMEDOUT;
14795 }
14796
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014797 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 return 0;
14799}
14800
14801/**
14802 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14803 * @wiphy: Pointer to wiphy
14804 * @dev: Pointer to network device
14805 *
14806 * This function is used to leave an IBSS network
14807 *
14808 * Return: 0 for success, non-zero for failure
14809 */
14810static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14811 struct net_device *dev)
14812{
14813 int ret = 0;
14814
14815 cds_ssr_protect(__func__);
14816 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14817 cds_ssr_unprotect(__func__);
14818
14819 return ret;
14820}
14821
14822/**
14823 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14824 * @wiphy: Pointer to wiphy
14825 * @changed: Parameters changed
14826 *
14827 * This function is used to set the phy parameters. RTS Threshold/FRAG
14828 * Threshold/Retry Count etc.
14829 *
14830 * Return: 0 for success, non-zero for failure
14831 */
14832static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14833 u32 changed)
14834{
14835 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14836 tHalHandle hHal = pHddCtx->hHal;
14837 int status;
14838
14839 ENTER();
14840
Anurag Chouhan6d760662016-02-20 16:05:43 +053014841 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014842 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014843 return -EINVAL;
14844 }
14845
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014846 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14848 NO_SESSION, wiphy->rts_threshold));
14849 status = wlan_hdd_validate_context(pHddCtx);
14850
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014851 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853
14854 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14855 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14856 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14857
14858 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14859 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014860 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014861 rts_threshold);
14862 return -EINVAL;
14863 }
14864
14865 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14866 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014867 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014868 rts_threshold);
14869 return -EIO;
14870 }
14871
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014872 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873 }
14874
14875 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14876 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14877 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14878 wiphy->frag_threshold;
14879
14880 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14881 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014882 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 frag_threshold);
14884 return -EINVAL;
14885 }
14886
14887 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14888 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014889 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014890 frag_threshold);
14891 return -EIO;
14892 }
14893
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014894 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014895 }
14896
14897 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14898 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14899 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14900 wiphy->retry_short : wiphy->retry_long;
14901
14902 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14903 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014904 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014905 return -EINVAL;
14906 }
14907
14908 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14909 if (0 != sme_cfg_set_int(hHal,
14910 WNI_CFG_LONG_RETRY_LIMIT,
14911 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014912 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014913 retry_value);
14914 return -EIO;
14915 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014916 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014917 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14918 if (0 != sme_cfg_set_int(hHal,
14919 WNI_CFG_SHORT_RETRY_LIMIT,
14920 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014921 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014922 retry_value);
14923 return -EIO;
14924 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014925 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014926 }
14927 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014928 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014929 return 0;
14930}
14931
14932/**
14933 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14934 * @wiphy: Pointer to wiphy
14935 * @changed: Parameters changed
14936 *
14937 * Return: 0 for success, non-zero for failure
14938 */
14939static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14940{
14941 int ret;
14942
14943 cds_ssr_protect(__func__);
14944 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14945 cds_ssr_unprotect(__func__);
14946
14947 return ret;
14948}
14949
14950/**
14951 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14952 * key
14953 * @wiphy: Pointer to wiphy
14954 * @dev: Pointer to network device
14955 * @key_index: Key index
14956 *
14957 * Return: 0
14958 */
14959static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14960 struct net_device *netdev,
14961 u8 key_index)
14962{
14963 ENTER();
14964 return 0;
14965}
14966
14967/**
14968 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14969 * wlan_hdd_set_default_mgmt_key
14970 * @wiphy: pointer to wiphy
14971 * @netdev: pointer to net_device structure
14972 * @key_index: key index
14973 *
14974 * Return: 0 on success, error number on failure
14975 */
14976static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14977 struct net_device *netdev,
14978 u8 key_index)
14979{
14980 int ret;
14981
14982 cds_ssr_protect(__func__);
14983 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14984 cds_ssr_unprotect(__func__);
14985
14986 return ret;
14987}
14988
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014989/**
14990 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14991 * @wiphy: Pointer to wiphy
14992 * @dev: Pointer to network device
14993 * @params: Pointer to tx queue parameters
14994 *
14995 * Return: 0
14996 */
14997static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14998 struct net_device *dev,
14999 struct ieee80211_txq_params *params)
15000{
15001 ENTER();
15002 return 0;
15003}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015004
15005/**
15006 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15007 * @wiphy: pointer to wiphy
15008 * @netdev: pointer to net_device structure
15009 * @params: pointer to ieee80211_txq_params
15010 *
15011 * Return: 0 on success, error number on failure
15012 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015013static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15014 struct net_device *dev,
15015 struct ieee80211_txq_params *params)
15016{
15017 int ret;
15018
15019 cds_ssr_protect(__func__);
15020 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15021 cds_ssr_unprotect(__func__);
15022
15023 return ret;
15024}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025
15026/**
15027 * __wlan_hdd_cfg80211_del_station() - delete station v2
15028 * @wiphy: Pointer to wiphy
15029 * @param: Pointer to delete station parameter
15030 *
15031 * Return: 0 for success, non-zero for failure
15032 */
15033static
15034int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15035 struct net_device *dev,
15036 struct tagCsrDelStaParams *pDelStaParams)
15037{
15038 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15039 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015040 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015041 hdd_hostapd_state_t *hapd_state;
15042 int status;
15043 uint8_t staId;
15044 uint8_t *mac;
15045
15046 ENTER();
15047
Anurag Chouhan6d760662016-02-20 16:05:43 +053015048 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015049 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050 return -EINVAL;
15051 }
15052
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015053 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15054 hdd_err("invalid session id: %d", pAdapter->sessionId);
15055 return -EINVAL;
15056 }
15057
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015058 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015059 TRACE_CODE_HDD_CFG80211_DEL_STA,
15060 pAdapter->sessionId, pAdapter->device_mode));
15061
15062 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15063 status = wlan_hdd_validate_context(pHddCtx);
15064
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015065 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015066 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067
15068 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15069
Krunal Sonib4326f22016-03-10 13:05:51 -080015070 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15071 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015072
15073 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15074 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015075 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015076 return 0;
15077 }
15078
Anurag Chouhanc5548422016-02-24 18:33:27 +053015079 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015080 uint16_t i;
15081 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15082 if ((pAdapter->aStaInfo[i].isUsed) &&
15083 (!pAdapter->aStaInfo[i].
15084 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015085 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015086 mac,
15087 pAdapter->aStaInfo[i].
15088 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015089 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015090 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15091 hdd_ipa_wlan_evt(pAdapter,
15092 pAdapter->
15093 aStaInfo[i].
15094 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015095 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 mac);
15097 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015098 hdd_notice("Delete STA with MAC::"
15099 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015100 MAC_ADDR_ARRAY(mac));
15101
15102 if (pHddCtx->dev_dfs_cac_status ==
15103 DFS_CAC_IN_PROGRESS)
15104 goto fn_end;
15105
Wei Song2f76f642016-11-18 16:32:53 +080015106 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015107 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015108 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015109 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015110 hdd_softap_sta_deauth(pAdapter,
15111 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015112 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015113 pAdapter->aStaInfo[i].
15114 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015115 qdf_status =
15116 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015117 &hapd_state->
15118 qdf_sta_disassoc_event,
15119 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015120 if (!QDF_IS_STATUS_SUCCESS(
15121 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015122 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015123 }
15124 }
15125 }
15126 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015127 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015128 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015129 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015130 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015131 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015132 hdd_notice("Skip DEL STA as this is not used::"
15133 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015134 MAC_ADDR_ARRAY(mac));
15135 return -ENOENT;
15136 }
15137
15138 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15139 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015140 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015141 }
15142
15143 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15144 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015145 hdd_notice("Skip DEL STA as deauth is in progress::"
15146 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015147 MAC_ADDR_ARRAY(mac));
15148 return -ENOENT;
15149 }
15150
15151 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15152
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015153 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015154 MAC_ADDR_ARRAY(mac));
15155
15156 /* Case: SAP in ACS selected DFS ch and client connected
15157 * Now Radar detected. Then if random channel is another
15158 * DFS ch then new CAC is initiated and no TX allowed.
15159 * So do not send any mgmt frames as it will timeout
15160 * during CAC.
15161 */
15162
15163 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15164 goto fn_end;
15165
Wei Song2f76f642016-11-18 16:32:53 +080015166 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015167 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15168 (pAdapter), pAdapter->sessionId,
15169 (uint8_t *)&pDelStaParams->peerMacAddr,
15170 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015171 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015172 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015173 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015174 pAdapter->aStaInfo[staId].isDeauthInProgress =
15175 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015176 hdd_notice("STA removal failed for ::"
15177 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178 MAC_ADDR_ARRAY(mac));
15179 return -ENOENT;
15180 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015181 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015182 &hapd_state->
15183 qdf_sta_disassoc_event,
15184 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015185 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015186 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 }
15188 }
15189 }
15190
15191fn_end:
15192 EXIT();
15193 return 0;
15194}
15195
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015196#if defined(USE_CFG80211_DEL_STA_V2)
15197/**
15198 * wlan_hdd_del_station() - delete station wrapper
15199 * @adapter: pointer to the hdd adapter
15200 *
15201 * Return: None
15202 */
15203void wlan_hdd_del_station(hdd_adapter_t *adapter)
15204{
15205 struct station_del_parameters del_sta;
15206 del_sta.mac = NULL;
15207 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15208 del_sta.reason_code = eCsrForcedDeauthSta;
15209
15210 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15211 &del_sta);
15212}
15213#else
15214void wlan_hdd_del_station(hdd_adapter_t *adapter)
15215{
15216 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15217}
15218#endif
15219
15220#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015221/**
15222 * wlan_hdd_cfg80211_del_station() - delete station v2
15223 * @wiphy: Pointer to wiphy
15224 * @param: Pointer to delete station parameter
15225 *
15226 * Return: 0 for success, non-zero for failure
15227 */
15228int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15229 struct net_device *dev,
15230 struct station_del_parameters *param)
15231#else
15232/**
15233 * wlan_hdd_cfg80211_del_station() - delete station
15234 * @wiphy: Pointer to wiphy
15235 * @mac: Pointer to station mac address
15236 *
15237 * Return: 0 for success, non-zero for failure
15238 */
15239#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15240int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15241 struct net_device *dev,
15242 const uint8_t *mac)
15243#else
15244int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15245 struct net_device *dev,
15246 uint8_t *mac)
15247#endif
15248#endif
15249{
15250 int ret;
15251 struct tagCsrDelStaParams delStaParams;
15252
15253 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015254#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015256 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015257 return -EINVAL;
15258 }
15259 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15260 param->subtype, &delStaParams);
15261#else
15262 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15263 (SIR_MAC_MGMT_DEAUTH >> 4),
15264 &delStaParams);
15265#endif
15266 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15267 cds_ssr_unprotect(__func__);
15268
15269 return ret;
15270}
15271
15272/**
15273 * __wlan_hdd_cfg80211_add_station() - add station
15274 * @wiphy: Pointer to wiphy
15275 * @mac: Pointer to station mac address
15276 * @pmksa: Pointer to add station parameter
15277 *
15278 * Return: 0 for success, non-zero for failure
15279 */
15280static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15281 struct net_device *dev,
15282 const uint8_t *mac,
15283 struct station_parameters *params)
15284{
15285 int status = -EPERM;
15286#ifdef FEATURE_WLAN_TDLS
15287 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15288 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15289 u32 mask, set;
15290
15291 ENTER();
15292
Anurag Chouhan6d760662016-02-20 16:05:43 +053015293 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015294 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 return -EINVAL;
15296 }
15297
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015298 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15299 hdd_err("invalid session id: %d", pAdapter->sessionId);
15300 return -EINVAL;
15301 }
15302
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015303 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 TRACE_CODE_HDD_CFG80211_ADD_STA,
15305 pAdapter->sessionId, params->listen_interval));
15306
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015307 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015308 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309
15310 mask = params->sta_flags_mask;
15311
15312 set = params->sta_flags_set;
15313
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015314 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315 MAC_ADDR_ARRAY(mac));
15316
15317 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15318 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15319 status =
15320 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15321 }
15322 }
15323#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015324 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015325 return status;
15326}
15327
15328/**
15329 * wlan_hdd_cfg80211_add_station() - add station
15330 * @wiphy: Pointer to wiphy
15331 * @mac: Pointer to station mac address
15332 * @pmksa: Pointer to add station parameter
15333 *
15334 * Return: 0 for success, non-zero for failure
15335 */
15336#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15337static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15338 struct net_device *dev,
15339 const uint8_t *mac,
15340 struct station_parameters *params)
15341#else
15342static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15343 struct net_device *dev, uint8_t *mac,
15344 struct station_parameters *params)
15345#endif
15346{
15347 int ret;
15348
15349 cds_ssr_protect(__func__);
15350 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15351 cds_ssr_unprotect(__func__);
15352
15353 return ret;
15354}
15355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356/**
15357 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15358 * @wiphy: Pointer to wiphy
15359 * @dev: Pointer to network device
15360 * @pmksa: Pointer to set pmksa parameter
15361 *
15362 * Return: 0 for success, non-zero for failure
15363 */
15364static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15365 struct net_device *dev,
15366 struct cfg80211_pmksa *pmksa)
15367{
15368 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15369 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15370 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015371 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015372 int status;
15373 tPmkidCacheInfo pmk_id;
15374
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015375 ENTER();
15376
Anurag Chouhan6d760662016-02-20 16:05:43 +053015377 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015378 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015379 return -EINVAL;
15380 }
15381
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015382 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15383 hdd_err("invalid session id: %d", pAdapter->sessionId);
15384 return -EINVAL;
15385 }
15386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015387 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015388 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015389 return -EINVAL;
15390 }
15391
15392 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015393 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015394 pmksa->bssid, pmksa->pmkid);
15395 return -EINVAL;
15396 }
15397
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015398 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015399 MAC_ADDR_ARRAY(pmksa->bssid));
15400
15401 status = wlan_hdd_validate_context(pHddCtx);
15402
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015403 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015404 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015405
15406 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15407
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015408 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15409 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015410
15411 /* Add to the PMKSA ID Cache in CSR */
15412 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15413 &pmk_id, 1, false);
15414
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015415 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015416 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15417 pAdapter->sessionId, result));
15418
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015419 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015420 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015421}
15422
15423/**
15424 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15425 * @wiphy: Pointer to wiphy
15426 * @dev: Pointer to network device
15427 * @pmksa: Pointer to set pmksa parameter
15428 *
15429 * Return: 0 for success, non-zero for failure
15430 */
15431static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15432 struct net_device *dev,
15433 struct cfg80211_pmksa *pmksa)
15434{
15435 int ret;
15436
15437 cds_ssr_protect(__func__);
15438 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15439 cds_ssr_unprotect(__func__);
15440
15441 return ret;
15442}
15443
15444/**
15445 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15446 * @wiphy: Pointer to wiphy
15447 * @dev: Pointer to network device
15448 * @pmksa: Pointer to pmksa parameter
15449 *
15450 * Return: 0 for success, non-zero for failure
15451 */
15452static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15453 struct net_device *dev,
15454 struct cfg80211_pmksa *pmksa)
15455{
15456 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15457 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15458 tHalHandle halHandle;
15459 int status = 0;
15460
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015461 ENTER();
15462
Anurag Chouhan6d760662016-02-20 16:05:43 +053015463 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015464 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015465 return -EINVAL;
15466 }
15467
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015468 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15469 hdd_err("invalid session id: %d", pAdapter->sessionId);
15470 return -EINVAL;
15471 }
15472
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015473 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015474 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015475 return -EINVAL;
15476 }
15477
15478 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015479 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015480 return -EINVAL;
15481 }
15482
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015483 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015484 MAC_ADDR_ARRAY(pmksa->bssid));
15485
15486 status = wlan_hdd_validate_context(pHddCtx);
15487
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015488 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015490
15491 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15492
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015493 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015494 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15495 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015496 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015497 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015498 sme_roam_del_pmkid_from_cache(halHandle,
15499 pAdapter->sessionId, pmksa->bssid,
15500 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015501 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015502 MAC_ADDR_ARRAY(pmksa->bssid));
15503 status = -EINVAL;
15504 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015505 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015506 return status;
15507}
15508
15509/**
15510 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15511 * @wiphy: Pointer to wiphy
15512 * @dev: Pointer to network device
15513 * @pmksa: Pointer to pmksa parameter
15514 *
15515 * Return: 0 for success, non-zero for failure
15516 */
15517static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15518 struct net_device *dev,
15519 struct cfg80211_pmksa *pmksa)
15520{
15521 int ret;
15522
15523 cds_ssr_protect(__func__);
15524 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15525 cds_ssr_unprotect(__func__);
15526
15527 return ret;
15528
15529}
15530
15531/**
15532 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15533 * @wiphy: Pointer to wiphy
15534 * @dev: Pointer to network device
15535 *
15536 * Return: 0 for success, non-zero for failure
15537 */
15538static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15539 struct net_device *dev)
15540{
15541 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15542 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15543 tHalHandle halHandle;
15544 int status = 0;
15545
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015546 ENTER();
15547
Anurag Chouhan6d760662016-02-20 16:05:43 +053015548 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015549 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015550 return -EINVAL;
15551 }
15552
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015553 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15554 hdd_err("invalid session id: %d", pAdapter->sessionId);
15555 return -EINVAL;
15556 }
15557
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015558 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015559
15560 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15561 status = wlan_hdd_validate_context(pHddCtx);
15562
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015563 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015565
15566 /* Retrieve halHandle */
15567 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15568
15569 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015570 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015571 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15572 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015573 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015574 status = -EINVAL;
15575 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015576 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 return status;
15578}
15579
15580/**
15581 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15582 * @wiphy: Pointer to wiphy
15583 * @dev: Pointer to network device
15584 *
15585 * Return: 0 for success, non-zero for failure
15586 */
15587static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15588 struct net_device *dev)
15589{
15590 int ret;
15591
15592 cds_ssr_protect(__func__);
15593 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15594 cds_ssr_unprotect(__func__);
15595
15596 return ret;
15597}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015598
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015599#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015600/**
15601 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15602 * @wiphy: Pointer to wiphy
15603 * @dev: Pointer to network device
15604 * @ftie: Pointer to fast transition ie parameter
15605 *
15606 * Return: 0 for success, non-zero for failure
15607 */
15608static int
15609__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15610 struct net_device *dev,
15611 struct cfg80211_update_ft_ies_params *ftie)
15612{
15613 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15614 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15615 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15616 int status;
15617
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015618 ENTER();
15619
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015620 status = wlan_hdd_validate_context(hdd_ctx);
15621 if (status)
15622 return status;
15623
Anurag Chouhan6d760662016-02-20 16:05:43 +053015624 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015625 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015626 return -EINVAL;
15627 }
15628
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015629 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15630 hdd_err("invalid session id: %d", pAdapter->sessionId);
15631 return -EINVAL;
15632 }
15633
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015634 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15636 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15637 /* Added for debug on reception of Re-assoc Req. */
15638 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015639 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015640 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015641 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015642 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015643 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015644 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015645
15646 /* Pass the received FT IEs to SME */
15647 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15648 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015649 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015650 return 0;
15651}
15652
15653/**
15654 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15655 * @wiphy: Pointer to wiphy
15656 * @dev: Pointer to network device
15657 * @ftie: Pointer to fast transition ie parameter
15658 *
15659 * Return: 0 for success, non-zero for failure
15660 */
15661static int
15662wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15663 struct net_device *dev,
15664 struct cfg80211_update_ft_ies_params *ftie)
15665{
15666 int ret;
15667
15668 cds_ssr_protect(__func__);
15669 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15670 cds_ssr_unprotect(__func__);
15671
15672 return ret;
15673}
15674#endif
15675
Mukul Sharma3d36c392017-01-18 18:39:12 +053015676void wlan_hdd_cfg80211_update_replay_counter_callback(
15677 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15678
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015679{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015680 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15681 uint8_t temp_replay_counter[8];
15682 int i;
15683 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015684
15685 ENTER();
15686
Mukul Sharma3d36c392017-01-18 18:39:12 +053015687 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015688 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015689 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015690 }
15691
Mukul Sharma3d36c392017-01-18 18:39:12 +053015692 if (!gtk_rsp_param) {
15693 hdd_err("gtk_rsp_param is Null");
15694 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015695 }
15696
Mukul Sharma3d36c392017-01-18 18:39:12 +053015697 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015698 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015699 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015700 }
15701
Mukul Sharma3d36c392017-01-18 18:39:12 +053015702 hdd_notice("updated replay counter: %llu from fwr",
15703 gtk_rsp_param->replay_counter);
15704 /* convert little to big endian since supplicant works on big endian */
15705 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15706 for (i = 0; i < 8; i++)
15707 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015708
Mukul Sharma3d36c392017-01-18 18:39:12 +053015709 hdd_notice("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015710 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015711 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015712 gtk_rsp_param->bssid.bytes,
15713 temp_replay_counter, GFP_KERNEL);
15714out:
15715 EXIT();
15716
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015717}
15718
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015719static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015720int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015721 struct net_device *dev,
15722 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015723{
15724 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015725 int result, i;
15726 struct pmo_gtk_req *gtk_req = NULL;
15727 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15728 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015729 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015730
15731 ENTER();
15732
Anurag Chouhan6d760662016-02-20 16:05:43 +053015733 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015734 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015735 result = -EINVAL;
15736 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015737 }
15738
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015739 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15740 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015741 result = -EINVAL;
15742 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015743 }
15744
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015745 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015746 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15747 pAdapter->sessionId, pAdapter->device_mode));
15748
Mukul Sharma3d36c392017-01-18 18:39:12 +053015749 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015750 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015751 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752
Mukul Sharma3d36c392017-01-18 18:39:12 +053015753 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15754 if (!gtk_req) {
15755 hdd_err("cannot allocate gtk_req");
15756 result = -ENOMEM;
15757 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015758 }
15759
Mukul Sharma3d36c392017-01-18 18:39:12 +053015760 /* convert big to little endian since driver work on little endian */
15761 buf = (uint8_t *)&gtk_req->replay_counter;
15762 for (i = 0; i < 8; i++)
15763 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015764
Mukul Sharma3d36c392017-01-18 18:39:12 +053015765 hdd_notice("current replay counter: %llu in user space",
15766 gtk_req->replay_counter);
15767 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15768 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15769 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15770 if (status != QDF_STATUS_SUCCESS) {
15771 hdd_err("Failed to cache GTK Offload");
15772 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015773 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015774out:
15775 if (gtk_req)
15776 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015777 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015778
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015779 return result;
15780}
15781
15782/**
15783 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15784 * @wiphy: Pointer to wiphy
15785 * @dev: Pointer to network device
15786 * @data: Pointer to rekey data
15787 *
15788 * This function is used to offload GTK rekeying job to the firmware.
15789 *
15790 * Return: 0 for success, non-zero for failure
15791 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015792static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015793int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15794 struct net_device *dev,
15795 struct cfg80211_gtk_rekey_data *data)
15796{
15797 int ret;
15798
15799 cds_ssr_protect(__func__);
15800 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15801 cds_ssr_unprotect(__func__);
15802
15803 return ret;
15804}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015805
15806/**
15807 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15808 * @wiphy: Pointer to wiphy
15809 * @dev: Pointer to network device
15810 * @param: Pointer to access control parameter
15811 *
15812 * Return: 0 for success, non-zero for failure
15813 */
15814static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15815 struct net_device *dev,
15816 const struct cfg80211_acl_data *params)
15817{
15818 int i;
15819 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15820 hdd_hostapd_state_t *pHostapdState;
15821 tsap_Config_t *pConfig;
15822 v_CONTEXT_t p_cds_context = NULL;
15823 hdd_context_t *pHddCtx;
15824 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015825 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015826
15827 ENTER();
15828
Anurag Chouhan6d760662016-02-20 16:05:43 +053015829 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015830 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015831 return -EINVAL;
15832 }
15833
15834 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015835 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836 return -EINVAL;
15837 }
15838
15839 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15840 status = wlan_hdd_validate_context(pHddCtx);
15841
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015842 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015843 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015844
15845 p_cds_context = pHddCtx->pcds_context;
15846 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15847
15848 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015849 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015850 return -EINVAL;
15851 }
15852
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015853 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015854 params->n_acl_entries);
15855
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015856 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015857 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15858 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015859 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015860 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15861
15862 /* default value */
15863 pConfig->num_accept_mac = 0;
15864 pConfig->num_deny_mac = 0;
15865
15866 /**
15867 * access control policy
15868 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15869 * listed in hostapd.deny file.
15870 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15871 * listed in hostapd.accept file.
15872 */
15873 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15874 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15875 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15876 params->acl_policy) {
15877 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15878 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015879 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015880 params->acl_policy);
15881 return -ENOTSUPP;
15882 }
15883
15884 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15885 pConfig->num_accept_mac = params->n_acl_entries;
15886 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015887 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15888 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015889 MAC_ADDR_ARRAY(
15890 params->mac_addrs[i].addr));
15891
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015892 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015893 params->mac_addrs[i].addr,
15894 sizeof(qcmacaddr));
15895 }
15896 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15897 pConfig->num_deny_mac = params->n_acl_entries;
15898 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015899 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15900 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015901 MAC_ADDR_ARRAY(
15902 params->mac_addrs[i].addr));
15903
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015904 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015905 params->mac_addrs[i].addr,
15906 sizeof(qcmacaddr));
15907 }
15908 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015909 qdf_status = wlansap_set_mac_acl(
15910 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015911 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015912 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015913 return -EINVAL;
15914 }
15915 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015916 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015917 hdd_device_mode_to_string(pAdapter->device_mode),
15918 pAdapter->device_mode);
15919 return -EINVAL;
15920 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015921 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922 return 0;
15923}
15924
15925/**
15926 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15927 * __wlan_hdd_cfg80211_set_mac_acl
15928 * @wiphy: pointer to wiphy structure
15929 * @dev: pointer to net_device
15930 * @params: pointer to cfg80211_acl_data
15931 *
15932 * Return; 0 on success, error number otherwise
15933 */
15934static int
15935wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15936 struct net_device *dev,
15937 const struct cfg80211_acl_data *params)
15938{
15939 int ret;
15940
15941 cds_ssr_protect(__func__);
15942 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15943 cds_ssr_unprotect(__func__);
15944
15945 return ret;
15946}
15947
15948#ifdef WLAN_NL80211_TESTMODE
15949#ifdef FEATURE_WLAN_LPHB
15950/**
15951 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15952 * @pHddCtx: Pointer to hdd context
15953 * @lphbInd: Pointer to low power heart beat indication parameter
15954 *
15955 * Return: none
15956 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015957static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15958 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015959{
15960 struct sk_buff *skb;
15961
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015962 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015963
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015964 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015966
15967 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015968 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015969 return;
15970 }
15971
15972 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15973 wiphy, sizeof(tSirLPHBInd),
15974 GFP_ATOMIC);
15975 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015976 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977 return;
15978 }
15979
15980 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015981 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 goto nla_put_failure;
15983 }
15984 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015985 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015986 goto nla_put_failure;
15987 }
15988 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015989 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015990 goto nla_put_failure;
15991 }
15992 cfg80211_testmode_event(skb, GFP_ATOMIC);
15993 return;
15994
15995nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015996 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015997 kfree_skb(skb);
15998
15999 return;
16000}
16001#endif /* FEATURE_WLAN_LPHB */
16002
16003/**
16004 * __wlan_hdd_cfg80211_testmode() - test mode
16005 * @wiphy: Pointer to wiphy
16006 * @data: Data pointer
16007 * @len: Data length
16008 *
16009 * Return: 0 for success, non-zero for failure
16010 */
16011static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16012 void *data, int len)
16013{
16014 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16015 int err;
16016 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16017
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016018 ENTER();
16019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020 err = wlan_hdd_validate_context(pHddCtx);
16021 if (err)
16022 return err;
16023
16024 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16025 len, wlan_hdd_tm_policy);
16026 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016027 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016028 return err;
16029 }
16030
16031 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016032 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 return -EINVAL;
16034 }
16035
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016036 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016037 TRACE_CODE_HDD_CFG80211_TESTMODE,
16038 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016039 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16040#ifdef FEATURE_WLAN_LPHB
16041 /* Low Power Heartbeat configuration request */
16042 case WLAN_HDD_TM_CMD_WLAN_HB:
16043 {
16044 int buf_len;
16045 void *buf;
16046 tSirLPHBReq *hb_params = NULL;
16047 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016048 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016049
16050 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016051 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016052 return -EINVAL;
16053 }
16054
16055 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16056 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16057
16058 hb_params_temp = (tSirLPHBReq *) buf;
16059 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16060 && (hb_params_temp->params.lphbTcpParamReq.
16061 timePeriodSec == 0))
16062 return -EINVAL;
16063
16064 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016065 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016066 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016067 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016068 return -ENOMEM;
16069 }
16070
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016071 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016072 smeStatus =
16073 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16074 hb_params,
16075 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016076 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016077 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016078 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016079 }
16080 return 0;
16081 }
16082#endif /* FEATURE_WLAN_LPHB */
16083
16084#if defined(QCA_WIFI_FTM)
16085 case WLAN_HDD_TM_CMD_WLAN_FTM:
16086 {
16087 int buf_len;
16088 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016089 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016090 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016091 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092 return -EINVAL;
16093 }
16094
16095 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16096 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16097
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016098 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016099
16100 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16101
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016102 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016103 err = -EBUSY;
16104 break;
16105 }
16106#endif
16107
16108 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016109 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016110 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16111 return -EOPNOTSUPP;
16112 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016113 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016114 return err;
16115}
16116
16117/**
16118 * wlan_hdd_cfg80211_testmode() - test mode
16119 * @wiphy: Pointer to wiphy
16120 * @dev: Pointer to network device
16121 * @data: Data pointer
16122 * @len: Data length
16123 *
16124 * Return: 0 for success, non-zero for failure
16125 */
16126static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16127#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16128 struct wireless_dev *wdev,
16129#endif
16130 void *data, int len)
16131{
16132 int ret;
16133
16134 cds_ssr_protect(__func__);
16135 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16136 cds_ssr_unprotect(__func__);
16137
16138 return ret;
16139}
16140
16141#if defined(QCA_WIFI_FTM)
16142/**
16143 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16144 * @buf: Pointer to buffer
16145 * @buf_len: Buffer length
16146 *
16147 * Return: none
16148 */
16149void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16150{
16151 struct sk_buff *skb;
16152 hdd_context_t *hdd_ctx;
16153
16154 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016155 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 return;
16157 }
16158
Anurag Chouhan6d760662016-02-20 16:05:43 +053016159 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016161 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162 return;
16163 }
16164
16165 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16166 buf_len, GFP_KERNEL);
16167 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016168 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016169 return;
16170 }
16171
16172 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16173 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16174 goto nla_put_failure;
16175
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016176 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016177
16178 cfg80211_testmode_event(skb, GFP_KERNEL);
16179 return;
16180
16181nla_put_failure:
16182 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016183 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016184}
16185#endif
16186#endif /* CONFIG_NL80211_TESTMODE */
16187
16188#ifdef QCA_HT_2040_COEX
16189/**
16190 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16191 * @wiphy: Pointer to wiphy
16192 * @dev: Pointer to network device
16193 * @chandef: Pointer to channel definition parameter
16194 *
16195 * Return: 0 for success, non-zero for failure
16196 */
16197static int
16198__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16199 struct net_device *dev,
16200 struct cfg80211_chan_def *chandef)
16201{
16202 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16203 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016204 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016205 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016206 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016207
Anurag Chouhan6d760662016-02-20 16:05:43 +053016208 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016209 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 return -EINVAL;
16211 }
16212
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016213 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16214 hdd_err("invalid session id: %d", pAdapter->sessionId);
16215 return -EINVAL;
16216 }
16217
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016218 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16219 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016220 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016221 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016222
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016223 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016224 sme_get_config_param(pHddCtx->hHal, &sme_config);
16225 switch (chandef->width) {
16226 case NL80211_CHAN_WIDTH_20:
16227 if (sme_config.csrConfig.channelBondingMode24GHz !=
16228 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16229 sme_config.csrConfig.channelBondingMode24GHz =
16230 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16231 sme_update_config(pHddCtx->hHal, &sme_config);
16232 cbModeChange = true;
16233 }
16234 break;
16235
16236 case NL80211_CHAN_WIDTH_40:
16237 if (sme_config.csrConfig.channelBondingMode24GHz ==
16238 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16239 if (NL80211_CHAN_HT40MINUS ==
16240 cfg80211_get_chandef_type(chandef))
16241 sme_config.csrConfig.channelBondingMode24GHz =
16242 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16243 else
16244 sme_config.csrConfig.channelBondingMode24GHz =
16245 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16246 sme_update_config(pHddCtx->hHal, &sme_config);
16247 cbModeChange = true;
16248 }
16249 break;
16250
16251 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016252 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 return -EINVAL;
16254 }
16255
16256 if (!cbModeChange)
16257 return 0;
16258
Krunal Sonib4326f22016-03-10 13:05:51 -080016259 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016260 return 0;
16261
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016262 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016263 sme_config.csrConfig.channelBondingMode24GHz);
16264
16265 /* Change SAP ht2040 mode */
16266 status = hdd_set_sap_ht2040_mode(pAdapter,
16267 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016268 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016269 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016270 return -EINVAL;
16271 }
16272
16273 return 0;
16274}
16275
16276/**
16277 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16278 * @wiphy: Pointer to wiphy
16279 * @dev: Pointer to network device
16280 * @chandef: Pointer to channel definition parameter
16281 *
16282 * Return: 0 for success, non-zero for failure
16283 */
16284static int
16285wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16286 struct net_device *dev,
16287 struct cfg80211_chan_def *chandef)
16288{
16289 int ret;
16290
16291 cds_ssr_protect(__func__);
16292 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16293 cds_ssr_unprotect(__func__);
16294
16295 return ret;
16296}
16297#endif
16298
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016299#ifdef CHANNEL_SWITCH_SUPPORTED
16300/**
16301 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16302 * channel in SAP/GO
16303 * @wiphy: wiphy pointer
16304 * @dev: dev pointer.
16305 * @csa_params: Change channel params
16306 *
16307 * This function is called to switch channel in SAP/GO
16308 *
16309 * Return: 0 if success else return non zero
16310 */
16311static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16312 struct net_device *dev,
16313 struct cfg80211_csa_settings *csa_params)
16314{
16315 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16316 hdd_context_t *hdd_ctx;
16317 uint8_t channel;
16318 uint16_t freq;
16319 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016320 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016321
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016322 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016323 csa_params->chandef.chan->center_freq);
16324
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016325 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16326 hdd_err("invalid session id: %d", adapter->sessionId);
16327 return -EINVAL;
16328 }
16329
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016330 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16331 ret = wlan_hdd_validate_context(hdd_ctx);
16332
16333 if (0 != ret)
16334 return ret;
16335
Krunal Sonib4326f22016-03-10 13:05:51 -080016336 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16337 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016338 return -ENOTSUPP;
16339
16340 freq = csa_params->chandef.chan->center_freq;
16341 channel = cds_freq_to_chan(freq);
16342
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016343 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16344
16345 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016346 return ret;
16347}
16348
16349/**
16350 * wlan_hdd_cfg80211_channel_switch()- function to switch
16351 * channel in SAP/GO
16352 * @wiphy: wiphy pointer
16353 * @dev: dev pointer.
16354 * @csa_params: Change channel params
16355 *
16356 * This function is called to switch channel in SAP/GO
16357 *
16358 * Return: 0 if success else return non zero
16359 */
16360static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16361 struct net_device *dev,
16362 struct cfg80211_csa_settings *csa_params)
16363{
16364 int ret;
16365
16366 cds_ssr_protect(__func__);
16367 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16368 cds_ssr_unprotect(__func__);
16369 return ret;
16370}
16371#endif
16372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016373/**
16374 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16375 * translation from NL to policy manager type
16376 * @type: Generic connection mode type defined in NL
16377 *
16378 *
16379 * This function provides the type translation
16380 *
16381 * Return: cds_con_mode enum
16382 */
16383enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16384 enum nl80211_iftype type)
16385{
16386 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16387 switch (type) {
16388 case NL80211_IFTYPE_STATION:
16389 mode = CDS_STA_MODE;
16390 break;
16391 case NL80211_IFTYPE_P2P_CLIENT:
16392 mode = CDS_P2P_CLIENT_MODE;
16393 break;
16394 case NL80211_IFTYPE_P2P_GO:
16395 mode = CDS_P2P_GO_MODE;
16396 break;
16397 case NL80211_IFTYPE_AP:
16398 mode = CDS_SAP_MODE;
16399 break;
16400 case NL80211_IFTYPE_ADHOC:
16401 mode = CDS_IBSS_MODE;
16402 break;
16403 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016404 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405 type);
16406 }
16407 return mode;
16408}
16409
16410/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016411 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16412 * @wiphy: Handle to struct wiphy to get handle to module context.
16413 * @chandef: Contains information about the capture channel to be set.
16414 *
16415 * This interface is called if and only if monitor mode interface alone is
16416 * active.
16417 *
16418 * Return: 0 success or error code on failure.
16419 */
16420static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16421 struct cfg80211_chan_def *chandef)
16422{
16423 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16424 hdd_adapter_t *adapter;
16425 hdd_station_ctx_t *sta_ctx;
16426 struct hdd_mon_set_ch_info *ch_info;
16427 QDF_STATUS status;
16428 tHalHandle hal_hdl;
16429 struct qdf_mac_addr bssid;
16430 tCsrRoamProfile roam_profile;
16431 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016432 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016433 int ret;
16434 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16435
16436 ENTER();
16437
16438 ret = wlan_hdd_validate_context(hdd_ctx);
16439 if (ret)
16440 return ret;
16441
16442 hal_hdl = hdd_ctx->hHal;
16443
16444 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16445 if (!adapter)
16446 return -EIO;
16447
16448 hdd_info("%s: set monitor mode Channel %d and freq %d",
16449 adapter->dev->name, chan_num, chandef->chan->center_freq);
16450
16451 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16452 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016453 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16454 roam_profile.ChannelInfo.numOfChannels = 1;
16455 roam_profile.phyMode = ch_info->phy_mode;
16456 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016457 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016458
16459 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16460 QDF_MAC_ADDR_SIZE);
16461
16462 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016463 /*
16464 * CDS api expects secondary channel for calculating
16465 * the channel params
16466 */
16467 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16468 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16469 if (chan_num >= 1 && chan_num <= 5)
16470 sec_ch = chan_num + 4;
16471 else if (chan_num >= 6 && chan_num <= 13)
16472 sec_ch = chan_num - 4;
16473 }
16474 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016475 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16476 &roam_profile);
16477 if (status) {
16478 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16479 status);
16480 ret = qdf_status_to_os_return(status);
16481 return ret;
16482 }
16483 EXIT();
16484 return 0;
16485}
16486
16487/**
16488 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16489 * @wiphy: Handle to struct wiphy to get handle to module context.
16490 * @chandef: Contains information about the capture channel to be set.
16491 *
16492 * This interface is called if and only if monitor mode interface alone is
16493 * active.
16494 *
16495 * Return: 0 success or error code on failure.
16496 */
16497static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16498 struct cfg80211_chan_def *chandef)
16499{
16500 int ret;
16501
16502 cds_ssr_protect(__func__);
16503 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16504 cds_ssr_unprotect(__func__);
16505 return ret;
16506}
16507
16508/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016509 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16510 * @adapter: pointer to adapter
16511 *
16512 * Wrapper function to clear link layer stats.
16513 * return - void
16514 */
16515void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16516{
16517 tSirLLStatsClearReq link_layer_stats_clear_req;
16518 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16519
Mukul Sharma491021c2016-09-29 21:39:19 +053016520 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16521 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016522 link_layer_stats_clear_req.stopReq = 0;
16523 link_layer_stats_clear_req.reqId = 1;
16524 link_layer_stats_clear_req.staId = adapter->sessionId;
16525 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16526
16527 return;
16528}
16529
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016530#define CNT_DIFF(cur, prev) \
16531 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16532#define MAX_COUNT 0xffffffff
16533static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16534 struct scan_chan_info *chan,
16535 struct scan_chan_info *info, uint32_t cmd_flag)
16536{
16537 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16538 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16539 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16540
16541 mutex_lock(&hdd_ctx->chan_info_lock);
16542
16543 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16544 qdf_mem_zero(chan, sizeof(*chan));
16545
16546 chan->freq = info->freq;
16547 chan->noise_floor = info->noise_floor;
16548 chan->clock_freq = info->clock_freq;
16549 chan->cmd_flag = info->cmd_flag;
16550 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16551
16552 chan->rx_clear_count =
16553 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16554
16555 chan->tx_frame_count =
16556 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16557
16558 mutex_unlock(&hdd_ctx->chan_info_lock);
16559
16560}
16561#undef CNT_DIFF
16562#undef MAX_COUNT
16563
16564/**
16565 * wlan_hdd_chan_info_cb() - channel info callback
16566 * @chan_info: struct scan_chan_info
16567 *
16568 * Store channel info into HDD context
16569 *
16570 * Return: None.
16571 */
16572static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16573{
16574 hdd_context_t *hdd_ctx;
16575 struct scan_chan_info *chan;
16576 uint8_t idx;
16577
16578 ENTER();
16579
16580 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16581 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16582 hdd_err("hdd_ctx is invalid");
16583 return;
16584 }
16585
16586 if (!hdd_ctx->chan_info) {
16587 hdd_err("chan_info is NULL");
16588 return;
16589 }
16590
16591 chan = hdd_ctx->chan_info;
16592 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16593 if (chan[idx].freq == info->freq) {
16594 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16595 info->cmd_flag);
16596 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16597 chan[idx].cmd_flag, chan[idx].freq,
16598 chan[idx].noise_floor,
16599 chan[idx].cycle_count, chan[idx].rx_clear_count,
16600 chan[idx].clock_freq, chan[idx].cmd_flag,
16601 chan[idx].tx_frame_count, idx);
16602 if (chan[idx].freq == 0)
16603 break;
16604
16605 }
16606 }
16607
16608 EXIT();
16609}
16610
16611/**
16612 * wlan_hdd_init_chan_info() - init chan info in hdd context
16613 * @hdd_ctx: HDD context pointer
16614 *
16615 * Return: none
16616 */
16617void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16618{
16619 uint8_t num_2g, num_5g, index = 0;
16620
16621 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16622 hdd_info("SNR monitoring is disabled");
16623 return;
16624 }
16625
16626 hdd_ctx->chan_info =
16627 qdf_mem_malloc(sizeof(struct scan_chan_info)
16628 * QDF_MAX_NUM_CHAN);
16629 if (hdd_ctx->chan_info == NULL) {
16630 hdd_err("Failed to malloc for chan info");
16631 return;
16632 }
16633 mutex_init(&hdd_ctx->chan_info_lock);
16634
16635 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16636 for (; index < num_2g; index++) {
16637 hdd_ctx->chan_info[index].freq =
16638 hdd_channels_2_4_ghz[index].center_freq;
16639 }
16640
16641 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16642 for (; (index - num_2g) < num_5g; index++) {
16643 if (cds_is_dsrc_channel(
16644 hdd_channels_5_ghz[index - num_2g].center_freq))
16645 continue;
16646 hdd_ctx->chan_info[index].freq =
16647 hdd_channels_5_ghz[index - num_2g].center_freq;
16648 }
16649 sme_set_chan_info_callback(hdd_ctx->hHal,
16650 &wlan_hdd_chan_info_cb);
16651}
16652
16653/**
16654 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16655 * @hdd_ctx: hdd context pointer
16656 *
16657 * Return: none
16658 */
16659void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16660{
16661 struct scan_chan_info *chan;
16662
16663 chan = hdd_ctx->chan_info;
16664 hdd_ctx->chan_info = NULL;
16665 if (chan)
16666 qdf_mem_free(chan);
16667}
16668
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016669/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016670 * struct cfg80211_ops - cfg80211_ops
16671 *
16672 * @add_virtual_intf: Add virtual interface
16673 * @del_virtual_intf: Delete virtual interface
16674 * @change_virtual_intf: Change virtual interface
16675 * @change_station: Change station
16676 * @add_beacon: Add beacon in sap mode
16677 * @del_beacon: Delete beacon in sap mode
16678 * @set_beacon: Set beacon in sap mode
16679 * @start_ap: Start ap
16680 * @change_beacon: Change beacon
16681 * @stop_ap: Stop ap
16682 * @change_bss: Change bss
16683 * @add_key: Add key
16684 * @get_key: Get key
16685 * @del_key: Delete key
16686 * @set_default_key: Set default key
16687 * @set_channel: Set channel
16688 * @scan: Scan
16689 * @connect: Connect
16690 * @disconnect: Disconnect
16691 * @join_ibss = Join ibss
16692 * @leave_ibss = Leave ibss
16693 * @set_wiphy_params = Set wiphy params
16694 * @set_tx_power = Set tx power
16695 * @get_tx_power = get tx power
16696 * @remain_on_channel = Remain on channel
16697 * @cancel_remain_on_channel = Cancel remain on channel
16698 * @mgmt_tx = Tx management frame
16699 * @mgmt_tx_cancel_wait = Cancel management tx wait
16700 * @set_default_mgmt_key = Set default management key
16701 * @set_txq_params = Set tx queue parameters
16702 * @get_station = Get station
16703 * @set_power_mgmt = Set power management
16704 * @del_station = Delete station
16705 * @add_station = Add station
16706 * @set_pmksa = Set pmksa
16707 * @del_pmksa = Delete pmksa
16708 * @flush_pmksa = Flush pmksa
16709 * @update_ft_ies = Update FT IEs
16710 * @tdls_mgmt = Tdls management
16711 * @tdls_oper = Tdls operation
16712 * @set_rekey_data = Set rekey data
16713 * @sched_scan_start = Scheduled scan start
16714 * @sched_scan_stop = Scheduled scan stop
16715 * @resume = Resume wlan
16716 * @suspend = Suspend wlan
16717 * @set_mac_acl = Set mac acl
16718 * @testmode_cmd = Test mode command
16719 * @set_ap_chanwidth = Set AP channel bandwidth
16720 * @dump_survey = Dump survey
16721 * @key_mgmt_set_pmk = Set pmk key management
16722 */
16723static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16724 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16725 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16726 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16727 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016728 .start_ap = wlan_hdd_cfg80211_start_ap,
16729 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16730 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016731 .change_bss = wlan_hdd_cfg80211_change_bss,
16732 .add_key = wlan_hdd_cfg80211_add_key,
16733 .get_key = wlan_hdd_cfg80211_get_key,
16734 .del_key = wlan_hdd_cfg80211_del_key,
16735 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16736 .scan = wlan_hdd_cfg80211_scan,
16737 .connect = wlan_hdd_cfg80211_connect,
16738 .disconnect = wlan_hdd_cfg80211_disconnect,
16739 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16740 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16741 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16742 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16743 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16744 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16745 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16746 .mgmt_tx = wlan_hdd_mgmt_tx,
16747 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16748 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16749 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016750 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016751 .get_station = wlan_hdd_cfg80211_get_station,
16752 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16753 .del_station = wlan_hdd_cfg80211_del_station,
16754 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016755 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16756 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16757 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016758#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016759 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16760#endif
16761#ifdef FEATURE_WLAN_TDLS
16762 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16763 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16764#endif
16765#ifdef WLAN_FEATURE_GTK_OFFLOAD
16766 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16767#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16768#ifdef FEATURE_WLAN_SCAN_PNO
16769 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16770 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16771#endif /*FEATURE_WLAN_SCAN_PNO */
16772 .resume = wlan_hdd_cfg80211_resume_wlan,
16773 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16774 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16775#ifdef WLAN_NL80211_TESTMODE
16776 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16777#endif
16778#ifdef QCA_HT_2040_COEX
16779 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16780#endif
16781 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016782#ifdef CHANNEL_SWITCH_SUPPORTED
16783 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16784#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016785 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016786#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16787 defined(CFG80211_ABORT_SCAN)
16788 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16789#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016790};