blob: 48fce31fe2ca18cfe71c3479a55fce5206dd413d [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"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800103#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800104
Leo Changfdb45c32016-10-28 11:09:23 -0700105#include <cdp_txrx_cmn.h>
106#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800107#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530108#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800109#include "os_if_wifi_pos.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111#define g_mode_rates_size (12)
112#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
114 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
115
116/*
117 * Android CTS verifier needs atleast this much wait time (in msec)
118 */
119#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
120
121/*
122 * Refer @tCfgProtection structure for definition of the bit map.
123 * below value is obtained by setting the following bit-fields.
124 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
125 */
126#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
127
128#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700129 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800130 .center_freq = (freq), \
131 .hw_value = (chan), \
132 .flags = (flag), \
133 .max_antenna_gain = 0, \
134 .max_power = 30, \
135}
136
137#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700138 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139 .center_freq = (freq), \
140 .hw_value = (chan), \
141 .flags = (flag), \
142 .max_antenna_gain = 0, \
143 .max_power = 30, \
144}
145
146#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
147 { \
148 .bitrate = rate, \
149 .hw_value = rate_id, \
150 .flags = flag, \
151 }
152
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
154#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155
156#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157
Agrawal Ashish65634612016-08-18 13:24:32 +0530158#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
159 mode <= DFS_MODE_DEPRIORITIZE))
160#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
161 || (channel >= 36 && channel <= 184))
162
Peng Xu4d67c8f2015-10-16 16:02:26 -0700163#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530164#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700165
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166static const u32 hdd_cipher_suites[] = {
167 WLAN_CIPHER_SUITE_WEP40,
168 WLAN_CIPHER_SUITE_WEP104,
169 WLAN_CIPHER_SUITE_TKIP,
170#ifdef FEATURE_WLAN_ESE
171#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
172#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
173 WLAN_CIPHER_SUITE_BTK,
174 WLAN_CIPHER_SUITE_KRK,
175 WLAN_CIPHER_SUITE_CCMP,
176#else
177 WLAN_CIPHER_SUITE_CCMP,
178#endif
179#ifdef FEATURE_WLAN_WAPI
180 WLAN_CIPHER_SUITE_SMS4,
181#endif
182#ifdef WLAN_FEATURE_11W
183 WLAN_CIPHER_SUITE_AES_CMAC,
184#endif
185};
186
Abhishek Singhf512bf32016-05-04 16:47:46 +0530187static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188 HDD2GHZCHAN(2412, 1, 0),
189 HDD2GHZCHAN(2417, 2, 0),
190 HDD2GHZCHAN(2422, 3, 0),
191 HDD2GHZCHAN(2427, 4, 0),
192 HDD2GHZCHAN(2432, 5, 0),
193 HDD2GHZCHAN(2437, 6, 0),
194 HDD2GHZCHAN(2442, 7, 0),
195 HDD2GHZCHAN(2447, 8, 0),
196 HDD2GHZCHAN(2452, 9, 0),
197 HDD2GHZCHAN(2457, 10, 0),
198 HDD2GHZCHAN(2462, 11, 0),
199 HDD2GHZCHAN(2467, 12, 0),
200 HDD2GHZCHAN(2472, 13, 0),
201 HDD2GHZCHAN(2484, 14, 0),
202};
203
Abhishek Singhf512bf32016-05-04 16:47:46 +0530204static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205 HDD5GHZCHAN(5180, 36, 0),
206 HDD5GHZCHAN(5200, 40, 0),
207 HDD5GHZCHAN(5220, 44, 0),
208 HDD5GHZCHAN(5240, 48, 0),
209 HDD5GHZCHAN(5260, 52, 0),
210 HDD5GHZCHAN(5280, 56, 0),
211 HDD5GHZCHAN(5300, 60, 0),
212 HDD5GHZCHAN(5320, 64, 0),
213 HDD5GHZCHAN(5500, 100, 0),
214 HDD5GHZCHAN(5520, 104, 0),
215 HDD5GHZCHAN(5540, 108, 0),
216 HDD5GHZCHAN(5560, 112, 0),
217 HDD5GHZCHAN(5580, 116, 0),
218 HDD5GHZCHAN(5600, 120, 0),
219 HDD5GHZCHAN(5620, 124, 0),
220 HDD5GHZCHAN(5640, 128, 0),
221 HDD5GHZCHAN(5660, 132, 0),
222 HDD5GHZCHAN(5680, 136, 0),
223 HDD5GHZCHAN(5700, 140, 0),
224 HDD5GHZCHAN(5720, 144, 0),
225 HDD5GHZCHAN(5745, 149, 0),
226 HDD5GHZCHAN(5765, 153, 0),
227 HDD5GHZCHAN(5785, 157, 0),
228 HDD5GHZCHAN(5805, 161, 0),
229 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230 HDD5GHZCHAN(5852, 170, 0),
231 HDD5GHZCHAN(5855, 171, 0),
232 HDD5GHZCHAN(5860, 172, 0),
233 HDD5GHZCHAN(5865, 173, 0),
234 HDD5GHZCHAN(5870, 174, 0),
235 HDD5GHZCHAN(5875, 175, 0),
236 HDD5GHZCHAN(5880, 176, 0),
237 HDD5GHZCHAN(5885, 177, 0),
238 HDD5GHZCHAN(5890, 178, 0),
239 HDD5GHZCHAN(5895, 179, 0),
240 HDD5GHZCHAN(5900, 180, 0),
241 HDD5GHZCHAN(5905, 181, 0),
242 HDD5GHZCHAN(5910, 182, 0),
243 HDD5GHZCHAN(5915, 183, 0),
244 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800245};
246
247static struct ieee80211_rate g_mode_rates[] = {
248 HDD_G_MODE_RATETAB(10, 0x1, 0),
249 HDD_G_MODE_RATETAB(20, 0x2, 0),
250 HDD_G_MODE_RATETAB(55, 0x4, 0),
251 HDD_G_MODE_RATETAB(110, 0x8, 0),
252 HDD_G_MODE_RATETAB(60, 0x10, 0),
253 HDD_G_MODE_RATETAB(90, 0x20, 0),
254 HDD_G_MODE_RATETAB(120, 0x40, 0),
255 HDD_G_MODE_RATETAB(180, 0x80, 0),
256 HDD_G_MODE_RATETAB(240, 0x100, 0),
257 HDD_G_MODE_RATETAB(360, 0x200, 0),
258 HDD_G_MODE_RATETAB(480, 0x400, 0),
259 HDD_G_MODE_RATETAB(540, 0x800, 0),
260};
261
262static struct ieee80211_rate a_mode_rates[] = {
263 HDD_G_MODE_RATETAB(60, 0x10, 0),
264 HDD_G_MODE_RATETAB(90, 0x20, 0),
265 HDD_G_MODE_RATETAB(120, 0x40, 0),
266 HDD_G_MODE_RATETAB(180, 0x80, 0),
267 HDD_G_MODE_RATETAB(240, 0x100, 0),
268 HDD_G_MODE_RATETAB(360, 0x200, 0),
269 HDD_G_MODE_RATETAB(480, 0x400, 0),
270 HDD_G_MODE_RATETAB(540, 0x800, 0),
271};
272
273static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530274 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700276 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277 .bitrates = g_mode_rates,
278 .n_bitrates = g_mode_rates_size,
279 .ht_cap.ht_supported = 1,
280 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
281 | IEEE80211_HT_CAP_GRN_FLD
282 | IEEE80211_HT_CAP_DSSSCCK40
283 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
284 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
285 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
286 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
287 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
288 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
289 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
290};
291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530293 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700295 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 .bitrates = a_mode_rates,
297 .n_bitrates = a_mode_rates_size,
298 .ht_cap.ht_supported = 1,
299 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
300 | IEEE80211_HT_CAP_GRN_FLD
301 | IEEE80211_HT_CAP_DSSSCCK40
302 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
303 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
304 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
305 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
306 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
307 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
308 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
309 .vht_cap.vht_supported = 1,
310};
311
312/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800313 * TX/RX direction for each kind of interface
314 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800315static const struct ieee80211_txrx_stypes
316 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
317 [NL80211_IFTYPE_STATION] = {
318 .tx = 0xffff,
319 .rx = BIT(SIR_MAC_MGMT_ACTION) |
320 BIT(SIR_MAC_MGMT_PROBE_REQ),
321 },
322 [NL80211_IFTYPE_AP] = {
323 .tx = 0xffff,
324 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
325 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_PROBE_REQ) |
327 BIT(SIR_MAC_MGMT_DISASSOC) |
328 BIT(SIR_MAC_MGMT_AUTH) |
329 BIT(SIR_MAC_MGMT_DEAUTH) |
330 BIT(SIR_MAC_MGMT_ACTION),
331 },
332 [NL80211_IFTYPE_ADHOC] = {
333 .tx = 0xffff,
334 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
335 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
336 BIT(SIR_MAC_MGMT_PROBE_REQ) |
337 BIT(SIR_MAC_MGMT_DISASSOC) |
338 BIT(SIR_MAC_MGMT_AUTH) |
339 BIT(SIR_MAC_MGMT_DEAUTH) |
340 BIT(SIR_MAC_MGMT_ACTION),
341 },
342 [NL80211_IFTYPE_P2P_CLIENT] = {
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ACTION) |
345 BIT(SIR_MAC_MGMT_PROBE_REQ),
346 },
347 [NL80211_IFTYPE_P2P_GO] = {
348 /* This is also same as for SoftAP */
349 .tx = 0xffff,
350 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
351 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
352 BIT(SIR_MAC_MGMT_PROBE_REQ) |
353 BIT(SIR_MAC_MGMT_DISASSOC) |
354 BIT(SIR_MAC_MGMT_AUTH) |
355 BIT(SIR_MAC_MGMT_DEAUTH) |
356 BIT(SIR_MAC_MGMT_ACTION),
357 },
358};
359
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800360/* Interface limits and combinations registered by the driver */
361
362/* STA ( + STA ) combination */
363static const struct ieee80211_iface_limit
364 wlan_hdd_sta_iface_limit[] = {
365 {
366 .max = 3, /* p2p0 is a STA as well */
367 .types = BIT(NL80211_IFTYPE_STATION),
368 },
369};
370
371/* ADHOC (IBSS) limit */
372static const struct ieee80211_iface_limit
373 wlan_hdd_adhoc_iface_limit[] = {
374 {
375 .max = 1,
376 .types = BIT(NL80211_IFTYPE_STATION),
377 },
378 {
379 .max = 1,
380 .types = BIT(NL80211_IFTYPE_ADHOC),
381 },
382};
383
384/* AP ( + AP ) combination */
385static const struct ieee80211_iface_limit
386 wlan_hdd_ap_iface_limit[] = {
387 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530388 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800389 .types = BIT(NL80211_IFTYPE_AP),
390 },
391};
392
393/* P2P limit */
394static const struct ieee80211_iface_limit
395 wlan_hdd_p2p_iface_limit[] = {
396 {
397 .max = 1,
398 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
399 },
400 {
401 .max = 1,
402 .types = BIT(NL80211_IFTYPE_P2P_GO),
403 },
404};
405
406static const struct ieee80211_iface_limit
407 wlan_hdd_sta_ap_iface_limit[] = {
408 {
409 /* We need 1 extra STA interface for OBSS scan when SAP starts
410 * with HT40 in STA+SAP concurrency mode
411 */
412 .max = (1 + SAP_MAX_OBSS_STA_CNT),
413 .types = BIT(NL80211_IFTYPE_STATION),
414 },
415 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530416 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800417 .types = BIT(NL80211_IFTYPE_AP),
418 },
419};
420
421/* STA + P2P combination */
422static const struct ieee80211_iface_limit
423 wlan_hdd_sta_p2p_iface_limit[] = {
424 {
425 /* One reserved for dedicated P2PDEV usage */
426 .max = 2,
427 .types = BIT(NL80211_IFTYPE_STATION)
428 },
429 {
430 /* Support for two identical (GO + GO or CLI + CLI)
431 * or dissimilar (GO + CLI) P2P interfaces
432 */
433 .max = 2,
434 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
435 },
436};
437
438/* STA + AP + P2PGO combination */
439static const struct ieee80211_iface_limit
440wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
441 /* Support for AP+P2PGO interfaces */
442 {
443 .max = 2,
444 .types = BIT(NL80211_IFTYPE_STATION)
445 },
446 {
447 .max = 1,
448 .types = BIT(NL80211_IFTYPE_P2P_GO)
449 },
450 {
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_AP)
453 }
454};
455
456/* SAP + P2P combination */
457static const struct ieee80211_iface_limit
458wlan_hdd_sap_p2p_iface_limit[] = {
459 {
460 /* 1 dedicated for p2p0 which is a STA type */
461 .max = 1,
462 .types = BIT(NL80211_IFTYPE_STATION)
463 },
464 {
465 /* The p2p interface in SAP+P2P can be GO/CLI.
466 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
467 */
468 .max = 1,
469 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
470 },
471 {
472 /* SAP+GO to support only one SAP interface */
473 .max = 1,
474 .types = BIT(NL80211_IFTYPE_AP)
475 }
476};
477
478/* P2P + P2P combination */
479static const struct ieee80211_iface_limit
480wlan_hdd_p2p_p2p_iface_limit[] = {
481 {
482 /* 1 dedicated for p2p0 which is a STA type */
483 .max = 1,
484 .types = BIT(NL80211_IFTYPE_STATION)
485 },
486 {
487 /* The p2p interface in P2P+P2P can be GO/CLI.
488 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
489 */
490 .max = 2,
491 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
492 },
493};
494
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700495static const struct ieee80211_iface_limit
496 wlan_hdd_mon_iface_limit[] = {
497 {
498 .max = 3, /* Monitor interface */
499 .types = BIT(NL80211_IFTYPE_MONITOR),
500 },
501};
502
503static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504 wlan_hdd_iface_combination[] = {
505 /* STA */
506 {
507 .limits = wlan_hdd_sta_iface_limit,
508 .num_different_channels = 2,
509 .max_interfaces = 3,
510 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
511 },
512 /* ADHOC */
513 {
514 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700515 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800516 .max_interfaces = 2,
517 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
518 },
519 /* AP */
520 {
521 .limits = wlan_hdd_ap_iface_limit,
522 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530523 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
525 },
526 /* P2P */
527 {
528 .limits = wlan_hdd_p2p_iface_limit,
529 .num_different_channels = 2,
530 .max_interfaces = 2,
531 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
532 },
533 /* STA + AP */
534 {
535 .limits = wlan_hdd_sta_ap_iface_limit,
536 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530537 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
539 .beacon_int_infra_match = true,
540 },
541 /* STA + P2P */
542 {
543 .limits = wlan_hdd_sta_p2p_iface_limit,
544 .num_different_channels = 2,
545 /* one interface reserved for P2PDEV dedicated usage */
546 .max_interfaces = 4,
547 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
548 .beacon_int_infra_match = true,
549 },
550 /* STA + P2P GO + SAP */
551 {
552 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
553 /* we can allow 3 channels for three different persona
554 * but due to firmware limitation, allow max 2 concrnt channels.
555 */
556 .num_different_channels = 2,
557 /* one interface reserved for P2PDEV dedicated usage */
558 .max_interfaces = 4,
559 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
560 .beacon_int_infra_match = true,
561 },
562 /* SAP + P2P */
563 {
564 .limits = wlan_hdd_sap_p2p_iface_limit,
565 .num_different_channels = 2,
566 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
567 .max_interfaces = 3,
568 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
569 .beacon_int_infra_match = true,
570 },
571 /* P2P + P2P */
572 {
573 .limits = wlan_hdd_p2p_p2p_iface_limit,
574 .num_different_channels = 2,
575 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
576 .max_interfaces = 3,
577 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
578 .beacon_int_infra_match = true,
579 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530580 /* Monitor */
581 {
582 .limits = wlan_hdd_mon_iface_limit,
583 .max_interfaces = 3,
584 .num_different_channels = 2,
585 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
586 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800587};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588
589static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590
591#ifdef WLAN_NL80211_TESTMODE
592enum wlan_hdd_tm_attr {
593 WLAN_HDD_TM_ATTR_INVALID = 0,
594 WLAN_HDD_TM_ATTR_CMD = 1,
595 WLAN_HDD_TM_ATTR_DATA = 2,
596 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
597 WLAN_HDD_TM_ATTR_TYPE = 4,
598 /* keep last */
599 WLAN_HDD_TM_ATTR_AFTER_LAST,
600 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
601};
602
603enum wlan_hdd_tm_cmd {
604 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
605 WLAN_HDD_TM_CMD_WLAN_HB = 1,
606};
607
608#define WLAN_HDD_TM_DATA_MAX_LEN 5000
609
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530610enum wlan_hdd_vendor_ie_access_policy {
611 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
612 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
613};
614
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
616 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
617 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
618 .len = WLAN_HDD_TM_DATA_MAX_LEN},
619};
620#endif /* WLAN_NL80211_TESTMODE */
621
622#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
623static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
624 .flags = WIPHY_WOWLAN_MAGIC_PKT,
625 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
626 .pattern_min_len = 1,
627 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
628};
629#endif
630
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530632 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
633 * @flags: Pointer to the flags to Add channel switch flag.
634 *
635 * This Function adds Channel Switch support flag, if channel switch is
636 * supported by kernel.
637 * Return: void.
638 */
639#ifdef CHANNEL_SWITCH_SUPPORTED
640static inline void hdd_add_channel_switch_support(uint32_t *flags)
641{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800642 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530643 return;
644}
645#else
646static inline void hdd_add_channel_switch_support(uint32_t *flags)
647{
648 return;
649}
650#endif
651
Manikandan Mohan22b83722015-12-15 15:03:23 -0800652#ifdef FEATURE_WLAN_TDLS
653
654/* TDLS capabilities params */
655#define PARAM_MAX_TDLS_SESSION \
656 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
657#define PARAM_TDLS_FEATURE_SUPPORT \
658 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
659
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530660/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
662 * @wiphy: WIPHY structure pointer
663 * @wdev: Wireless device structure pointer
664 * @data: Pointer to the data received
665 * @data_len: Length of the data received
666 *
667 * This function provides TDLS capabilities
668 *
669 * Return: 0 on success and errno on failure
670 */
671static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
672 struct wireless_dev *wdev,
673 const void *data,
674 int data_len)
675{
676 int status;
677 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
678 struct sk_buff *skb;
679 uint32_t set = 0;
680
Jeff Johnson1f61b612016-02-12 16:28:33 -0800681 ENTER_DEV(wdev->netdev);
682
Anurag Chouhan6d760662016-02-20 16:05:43 +0530683 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 hdd_err("Command not allowed in FTM mode");
685 return -EPERM;
686 }
687
688 status = wlan_hdd_validate_context(hdd_ctx);
689 if (status)
690 return status;
691
692 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
693 NLMSG_HDRLEN);
694 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 goto fail;
697 }
698
699 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700700 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800701 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
702 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700703 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 goto fail;
705 }
706 } else {
707 set = set | WIFI_TDLS_SUPPORT;
708 set = set | (hdd_ctx->config->fTDLSExternalControl ?
709 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
710 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
711 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700712 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
714 hdd_ctx->max_num_tdls_sta) ||
715 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
716 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700717 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800718 goto fail;
719 }
720 }
721 return cfg80211_vendor_cmd_reply(skb);
722fail:
723 if (skb)
724 kfree_skb(skb);
725 return -EINVAL;
726}
727
728/**
729 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
730 * @wiphy: WIPHY structure pointer
731 * @wdev: Wireless device structure pointer
732 * @data: Pointer to the data received
733 * @data_len: Length of the data received
734 *
735 * This function provides TDLS capabilities
736 *
737 * Return: 0 on success and errno on failure
738 */
739static int
740wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
741 struct wireless_dev *wdev,
742 const void *data,
743 int data_len)
744{
745 int ret;
746
747 cds_ssr_protect(__func__);
748 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
749 data, data_len);
750 cds_ssr_unprotect(__func__);
751
752 return ret;
753}
754#endif
755
756#ifdef QCA_HT_2040_COEX
757static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
758#endif
759
760#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
761/*
762 * FUNCTION: wlan_hdd_send_avoid_freq_event
763 * This is called when wlan driver needs to send vendor specific
764 * avoid frequency range event to userspace
765 */
766int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
767 tHddAvoidFreqList *pAvoidFreqList)
768{
769 struct sk_buff *vendor_event;
770
771 ENTER();
772
773 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700774 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return -EINVAL;
776 }
777
778 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700779 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 return -EINVAL;
781 }
782
783 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
784 NULL,
785 sizeof(tHddAvoidFreqList),
786 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
787 GFP_KERNEL);
788 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700789 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790 return -EINVAL;
791 }
792
793 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
794 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
795
796 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
797
798 EXIT();
799 return 0;
800}
801#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
802
803/* vendor specific events */
804static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
805#ifdef FEATURE_WLAN_CH_AVOID
806 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
807 .vendor_id =
808 QCA_NL80211_VENDOR_ID,
809 .subcmd =
810 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
811 },
812#endif /* FEATURE_WLAN_CH_AVOID */
813
814#ifdef WLAN_FEATURE_NAN
815 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
816 .vendor_id =
817 QCA_NL80211_VENDOR_ID,
818 .subcmd =
819 QCA_NL80211_VENDOR_SUBCMD_NAN
820 },
821#endif
822
823#ifdef WLAN_FEATURE_STATS_EXT
824 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
829 },
830#endif /* WLAN_FEATURE_STATS_EXT */
831#ifdef FEATURE_WLAN_EXTSCAN
832 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
833 .vendor_id =
834 QCA_NL80211_VENDOR_ID,
835 .subcmd =
836 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
837 },
838 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
839 .vendor_id =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .subcmd =
850 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
851 },
852 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
853 .
854 vendor_id
855 =
856 QCA_NL80211_VENDOR_ID,
857 .
858 subcmd =
859 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
860 },
861 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
862 .
863 vendor_id
864 =
865 QCA_NL80211_VENDOR_ID,
866 .
867 subcmd
868 =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
872 .
873 vendor_id
874 =
875 QCA_NL80211_VENDOR_ID,
876 .subcmd =
877 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
878 },
879 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
880 .vendor_id =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .subcmd =
899 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
900 },
901 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
902 .
903 vendor_id
904 =
905 QCA_NL80211_VENDOR_ID,
906 .
907 subcmd
908 =
909 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
910 },
911 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
912 .
913 vendor_id
914 =
915 QCA_NL80211_VENDOR_ID,
916 .
917 subcmd =
918 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
919 },
920 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
921 .
922 vendor_id
923 =
924 QCA_NL80211_VENDOR_ID,
925 .
926 subcmd
927 =
928 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
929 },
930 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
931 .
932 vendor_id
933 =
934 QCA_NL80211_VENDOR_ID,
935 .
936 subcmd
937 =
938 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
939 },
940 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
941 .vendor_id = QCA_NL80211_VENDOR_ID,
942 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
943 },
944 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
945 .vendor_id = QCA_NL80211_VENDOR_ID,
946 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
947 },
948#endif /* FEATURE_WLAN_EXTSCAN */
949
950#ifdef WLAN_FEATURE_LINK_LAYER_STATS
951 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
952 .vendor_id =
953 QCA_NL80211_VENDOR_ID,
954 .subcmd =
955 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
956 },
957 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
958 .vendor_id =
959 QCA_NL80211_VENDOR_ID,
960 .subcmd =
961 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
962 },
963 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
964 .vendor_id =
965 QCA_NL80211_VENDOR_ID,
966 .subcmd =
967 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
968 },
969 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
970 .vendor_id =
971 QCA_NL80211_VENDOR_ID,
972 .subcmd =
973 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
974 },
975 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
976 .vendor_id =
977 QCA_NL80211_VENDOR_ID,
978 .subcmd =
979 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
980 },
981 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
982 .vendor_id =
983 QCA_NL80211_VENDOR_ID,
984 .subcmd =
985 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
986 },
987#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
988 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
989 .vendor_id =
990 QCA_NL80211_VENDOR_ID,
991 .subcmd =
992 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
993 },
994 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
995 .vendor_id = QCA_NL80211_VENDOR_ID,
996 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
997 },
998#ifdef WLAN_FEATURE_ROAM_OFFLOAD
999 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1004 },
1005#endif
1006 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1007 .vendor_id =
1008 QCA_NL80211_VENDOR_ID,
1009 .subcmd =
1010 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1011 },
1012 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1013 .vendor_id =
1014 QCA_NL80211_VENDOR_ID,
1015 .subcmd =
1016 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1017 },
1018 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1019 .vendor_id =
1020 QCA_NL80211_VENDOR_ID,
1021 .subcmd =
1022 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1023 },
1024 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1025 .vendor_id =
1026 QCA_NL80211_VENDOR_ID,
1027 .subcmd =
1028 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1029 },
1030 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1031 .vendor_id =
1032 QCA_NL80211_VENDOR_ID,
1033 .subcmd =
1034 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1035 },
1036#ifdef FEATURE_WLAN_EXTSCAN
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1044 },
1045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1048 },
1049 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1050 .vendor_id = QCA_NL80211_VENDOR_ID,
1051 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1052 },
1053 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1056 },
1057#endif /* FEATURE_WLAN_EXTSCAN */
1058 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1061 },
1062#ifdef WLAN_FEATURE_MEMDUMP
1063 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1064 .vendor_id = QCA_NL80211_VENDOR_ID,
1065 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1066 },
1067#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001068#ifdef WLAN_FEATURE_TSF
1069 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1072 },
1073#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1075 .vendor_id = QCA_NL80211_VENDOR_ID,
1076 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1077 },
1078 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1081 },
1082 /* OCB events */
1083 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1084 .vendor_id = QCA_NL80211_VENDOR_ID,
1085 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1086 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001087#ifdef FEATURE_LFR_SUBNET_DETECTION
1088 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1089 .vendor_id = QCA_NL80211_VENDOR_ID,
1090 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1091 },
1092#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001093
1094#ifdef WLAN_FEATURE_NAN_DATAPATH
1095 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1098 },
1099#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001100
1101 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1102 .vendor_id = QCA_NL80211_VENDOR_ID,
1103 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1104 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301105 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1106 .vendor_id = QCA_NL80211_VENDOR_ID,
1107 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1108 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301109 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1110 .vendor_id = QCA_NL80211_VENDOR_ID,
1111 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1112 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001113#ifdef WLAN_UMAC_CONVERGENCE
1114 COMMON_VENDOR_EVENTS
1115#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001116};
1117
1118/**
1119 * __is_driver_dfs_capable() - get driver DFS capability
1120 * @wiphy: pointer to wireless wiphy structure.
1121 * @wdev: pointer to wireless_dev structure.
1122 * @data: Pointer to the data to be passed via vendor interface
1123 * @data_len:Length of the data to be passed
1124 *
1125 * This function is called by userspace to indicate whether or not
1126 * the driver supports DFS offload.
1127 *
1128 * Return: 0 on success, negative errno on failure
1129 */
1130static int __is_driver_dfs_capable(struct wiphy *wiphy,
1131 struct wireless_dev *wdev,
1132 const void *data,
1133 int data_len)
1134{
1135 u32 dfs_capability = 0;
1136 struct sk_buff *temp_skbuff;
1137 int ret_val;
1138 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1139
Jeff Johnson1f61b612016-02-12 16:28:33 -08001140 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141
1142 ret_val = wlan_hdd_validate_context(hdd_ctx);
1143 if (ret_val)
1144 return ret_val;
1145
Anurag Chouhan6d760662016-02-20 16:05:43 +05301146 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147 hdd_err("Command not allowed in FTM mode");
1148 return -EPERM;
1149 }
1150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152
1153 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1154 NLMSG_HDRLEN);
1155
1156 if (temp_skbuff != NULL) {
1157 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1158 dfs_capability);
1159 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001160 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 kfree_skb(temp_skbuff);
1162
1163 return ret_val;
1164 }
1165
1166 return cfg80211_vendor_cmd_reply(temp_skbuff);
1167 }
1168
Jeff Johnson020db452016-06-29 14:37:26 -07001169 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001170 return -ENOMEM;
1171}
1172
1173/**
1174 * is_driver_dfs_capable() - get driver DFS capability
1175 * @wiphy: pointer to wireless wiphy structure.
1176 * @wdev: pointer to wireless_dev structure.
1177 * @data: Pointer to the data to be passed via vendor interface
1178 * @data_len:Length of the data to be passed
1179 *
1180 * This function is called by userspace to indicate whether or not
1181 * the driver supports DFS offload. This is an SSR-protected
1182 * wrapper function.
1183 *
1184 * Return: 0 on success, negative errno on failure
1185 */
1186static int is_driver_dfs_capable(struct wiphy *wiphy,
1187 struct wireless_dev *wdev,
1188 const void *data,
1189 int data_len)
1190{
1191 int ret;
1192
1193 cds_ssr_protect(__func__);
1194 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1195 cds_ssr_unprotect(__func__);
1196
1197 return ret;
1198}
1199
1200/**
1201 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1202 *
1203 * @adapter: SAP adapter pointer
1204 *
1205 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1206 * radio. So in case of DFS MCC scenario override current SAP given config
1207 * to follow concurrent SAP DFS config
1208 *
1209 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1210 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1212{
1213 hdd_adapter_t *con_sap_adapter;
1214 tsap_Config_t *sap_config, *con_sap_config;
1215 int con_ch;
1216
1217 /*
1218 * Check if AP+AP case, once primary AP chooses a DFS
1219 * channel secondary AP should always follow primary APs channel
1220 */
1221 if (!cds_concurrent_beaconing_sessions_running())
1222 return 0;
1223
1224 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1225 if (!con_sap_adapter)
1226 return 0;
1227
1228 sap_config = &adapter->sessionCtx.ap.sapConfig;
1229 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1230 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1231
1232 if (!CDS_IS_DFS_CH(con_ch))
1233 return 0;
1234
Jeff Johnson020db452016-06-29 14:37:26 -07001235 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001237 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 sap_config->channel = con_ch;
1239
1240 if (con_sap_config->acs_cfg.acs_mode == true) {
1241 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1242 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001243 hdd_err("Primary AP channel config error");
1244 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 con_ch, con_sap_config->acs_cfg.pri_ch,
1246 con_sap_config->acs_cfg.ht_sec_ch);
1247 return -EINVAL;
1248 }
1249 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1250 * MCC restriction. So free ch list allocated in do_acs
1251 * func for Sec AP and realloc for Pri AP ch list size
1252 */
1253 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301256 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 &con_sap_config->acs_cfg,
1258 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301259 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001260 sizeof(uint8_t) *
1261 con_sap_config->acs_cfg.ch_list_count);
1262 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001263 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 return -ENOMEM;
1265 }
1266
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301267 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001268 con_sap_config->acs_cfg.ch_list,
1269 con_sap_config->acs_cfg.ch_list_count);
1270
1271 } else {
1272 sap_config->acs_cfg.pri_ch = con_ch;
1273 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1274 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1275 }
1276
1277 return con_ch;
1278}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001279
1280/**
1281 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1282 * @sap_cfg: pointer to SAP config struct
1283 *
1284 * This function sets the default ACS start and end channel for the given band
1285 * and also parses the given ACS channel list.
1286 *
1287 * Return: None
1288 */
1289
1290static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1291 bool vht_enabled)
1292{
1293 int i;
1294 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1295 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001296 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1297 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1299 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001300 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1301 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1303 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001304 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1305 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1307 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001308 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1309 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310 }
1311
1312 if (ht_enabled)
1313 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1314
1315 if (vht_enabled)
1316 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1317
1318
1319 /* Parse ACS Chan list from hostapd */
1320 if (!sap_cfg->acs_cfg.ch_list)
1321 return;
1322
1323 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1324 sap_cfg->acs_cfg.end_ch =
1325 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1326 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301327 /* avoid channel as start channel */
1328 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1329 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1331 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1332 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1333 }
1334}
1335
1336
1337static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1338
1339/**
1340 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1341 * @adapter: pointer to SAP adapter struct
1342 *
1343 * This function starts the ACS procedure if there are no
1344 * constraints like MBSSID DFS restrictions.
1345 *
1346 * Return: Status of ACS Start procedure
1347 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301348int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349{
1350
1351 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1352 tsap_Config_t *sap_config;
1353 tpWLAN_SAPEventCB acs_event_callback;
1354 int status;
1355
1356 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301357 if (hdd_ctx->acs_policy.acs_channel)
1358 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1359 else
1360 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361
1362 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001363 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001365
1366 if (status > 0) {
1367 /*notify hostapd about channel override */
1368 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1369 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1370 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 }
Jeff Johnson68755312017-02-10 11:46:55 -08001372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1374 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001375 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 return -EINVAL;
1377 }
1378
1379 acs_event_callback = hdd_hostapd_sap_event_cb;
1380
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301381 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301382 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301383 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 acs_event_callback, sap_config, adapter->dev);
1387
1388
1389 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001390 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001391 return -EINVAL;
1392 }
bings394afdd2017-01-09 11:22:38 +08001393 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1394 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1396
1397 return 0;
1398}
1399
1400/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301401 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1402 * @ap_adapter: AP adapter
1403 * @nol: Non-occupancy list
1404 * @nol_len: Length of NOL
1405 *
1406 * Get the NOL for SAP
1407 *
1408 * Return: Zero on success, non-zero on failure
1409 */
1410static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1411 uint32_t *nol_len)
1412{
1413 QDF_STATUS ret;
1414
1415 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1416 nol, nol_len);
1417 if (QDF_IS_STATUS_ERROR(ret))
1418 return -EINVAL;
1419
1420 return 0;
1421}
1422
1423/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301424 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1425 * @hdd_ctx: hdd context
1426 * @acs_chan_params: external acs channel params
1427 * @sap_config: SAP config
1428 *
1429 * This API provides unsorted pcl list.
1430 * this list is a subset of the valid channel list given by hostapd.
1431 * if channel is not present in pcl, weightage will be given as zero
1432 *
1433 * Return: Zero on success, non-zero on failure
1434 */
1435static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1436 struct hdd_vendor_acs_chan_params *acs_chan_params,
1437 tsap_Config_t *sap_config)
1438{
1439 int i, j;
1440
1441 for (i = 0; i < acs_chan_params->channel_count; i++) {
1442 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1443 if (acs_chan_params->channel_list[i] ==
1444 sap_config->acs_cfg.pcl_channels[j]) {
1445 acs_chan_params->vendor_pcl_list[i] =
1446 sap_config->acs_cfg.pcl_channels[j];
1447 acs_chan_params->vendor_weight_list[i] =
1448 sap_config->acs_cfg.
1449 pcl_channels_weight_list[j];
1450 break;
1451 } else {
1452 acs_chan_params->vendor_pcl_list[i] =
1453 acs_chan_params->channel_list[i];
1454 acs_chan_params->vendor_weight_list[i] = 0;
1455 }
1456 }
1457 }
1458 if (hdd_ctx->unsafe_channel_count == 0)
1459 return;
1460 /* Update unsafe channel weight as zero */
1461 for (i = 0; i < acs_chan_params->channel_count; i++) {
1462 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1463 if (acs_chan_params->channel_list[i] ==
1464 hdd_ctx->unsafe_channel_list[j]) {
1465 acs_chan_params->vendor_weight_list[i] = 0;
1466 }
1467 }
1468 }
1469}
1470
1471/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301472 * hdd_update_reg_chan_info : This API contructs channel info
1473 * for all the given channel
1474 * @adapter: pointer to SAP adapter struct
1475 * @channel_count: channel count
1476 * @channel_list: channel list
1477 *
1478 * Return: Status of of channel information updation
1479 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301480static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301481 uint32_t channel_count,
1482 uint8_t *channel_list)
1483{
1484 int i;
1485 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301486 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301487 uint8_t bw_offset = 0, chan = 0;
1488 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1489 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1490
1491 /* memory allocation */
1492 sap_config->channel_info = qdf_mem_malloc(
1493 sizeof(struct hdd_channel_info) *
1494 channel_count);
1495 if (!sap_config->channel_info) {
1496 hdd_err("memory allocation failed");
1497 return -ENOMEM;
1498
1499 }
1500 for (i = 0; i < channel_count; i++) {
1501 icv = &sap_config->channel_info[i];
1502 chan = channel_list[i];
1503
1504 if (chan == 0)
1505 continue;
1506
1507 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1508 bw_offset = 1 << BW_40_OFFSET_BIT;
1509 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1510 bw_offset = 1 << BW_20_OFFSET_BIT;
1511 icv->freq = cds_get_channel_freq(chan);
1512 icv->ieee_chan_number = chan;
1513 icv->max_reg_power = cds_get_channel_reg_power(chan);
1514
1515 /* filling demo values */
1516 icv->max_radio_power = HDD_MAX_TX_POWER;
1517 icv->min_radio_power = HDD_MIN_TX_POWER;
1518 /* not supported in current driver */
1519 icv->max_antenna_gain = 0;
1520
1521 icv->reg_class_id = wlan_hdd_find_opclass(
1522 WLAN_HDD_GET_HAL_CTX(adapter),
1523 chan, bw_offset);
1524
1525 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1526 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1527 cds_set_channel_params(chan, 0, &ch_params);
1528 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1529 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1530 }
1531 icv->flags = 0;
1532 icv->flags = cds_get_vendor_reg_flags(chan,
1533 sap_config->acs_cfg.ch_width,
1534 sap_config->acs_cfg.is_ht_enabled,
1535 sap_config->acs_cfg.is_vht_enabled,
1536 hdd_ctx->config->enable_sub_20_channel_width);
1537
1538 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1539 icv->freq, icv->flags,
1540 icv->flagext, icv->ieee_chan_number,
1541 icv->max_reg_power, icv->max_radio_power,
1542 icv->min_radio_power, icv->reg_class_id,
1543 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1544 icv->vht_center_freq_seg1);
1545 }
1546 return 0;
1547}
1548
1549/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1550#define CHAN_INFO_ATTR_FLAGS \
1551 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1552#define CHAN_INFO_ATTR_FLAG_EXT \
1553 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1554#define CHAN_INFO_ATTR_FREQ \
1555 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1556#define CHAN_INFO_ATTR_MAX_REG_POWER \
1557 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1558#define CHAN_INFO_ATTR_MAX_POWER \
1559 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1560#define CHAN_INFO_ATTR_MIN_POWER \
1561 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1562#define CHAN_INFO_ATTR_REG_CLASS_ID \
1563 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1564#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1565 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1566#define CHAN_INFO_ATTR_VHT_SEG_0 \
1567 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1568#define CHAN_INFO_ATTR_VHT_SEG_1 \
1569 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1570
1571/**
1572 * hdd_cfg80211_update_channel_info() - add channel info attributes
1573 * @skb: pointer to sk buff
1574 * @hdd_ctx: pointer to hdd station context
1575 * @idx: attribute index
1576 *
1577 * Return: Success(0) or reason code for failure
1578 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301579static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301580hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1581 tsap_Config_t *sap_config, int idx)
1582{
1583 struct nlattr *nla_attr, *channel;
1584 struct hdd_channel_info *icv;
1585 int i;
1586
1587 nla_attr = nla_nest_start(skb, idx);
1588 if (!nla_attr)
1589 goto fail;
1590
1591 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1592 channel = nla_nest_start(skb, i);
1593 if (!channel)
1594 goto fail;
1595
1596 icv = &sap_config->channel_info[i];
1597 if (!icv) {
1598 hdd_err("channel info not found");
1599 goto fail;
1600 }
1601 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1602 icv->freq) ||
1603 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1604 icv->flags) ||
1605 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1606 icv->flagext) ||
1607 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1608 icv->max_reg_power) ||
1609 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1610 icv->max_radio_power) ||
1611 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1612 icv->min_radio_power) ||
1613 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1614 icv->reg_class_id) ||
1615 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1616 icv->max_antenna_gain) ||
1617 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1618 icv->vht_center_freq_seg0) ||
1619 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1620 icv->vht_center_freq_seg1)) {
1621 hdd_err("put fail");
1622 goto fail;
1623 }
1624 nla_nest_end(skb, channel);
1625 }
1626 nla_nest_end(skb, nla_attr);
1627 return 0;
1628fail:
1629 hdd_err("nl channel update failed");
1630 return -EINVAL;
1631}
1632#undef CHAN_INFO_ATTR_FLAGS
1633#undef CHAN_INFO_ATTR_FLAG_EXT
1634#undef CHAN_INFO_ATTR_FREQ
1635#undef CHAN_INFO_ATTR_MAX_REG_POWER
1636#undef CHAN_INFO_ATTR_MAX_POWER
1637#undef CHAN_INFO_ATTR_MIN_POWER
1638#undef CHAN_INFO_ATTR_REG_CLASS_ID
1639#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1640#undef CHAN_INFO_ATTR_VHT_SEG_0
1641#undef CHAN_INFO_ATTR_VHT_SEG_1
1642
1643/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301644 * hdd_cfg80211_update_pcl() - add pcl info attributes
1645 * @skb: pointer to sk buff
1646 * @hdd_ctx: pointer to hdd station context
1647 * @idx: attribute index
1648 * @vendor_pcl_list: PCL list
1649 * @vendor_weight_list: PCL weights
1650 *
1651 * Return: Success(0) or reason code for failure
1652 */
1653static int32_t
1654hdd_cfg80211_update_pcl(struct sk_buff *skb,
1655 uint8_t ch_list_count, int idx,
1656 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1657{
1658 struct nlattr *nla_attr, *channel;
1659 int i;
1660
1661 nla_attr = nla_nest_start(skb, idx);
1662
1663 if (!nla_attr)
1664 goto fail;
1665
1666 for (i = 0; i < ch_list_count; i++) {
1667 channel = nla_nest_start(skb, i);
1668 if (!channel)
1669 goto fail;
1670 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1671 vendor_pcl_list[i]) ||
1672 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1673 vendor_weight_list[i])) {
1674 hdd_err("put fail");
1675 goto fail;
1676 }
1677 nla_nest_end(skb, channel);
1678 }
1679 nla_nest_end(skb, nla_attr);
1680
1681 return 0;
1682fail:
1683 hdd_err("updating pcl list failed");
1684 return -EINVAL;
1685}
1686
1687static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1688{
1689 /* Get scan band */
1690 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1691 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1692 *band = eCSR_BAND_24;
1693 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1694 *band = eCSR_BAND_5G;
1695 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1696 *band = eCSR_BAND_ALL;
1697 }
1698 /* Auto is not supported currently */
1699 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1700 hdd_err("invalid band");
1701 *band = eCSR_BAND_24;
1702 }
1703}
1704
1705void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1706 uint8_t reason)
1707{
1708 struct sk_buff *skb;
1709 tsap_Config_t *sap_config;
1710 uint32_t channel_count = 0, status;
1711 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1712 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1713 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1714 struct hdd_vendor_acs_chan_params acs_chan_params;
1715 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1716 eCsrBand band = eCSR_BAND_24;
1717 eCsrPhyMode phy_mode;
1718
1719 if (!hdd_ctx) {
1720 hdd_err("HDD context is NULL");
1721 return;
1722 }
1723
1724 ENTER();
1725 sap_config = &adapter->sessionCtx.ap.sapConfig;
1726
1727 /* Get valid channels for SAP */
1728 wlan_hdd_sap_get_valid_channellist(adapter,
1729 &channel_count, channel_list);
1730
1731 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1732 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1733 /* Get phymode */
1734 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1735
1736 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1737 &(adapter->wdev),
1738 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1739 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1740 GFP_KERNEL);
1741
1742 if (!skb) {
1743 hdd_err("cfg80211_vendor_event_alloc failed");
1744 return;
1745 }
1746 /*
1747 * Application expects pcl to be a subset of channel list
1748 * Remove all channels which are not in channel list from pcl
1749 * and add weight as zero
1750 */
1751 acs_chan_params.channel_count = channel_count;
1752 acs_chan_params.channel_list = channel_list;
1753 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1754 acs_chan_params.vendor_weight_list = vendor_weight_list;
1755
1756 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1757 sap_config);
1758 /* Update values in NL buffer */
1759 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1760 reason) ||
1761 nla_put_u8(skb,
1762 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1763 false) ||
1764 nla_put_u8(skb,
1765 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1766 true) ||
1767 nla_put_u8(skb,
1768 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1769 true) ||
1770 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1771 sap_config->acs_cfg.ch_width) ||
1772 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1773 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1774 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1775 band) ||
1776 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1777 phy_mode) ||
1778 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1779 channel_count, channel_list)) {
1780 hdd_err("nla put fail");
1781 goto fail;
1782 }
1783 status = hdd_cfg80211_update_pcl(skb, channel_count,
1784 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1785 vendor_pcl_list, vendor_weight_list);
1786
1787 if (status != 0)
1788 goto fail;
1789
1790 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1791 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1792
1793 if (status != 0)
1794 goto fail;
1795
1796 cfg80211_vendor_event(skb, GFP_KERNEL);
1797 return;
1798fail:
1799 if (skb)
1800 kfree_skb(skb);
1801}
1802
1803static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1804{
1805 struct hdd_external_acs_timer_context *timer_context;
1806
1807 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1808 return 0;
1809
1810 hdd_notice("Starting vendor app based ACS");
1811 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1812 timer_context->adapter = adapter;
1813
1814 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1815 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1816 QDF_TIMER_TYPE_SW,
1817 hdd_acs_response_timeout_handler, timer_context);
1818 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1819 return 0;
1820}
1821
1822/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1824 * @wiphy: Linux wiphy struct pointer
1825 * @wdev: Linux wireless device struct pointer
1826 * @data: ACS information from hostapd
1827 * @data_len: ACS information length
1828 *
1829 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1830 * and starts ACS procedure.
1831 *
1832 * Return: ACS procedure start status
1833 */
1834
1835static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1836 struct wireless_dev *wdev,
1837 const void *data, int data_len)
1838{
1839 struct net_device *ndev = wdev->netdev;
1840 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1841 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1842 tsap_Config_t *sap_config;
1843 struct sk_buff *temp_skbuff;
1844 int status = -EINVAL, i = 0;
1845 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1846 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301847 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848
1849 /* ***Note*** Donot set SME config related to ACS operation here because
1850 * ACS operation is not synchronouse and ACS for Second AP may come when
1851 * ACS operation for first AP is going on. So only do_acs is split to
1852 * seperate start_acs routine. Also SME-PMAC struct that is used to
1853 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1854 * config shall be set only from start_acs.
1855 */
1856
1857 /* nla_policy Policy template. Policy not applied as some attributes are
1858 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1859 *
1860 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1861 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1862 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1864 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1865 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1866 */
1867
Jeff Johnson1f61b612016-02-12 16:28:33 -08001868 ENTER_DEV(ndev);
1869
Anurag Chouhan6d760662016-02-20 16:05:43 +05301870 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871 hdd_err("Command not allowed in FTM mode");
1872 return -EPERM;
1873 }
1874
Kapil Gupta8878ad92017-02-13 11:56:04 +05301875 if (hdd_ctx->config->force_sap_acs &&
1876 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001877 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 return -EPERM;
1879 }
1880
1881 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301882 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301884
Naveen Rawat64e477e2016-05-20 10:34:56 -07001885 if (cds_is_sub_20_mhz_enabled()) {
1886 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1887 status = -EINVAL;
1888 goto out;
1889 }
1890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301892 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893
1894 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1895 NULL);
1896 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001897 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 goto out;
1899 }
1900
1901 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 goto out;
1904 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301905 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1906 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907
1908 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1909 ht_enabled =
1910 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1911 else
1912 ht_enabled = 0;
1913
1914 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1915 ht40_enabled =
1916 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1917 else
1918 ht40_enabled = 0;
1919
1920 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1921 vht_enabled =
1922 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1923 else
1924 vht_enabled = 0;
1925
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301926 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1927 vht_enabled = 0;
1928 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1929 }
1930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1932 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1933 } else {
1934 if (ht_enabled && ht40_enabled)
1935 ch_width = 40;
1936 else
1937 ch_width = 20;
1938 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301939
1940 /* this may be possible, when sap_force_11n_for_11ac is set */
1941 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1942 if (ht_enabled && ht40_enabled)
1943 ch_width = 40;
1944 else
1945 ch_width = 20;
1946 }
1947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 if (ch_width == 80)
1949 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1950 else if (ch_width == 40)
1951 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1952 else
1953 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1954
1955 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1956 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1957 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1958 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1959 * since it contains the frequency values of the channels in
1960 * the channel list.
1961 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1962 * is present
1963 */
1964 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1965 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1966 sap_config->acs_cfg.ch_list_count = nla_len(
1967 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1968 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301969 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970 sizeof(uint8_t) *
1971 sap_config->acs_cfg.ch_list_count);
1972 if (sap_config->acs_cfg.ch_list == NULL)
1973 goto out;
1974
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301975 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 sap_config->acs_cfg.ch_list_count);
1977 }
1978 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1979 uint32_t *freq =
1980 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1981 sap_config->acs_cfg.ch_list_count = nla_len(
1982 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1983 sizeof(uint32_t);
1984 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301985 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 sap_config->acs_cfg.ch_list_count);
1987 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001988 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 status = -ENOMEM;
1990 goto out;
1991 }
1992
1993 /* convert frequency to channel */
1994 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1995 sap_config->acs_cfg.ch_list[i] =
1996 ieee80211_frequency_to_channel(freq[i]);
1997 }
1998 }
1999
2000 hdd_debug("get pcl for DO_ACS vendor command");
2001
2002 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002003 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302004 sap_config->acs_cfg.pcl_channels,
2005 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302006 sap_config->acs_cfg.pcl_channels_weight_list,
2007 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302008 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002009 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302012 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2013 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07002014 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 vht_enabled = 1;
2016 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2017 sap_config->acs_cfg.ch_width =
2018 hdd_ctx->config->vhtChannelWidth;
2019 /* No VHT80 in 2.4G so perform ACS accordingly */
2020 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302021 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302023 ch_width = 40;
2024 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 }
2026
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302027 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2028
Jeff Johnson020db452016-06-29 14:37:26 -07002029 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 -08002030 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2031 ch_width, ht_enabled, vht_enabled,
2032 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2033
Kapil Gupta8878ad92017-02-13 11:56:04 +05302034 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2035 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2036
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07002038 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039 sap_config->acs_cfg.ch_list_count);
2040 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07002041 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 }
2043 sap_config->acs_cfg.acs_mode = true;
2044 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002045 /* ***Note*** Completion variable usage is not allowed
2046 * here since ACS scan operation may take max 2.2 sec
2047 * for 5G band:
2048 * 9 Active channel X 40 ms active scan time +
2049 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2051 * for this long. So we split up the scanning part.
2052 */
2053 set_bit(ACS_PENDING, &adapter->event_flags);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302054 hdd_notice("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055 status = 0;
2056 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302057 /* Check if vendor specific acs is enabled */
2058 if (hdd_ctx->config->vendor_acs_support) {
2059 sap_config->acs_cfg.hw_mode = hw_mode;
2060 hdd_create_acs_timer(adapter);
2061 hdd_update_acs_timer_reason(adapter,
2062 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2063 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2064 wlan_sap_set_vendor_acs(
2065 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2066 true);
2067 else
2068 wlan_sap_set_vendor_acs(
2069 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2070 false);
2071
2072 } else
2073 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002074 }
2075
2076out:
2077 if (0 == status) {
2078 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2079 NLMSG_HDRLEN);
2080 if (temp_skbuff != NULL)
2081 return cfg80211_vendor_cmd_reply(temp_skbuff);
2082 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002083 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2085
2086 return status;
2087}
2088
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002089/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002090 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2091 * @wiphy: Linux wiphy struct pointer
2092 * @wdev: Linux wireless device struct pointer
2093 * @data: ACS information from hostapd
2094 * @data_len: ACS information len
2095 *
2096 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2097 * and starts ACS procedure.
2098 *
2099 * Return: ACS procedure start status
2100 */
2101
2102static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2103 struct wireless_dev *wdev,
2104 const void *data, int data_len)
2105{
2106 int ret;
2107
2108 cds_ssr_protect(__func__);
2109 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2110 cds_ssr_unprotect(__func__);
2111
2112 return ret;
2113}
2114
2115/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002116 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2117 * @adapter: Pointer to adapter struct
2118 *
2119 * This function handle cleanup of what was done in DO_ACS, including free
2120 * memory.
2121 *
2122 * Return: void
2123 */
2124
2125void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2126{
2127 if (adapter == NULL)
2128 return;
2129 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2130 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2131 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2132 }
2133}
2134
2135/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002136 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2137 * @work: Linux workqueue struct pointer for ACS work
2138 *
2139 * This function starts the ACS procedure which was marked pending when an ACS
2140 * procedure was in progress for a concurrent SAP interface.
2141 *
2142 * Return: None
2143 */
2144
2145static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2146{
2147 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2148 acs_pending_work.work);
2149 wlan_hdd_cfg80211_start_acs(adapter);
2150}
2151
2152/**
2153 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2154 * @adapter: Pointer to SAP adapter struct
2155 * @pri_channel: SAP ACS procedure selected Primary channel
2156 * @sec_channel: SAP ACS procedure selected secondary channel
2157 *
2158 * This is a callback function from SAP module on ACS procedure is completed.
2159 * This function send the ACS selected channel information to hostapd
2160 *
2161 * Return: None
2162 */
2163
2164void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2165{
2166 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2167 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2168 struct sk_buff *vendor_event;
2169 int ret_val;
2170 hdd_adapter_t *con_sap_adapter;
2171 uint16_t ch_width;
2172
2173 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002174 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2176 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2177 GFP_KERNEL);
2178
2179 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002180 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 return;
2182 }
2183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 ret_val = nla_put_u8(vendor_event,
2185 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2186 sap_cfg->acs_cfg.pri_ch);
2187 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002188 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189 kfree_skb(vendor_event);
2190 return;
2191 }
2192
2193 ret_val = nla_put_u8(vendor_event,
2194 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2195 sap_cfg->acs_cfg.ht_sec_ch);
2196 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002197 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002198 kfree_skb(vendor_event);
2199 return;
2200 }
2201
2202 ret_val = nla_put_u8(vendor_event,
2203 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2204 sap_cfg->acs_cfg.vht_seg0_center_ch);
2205 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002206 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207 kfree_skb(vendor_event);
2208 return;
2209 }
2210
2211 ret_val = nla_put_u8(vendor_event,
2212 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2213 sap_cfg->acs_cfg.vht_seg1_center_ch);
2214 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002215 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216 kfree_skb(vendor_event);
2217 return;
2218 }
2219
2220 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2221 ch_width = 80;
2222 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2223 ch_width = 40;
2224 else
2225 ch_width = 20;
2226
2227 ret_val = nla_put_u16(vendor_event,
2228 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2229 ch_width);
2230 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002231 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 kfree_skb(vendor_event);
2233 return;
2234 }
2235 if (sap_cfg->acs_cfg.pri_ch > 14)
2236 ret_val = nla_put_u8(vendor_event,
2237 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2238 QCA_ACS_MODE_IEEE80211A);
2239 else
2240 ret_val = nla_put_u8(vendor_event,
2241 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2242 QCA_ACS_MODE_IEEE80211G);
2243
2244 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002245 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246 kfree_skb(vendor_event);
2247 return;
2248 }
2249
Jeff Johnson46b40792016-06-29 14:03:14 -07002250 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 -08002251 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2252 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2253 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2254
2255 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2256 /* ***Note*** As already mentioned Completion variable usage is not
2257 * allowed here since ACS scan operation may take max 2.2 sec.
2258 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2259 * operation.
2260 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2261 * when Primary AP ACS is complete and secondary AP ACS is started here
2262 * immediately, Primary AP start_bss may come inbetween ACS operation
2263 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2264 * delay. This path and below constraint will be removed on sessionizing
2265 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2266 * As per design constraint user space control application must take
2267 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2268 * this code path. Sec AP hostapd should be started after Primary AP
2269 * start beaconing which can be confirmed by getchannel iwpriv command
2270 */
2271
2272 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2273 if (con_sap_adapter &&
2274 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2276 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 /* Lets give 500ms for OBSS + START_BSS to complete */
2278 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2279 msecs_to_jiffies(500));
2280 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2281 }
2282
2283 return;
2284}
2285
2286static int
2287__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2288 struct wireless_dev *wdev,
2289 const void *data,
2290 int data_len)
2291{
2292 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2293 struct sk_buff *skb = NULL;
2294 uint32_t fset = 0;
2295 int ret;
2296
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002297 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302298
Anurag Chouhan6d760662016-02-20 16:05:43 +05302299 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 hdd_err("Command not allowed in FTM mode");
2301 return -EPERM;
2302 }
2303
2304 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302305 if (ret)
2306 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002307
2308 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002309 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310 fset |= WIFI_FEATURE_INFRA;
2311 }
2312 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002313 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314 fset |= WIFI_FEATURE_INFRA_5G;
2315 }
2316#ifdef WLAN_FEATURE_P2P
2317 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2318 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002319 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002320 fset |= WIFI_FEATURE_P2P;
2321 }
2322#endif
2323 fset |= WIFI_FEATURE_SOFT_AP;
2324
2325 /* HOTSPOT is a supplicant feature, enable it by default */
2326 fset |= WIFI_FEATURE_HOTSPOT;
2327
2328#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302329 if (pHddCtx->config->extscan_enabled &&
2330 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002331 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2333 }
2334#endif
2335 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002336 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 fset |= WIFI_FEATURE_NAN;
2338 }
2339 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002340 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341 fset |= WIFI_FEATURE_D2D_RTT;
2342 fset |= WIFI_FEATURE_D2AP_RTT;
2343 }
2344#ifdef FEATURE_WLAN_SCAN_PNO
2345 if (pHddCtx->config->configPNOScanSupport &&
2346 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002347 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348 fset |= WIFI_FEATURE_PNO;
2349 }
2350#endif
2351 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2352#ifdef FEATURE_WLAN_TDLS
2353 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2354 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002355 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 fset |= WIFI_FEATURE_TDLS;
2357 }
2358 if (sme_is_feature_supported_by_fw(TDLS) &&
2359 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2360 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002361 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2363 }
2364#endif
2365#ifdef WLAN_AP_STA_CONCURRENCY
2366 fset |= WIFI_FEATURE_AP_STA;
2367#endif
2368 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002369 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370
2371 if (hdd_link_layer_stats_supported())
2372 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2373
2374 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2375 NLMSG_HDRLEN);
2376 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 return -EINVAL;
2379 }
Jeff Johnson020db452016-06-29 14:37:26 -07002380 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002382 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 goto nla_put_failure;
2384 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302385 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302386 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387nla_put_failure:
2388 kfree_skb(skb);
2389 return -EINVAL;
2390}
2391
2392/**
2393 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2394 * @wiphy: pointer to wireless wiphy structure.
2395 * @wdev: pointer to wireless_dev structure.
2396 * @data: Pointer to the data to be passed via vendor interface
2397 * @data_len:Length of the data to be passed
2398 *
2399 * Return: Return the Success or Failure code.
2400 */
2401static int
2402wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2403 struct wireless_dev *wdev,
2404 const void *data, int data_len)
2405{
2406 int ret = 0;
2407
2408 cds_ssr_protect(__func__);
2409 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2410 data, data_len);
2411 cds_ssr_unprotect(__func__);
2412
2413 return ret;
2414}
2415
2416/**
2417 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2418 * @wiphy: pointer to wireless wiphy structure.
2419 * @wdev: pointer to wireless_dev structure.
2420 * @data: Pointer to the data to be passed via vendor interface
2421 * @data_len:Length of the data to be passed
2422 *
2423 * Set the MAC address that is to be used for scanning.
2424 *
2425 * Return: Return the Success or Failure code.
2426 */
2427static int
2428__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2429 struct wireless_dev *wdev,
2430 const void *data,
2431 int data_len)
2432{
2433 tpSirScanMacOui pReqMsg = NULL;
2434 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2435 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302436 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 int ret;
2438
Jeff Johnson1f61b612016-02-12 16:28:33 -08002439 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440
Anurag Chouhan6d760662016-02-20 16:05:43 +05302441 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 hdd_err("Command not allowed in FTM mode");
2443 return -EPERM;
2444 }
2445
2446 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302447 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449
2450 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002451 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 return -ENOTSUPP;
2453 }
2454
2455 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2456 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 return -EINVAL;
2459 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302460 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002462 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 return -ENOMEM;
2464 }
2465 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002466 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 goto fail;
2468 }
2469 nla_memcpy(&pReqMsg->oui[0],
2470 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2471 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002472 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 pReqMsg->oui[1], pReqMsg->oui[2]);
2474 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302475 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002476 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 goto fail;
2478 }
2479 return 0;
2480fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302481 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 return -EINVAL;
2483}
2484
2485/**
2486 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2487 * @wiphy: pointer to wireless wiphy structure.
2488 * @wdev: pointer to wireless_dev structure.
2489 * @data: Pointer to the data to be passed via vendor interface
2490 * @data_len:Length of the data to be passed
2491 *
2492 * Set the MAC address that is to be used for scanning. This is an
2493 * SSR-protecting wrapper function.
2494 *
2495 * Return: Return the Success or Failure code.
2496 */
2497static int
2498wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2499 struct wireless_dev *wdev,
2500 const void *data,
2501 int data_len)
2502{
2503 int ret;
2504
2505 cds_ssr_protect(__func__);
2506 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2507 data, data_len);
2508 cds_ssr_unprotect(__func__);
2509
2510 return ret;
2511}
2512
2513/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302514 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2515 * @wiphy: pointer phy adapter
2516 * @wdev: pointer to wireless device structure
2517 * @data: pointer to data buffer
2518 * @data_len: length of data
2519 *
2520 * This routine will give concurrency matrix
2521 *
2522 * Return: int status code
2523 */
2524static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2525 struct wireless_dev *wdev,
2526 const void *data,
2527 int data_len)
2528{
2529 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2530 uint8_t i, feature_sets, max_feature_sets;
2531 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2532 struct sk_buff *reply_skb;
2533 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2534 int ret;
2535
2536 ENTER_DEV(wdev->netdev);
2537
2538 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2539 hdd_err("Command not allowed in FTM mode");
2540 return -EPERM;
2541 }
2542
2543 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302544 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302545 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302546
2547 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2548 data, data_len, NULL)) {
2549 hdd_err("Invalid ATTR");
2550 return -EINVAL;
2551 }
2552
2553 /* Parse and fetch max feature set */
2554 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2555 hdd_err("Attr max feature set size failed");
2556 return -EINVAL;
2557 }
2558 max_feature_sets = nla_get_u32(tb[
2559 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2560 hdd_info("Max feature set size: %d", max_feature_sets);
2561
2562 /* Fill feature combination matrix */
2563 feature_sets = 0;
2564 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002565 WIFI_FEATURE_P2P;
2566 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2567 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302568 /* Add more feature combinations here */
2569
2570 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002571 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302572 hdd_info("Feature set matrix");
2573 for (i = 0; i < feature_sets; i++)
2574 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2575
2576 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2577 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2578 if (!reply_skb) {
2579 hdd_err("Feature set matrix: buffer alloc fail");
2580 return -ENOMEM;
2581 }
2582
2583 if (nla_put_u32(reply_skb,
2584 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2585 feature_sets) ||
2586 nla_put(reply_skb,
2587 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2588 sizeof(u32) * feature_sets,
2589 feature_set_matrix)) {
2590 hdd_err("nla put fail");
2591 kfree_skb(reply_skb);
2592 return -EINVAL;
2593 }
2594 return cfg80211_vendor_cmd_reply(reply_skb);
2595}
2596
2597/**
2598 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2599 * @wiphy: pointer to wireless wiphy structure.
2600 * @wdev: pointer to wireless_dev structure.
2601 * @data: Pointer to the data to be passed via vendor interface
2602 * @data_len:Length of the data to be passed
2603 *
2604 * Retrieves the concurrency feature set matrix
2605 *
2606 * Return: 0 on success, negative errno on failure
2607 */
2608static int
2609wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2610 struct wireless_dev *wdev,
2611 const void *data,
2612 int data_len)
2613{
2614 int ret;
2615
2616 cds_ssr_protect(__func__);
2617 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2618 data, data_len);
2619 cds_ssr_unprotect(__func__);
2620
2621 return ret;
2622}
2623
2624/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2626 * @feature_flags: pointer to the byte array of features.
2627 * @feature: Feature to be turned ON in the byte array.
2628 *
2629 * Return: None
2630 *
2631 * This is called to turn ON or SET the feature flag for the requested feature.
2632 **/
2633#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002634static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2635 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636{
2637 uint32_t index;
2638 uint8_t bit_mask;
2639
2640 index = feature / NUM_BITS_IN_BYTE;
2641 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2642 feature_flags[index] |= bit_mask;
2643}
2644
2645/**
2646 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2647 * @wiphy: pointer to wireless wiphy structure.
2648 * @wdev: pointer to wireless_dev structure.
2649 * @data: Pointer to the data to be passed via vendor interface
2650 * @data_len:Length of the data to be passed
2651 *
2652 * This is called when wlan driver needs to send supported feature set to
2653 * supplicant upon a request/query from the supplicant.
2654 *
2655 * Return: Return the Success or Failure code.
2656 **/
2657#define MAX_CONCURRENT_CHAN_ON_24G 2
2658#define MAX_CONCURRENT_CHAN_ON_5G 2
2659static int
2660__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2661 struct wireless_dev *wdev,
2662 const void *data, int data_len)
2663{
2664 struct sk_buff *skb = NULL;
2665 uint32_t dbs_capability = 0;
2666 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302667 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 int ret_val;
2669
2670 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2671 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2672
Jeff Johnson1f61b612016-02-12 16:28:33 -08002673 ENTER_DEV(wdev->netdev);
2674
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2676 if (ret_val)
2677 return ret_val;
2678
Anurag Chouhan6d760662016-02-20 16:05:43 +05302679 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 hdd_err("Command not allowed in FTM mode");
2681 return -EPERM;
2682 }
2683
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002684 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002685 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002686 wlan_hdd_cfg80211_set_feature(feature_flags,
2687 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2688 }
2689
2690 wlan_hdd_cfg80211_set_feature(feature_flags,
2691 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2692 if (wma_is_scan_simultaneous_capable())
2693 wlan_hdd_cfg80211_set_feature(feature_flags,
2694 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002695
2696 if (wma_is_p2p_lo_capable())
2697 wlan_hdd_cfg80211_set_feature(feature_flags,
2698 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2699
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2701 NLMSG_HDRLEN);
2702
2703 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002704 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 return -ENOMEM;
2706 }
2707
2708 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2709 sizeof(feature_flags), feature_flags))
2710 goto nla_put_failure;
2711
2712 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302713 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 if (one_by_one_dbs)
2715 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2716
2717 if (two_by_two_dbs)
2718 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2719
2720 if (!one_by_one_dbs && !two_by_two_dbs)
2721 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2722 } else {
2723 hdd_err("wma_get_dbs_hw_mode failed");
2724 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2725 }
2726
2727 hdd_info("dbs_capability is %d", dbs_capability);
2728
2729 if (nla_put_u32(skb,
2730 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2731 MAX_CONCURRENT_CHAN_ON_24G))
2732 goto nla_put_failure;
2733
2734 if (nla_put_u32(skb,
2735 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2736 MAX_CONCURRENT_CHAN_ON_5G))
2737 goto nla_put_failure;
2738
2739 return cfg80211_vendor_cmd_reply(skb);
2740
2741nla_put_failure:
2742 kfree_skb(skb);
2743 return -EINVAL;
2744}
2745
2746/**
2747 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2748 * @wiphy: pointer to wireless wiphy structure.
2749 * @wdev: pointer to wireless_dev structure.
2750 * @data: Pointer to the data to be passed via vendor interface
2751 * @data_len:Length of the data to be passed
2752 *
2753 * This is called when wlan driver needs to send supported feature set to
2754 * supplicant upon a request/query from the supplicant.
2755 *
2756 * Return: Return the Success or Failure code.
2757 */
2758static int
2759wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2760 struct wireless_dev *wdev,
2761 const void *data, int data_len)
2762{
2763 int ret;
2764
2765 cds_ssr_protect(__func__);
2766 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2767 data, data_len);
2768 cds_ssr_unprotect(__func__);
2769
2770 return ret;
2771}
2772
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302773#define PARAM_NUM_NW \
2774 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2775#define PARAM_SET_BSSID \
2776 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2777#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2778#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779
2780/**
2781 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2782 * @wiphy: The wiphy structure
2783 * @wdev: The wireless device
2784 * @data: Data passed by framework
2785 * @data_len: Parameters to be configured passed as data
2786 *
2787 * The roaming related parameters are configured by the framework
2788 * using this interface.
2789 *
2790 * Return: Return either success or failure code.
2791 */
2792static int
2793__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2794 struct wireless_dev *wdev, const void *data, int data_len)
2795{
2796 struct net_device *dev = wdev->netdev;
2797 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2798 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2799 uint8_t session_id;
2800 struct roam_ext_params roam_params;
2801 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302802 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002803 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2804 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2805 int rem, i;
2806 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002807 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808 int ret;
2809
Jeff Johnson1f61b612016-02-12 16:28:33 -08002810 ENTER_DEV(dev);
2811
Anurag Chouhan6d760662016-02-20 16:05:43 +05302812 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 hdd_err("Command not allowed in FTM mode");
2814 return -EPERM;
2815 }
2816
2817 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302818 if (ret)
2819 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820
2821 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2822 data, data_len,
2823 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002824 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 return -EINVAL;
2826 }
2827 /* Parse and fetch Command Type*/
2828 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002829 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 goto fail;
2831 }
2832 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302833 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2835 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002836 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837 goto fail;
2838 }
2839 req_id = nla_get_u32(
2840 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002841 hdd_debug("Req Id (%d)", req_id);
2842 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 switch (cmd_type) {
2844 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2845 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302846 if (tb[PARAM_NUM_NW]) {
2847 count = nla_get_u32(
2848 tb[PARAM_NUM_NW]);
2849 } else {
2850 hdd_err("Number of networks is not provided");
2851 goto fail;
2852 }
2853
2854 if (count &&
2855 tb[PRAM_SSID_LIST]) {
2856 nla_for_each_nested(curr_attr,
2857 tb[PRAM_SSID_LIST], rem) {
2858 if (nla_parse(tb2,
2859 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2860 nla_data(curr_attr), nla_len(curr_attr),
2861 NULL)) {
2862 hdd_err("nla_parse failed");
2863 goto fail;
2864 }
2865 /* Parse and Fetch allowed SSID list*/
2866 if (!tb2[PARAM_LIST_SSID]) {
2867 hdd_err("attr allowed ssid failed");
2868 goto fail;
2869 }
2870 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2871 /*
2872 * Upper Layers include a null termination
2873 * character. Check for the actual permissible
2874 * length of SSID and also ensure not to copy
2875 * the NULL termination character to the driver
2876 * buffer.
2877 */
2878 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2879 ((buf_len - 1) <=
2880 SIR_MAC_MAX_SSID_LENGTH)) {
2881 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302883 tb2[PARAM_LIST_SSID], buf_len - 1);
2884 roam_params.ssid_allowed_list[i].length
2885 = buf_len - 1;
2886 hdd_debug("SSID[%d]: %.*s,length = %d",
2887 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888 roam_params.ssid_allowed_list[i].length,
2889 roam_params.ssid_allowed_list[i].ssId,
2890 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302891 i++;
2892 } else {
2893 hdd_err("Invalid buffer length");
2894 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 }
2896 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302897 if (i != count) {
2898 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2899 i, count);
2900 goto fail;
2901 }
2902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002903 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002904 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 roam_params.num_ssid_allowed_list);
2906 sme_update_roam_params(pHddCtx->hHal, session_id,
2907 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2908 break;
2909 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2910 /* Parse and fetch 5G Boost Threshold */
2911 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002912 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913 goto fail;
2914 }
2915 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2916 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002917 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918 roam_params.raise_rssi_thresh_5g);
2919 /* Parse and fetch 5G Penalty Threshold */
2920 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002921 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 goto fail;
2923 }
2924 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2925 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002926 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 roam_params.drop_rssi_thresh_5g);
2928 /* Parse and fetch 5G Boost Factor */
2929 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002930 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 goto fail;
2932 }
2933 roam_params.raise_factor_5g = nla_get_u32(
2934 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002935 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 roam_params.raise_factor_5g);
2937 /* Parse and fetch 5G Penalty factor */
2938 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002939 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 goto fail;
2941 }
2942 roam_params.drop_factor_5g = nla_get_u32(
2943 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002944 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 roam_params.drop_factor_5g);
2946 /* Parse and fetch 5G Max Boost */
2947 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002948 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 goto fail;
2950 }
2951 roam_params.max_raise_rssi_5g = nla_get_u32(
2952 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002953 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 roam_params.max_raise_rssi_5g);
2955 /* Parse and fetch Rssi Diff */
2956 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002957 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 goto fail;
2959 }
2960 roam_params.rssi_diff = nla_get_s32(
2961 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002962 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 roam_params.rssi_diff);
2964 /* Parse and fetch Alert Rssi Threshold */
2965 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002966 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 goto fail;
2968 }
2969 roam_params.alert_rssi_threshold = nla_get_u32(
2970 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002971 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002972 roam_params.alert_rssi_threshold);
2973 sme_update_roam_params(pHddCtx->hHal, session_id,
2974 roam_params,
2975 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2976 break;
2977 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2978 /* Parse and fetch Activate Good Rssi Roam */
2979 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002980 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 goto fail;
2982 }
2983 roam_params.good_rssi_roam = nla_get_s32(
2984 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002985 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002986 roam_params.good_rssi_roam);
2987 sme_update_roam_params(pHddCtx->hHal, session_id,
2988 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2989 break;
2990 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2991 /* Parse and fetch number of preferred BSSID */
2992 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002993 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994 goto fail;
2995 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002996 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002998 if (count > MAX_BSSID_FAVORED) {
2999 hdd_err("Preferred BSSID count %u exceeds max %u",
3000 count, MAX_BSSID_FAVORED);
3001 goto fail;
3002 }
3003 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003004 i = 0;
3005 nla_for_each_nested(curr_attr,
3006 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3007 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003008
3009 if (i == count) {
3010 hdd_warn("Ignoring excess Preferred BSSID");
3011 break;
3012 }
3013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014 if (nla_parse(tb2,
3015 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3016 nla_data(curr_attr), nla_len(curr_attr),
3017 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003018 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019 goto fail;
3020 }
3021 /* Parse and fetch MAC address */
3022 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003023 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 goto fail;
3025 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003026 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303028 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003029 hdd_debug(MAC_ADDRESS_STR,
3030 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 /* Parse and fetch preference factor*/
3032 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003033 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 goto fail;
3035 }
3036 roam_params.bssid_favored_factor[i] = nla_get_u32(
3037 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003038 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 roam_params.bssid_favored_factor[i]);
3040 i++;
3041 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003042 if (i < count)
3043 hdd_warn("Num Preferred BSSID %u less than expected %u",
3044 i, count);
3045 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046 sme_update_roam_params(pHddCtx->hHal, session_id,
3047 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3048 break;
3049 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3050 /* Parse and fetch number of blacklist BSSID */
3051 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003052 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053 goto fail;
3054 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003055 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003057 if (count > MAX_BSSID_AVOID_LIST) {
3058 hdd_err("Blacklist BSSID count %u exceeds max %u",
3059 count, MAX_BSSID_AVOID_LIST);
3060 goto fail;
3061 }
3062 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003063 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303064
3065 if (count &&
3066 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3067 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3069 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003070
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303071 if (i == count) {
3072 hdd_warn("Ignoring excess Blacklist BSSID");
3073 break;
3074 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003075
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303076 if (nla_parse(tb2,
3077 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3078 nla_data(curr_attr), nla_len(curr_attr),
3079 NULL)) {
3080 hdd_err("nla_parse failed");
3081 goto fail;
3082 }
3083 /* Parse and fetch MAC address */
3084 if (!tb2[PARAM_SET_BSSID]) {
3085 hdd_err("attr blacklist addr failed");
3086 goto fail;
3087 }
3088 nla_memcpy(
3089 roam_params.bssid_avoid_list[i].bytes,
3090 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3091 hdd_debug(MAC_ADDRESS_STR,
3092 MAC_ADDR_ARRAY(
3093 roam_params.bssid_avoid_list[i].bytes));
3094 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003095 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003097 if (i < count)
3098 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3099 i, count);
3100 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 sme_update_roam_params(pHddCtx->hHal, session_id,
3102 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3103 break;
3104 }
3105 return 0;
3106fail:
3107 return -EINVAL;
3108}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303109#undef PARAM_NUM_NW
3110#undef PARAM_SET_BSSID
3111#undef PRAM_SSID_LIST
3112#undef PARAM_LIST_SSID
3113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114
3115/**
3116 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3117 * @wiphy: pointer to wireless wiphy structure.
3118 * @wdev: pointer to wireless_dev structure.
3119 * @data: Pointer to the data to be passed via vendor interface
3120 * @data_len:Length of the data to be passed
3121 *
3122 * Return: Return the Success or Failure code.
3123 */
3124static int
3125wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3126 struct wireless_dev *wdev,
3127 const void *data,
3128 int data_len)
3129{
3130 int ret;
3131
3132 cds_ssr_protect(__func__);
3133 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3134 data, data_len);
3135 cds_ssr_unprotect(__func__);
3136
3137 return ret;
3138}
3139
3140static const struct nla_policy
3141wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3142 +1] = {
3143 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3144};
3145
3146/**
3147 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3148 * @hdd_ctx: HDD context
3149 * @device_mode: device mode
3150 * Return: bool
3151 */
3152static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003153 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154{
3155 hdd_adapter_t *adapter;
3156 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3157 hdd_ap_ctx_t *ap_ctx;
3158 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303159 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303161 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 &adapter_node);
3163
3164 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 adapter = adapter_node->pAdapter;
3167
3168 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003169 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 ap_ctx =
3171 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3172
3173 /*
3174 * if there is SAP already running on DFS channel,
3175 * do not disable scan on dfs channels. Note that
3176 * with SAP on DFS, there cannot be conurrency on
3177 * single radio. But then we can have multiple
3178 * radios !!
3179 */
3180 if (CHANNEL_STATE_DFS ==
3181 cds_get_channel_state(
3182 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003183 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003184 return true;
3185 }
3186 }
3187
3188 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003189 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 sta_ctx =
3191 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3192
3193 /*
3194 * if STA is already connected on DFS channel,
3195 * do not disable scan on dfs channels
3196 */
3197 if (hdd_conn_is_connected(sta_ctx) &&
3198 (CHANNEL_STATE_DFS ==
3199 cds_get_channel_state(
3200 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003201 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 return true;
3203 }
3204 }
3205
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303206 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 adapter_node,
3208 &next);
3209 adapter_node = next;
3210 }
3211
3212 return false;
3213}
3214
3215/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003216 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3217 * @hdd_ctx: HDD context within host driver
3218 * @adapter: Adapter pointer
3219 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3220 *
3221 * Loops through devices to see who is operating on DFS channels
3222 * and then disables/enables DFS channels by calling SME API.
3223 * Fails the disable request if any device is active on a DFS channel.
3224 *
3225 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003226 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003227
3228int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3229 hdd_adapter_t *adapter,
3230 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003231{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303233 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235
3236 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3237 if (no_dfs_flag) {
3238 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003239 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240
3241 if (true == status)
3242 return -EOPNOTSUPP;
3243
3244 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003245 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246
3247 if (true == status)
3248 return -EOPNOTSUPP;
3249 }
3250
3251 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3252
3253 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3254
3255 /*
3256 * call the SME API to tunnel down the new channel list
3257 * to the firmware
3258 */
3259 status = sme_handle_dfs_chan_scan(
3260 h_hal, hdd_ctx->config->enableDFSChnlScan);
3261
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303262 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 ret_val = 0;
3264
3265 /*
3266 * Clear the SME scan cache also. Note that the
3267 * clearing of scan results is independent of session;
3268 * so no need to iterate over
3269 * all sessions
3270 */
3271 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303272 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 ret_val = -EPERM;
3274 }
3275
3276 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003277 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 ret_val = 0;
3279 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003280 return ret_val;
3281}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003283/**
3284 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3285 * @wiphy: corestack handler
3286 * @wdev: wireless device
3287 * @data: data
3288 * @data_len: data length
3289 * Return: success(0) or reason code for failure
3290 */
3291static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3292 struct wireless_dev *wdev,
3293 const void *data,
3294 int data_len)
3295{
3296 struct net_device *dev = wdev->netdev;
3297 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3298 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3299 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3300 int ret_val;
3301 uint32_t no_dfs_flag = 0;
3302
Jeff Johnson1f61b612016-02-12 16:28:33 -08003303 ENTER_DEV(dev);
3304
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003305 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303306 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003307 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003308
3309 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3310 data, data_len,
3311 wlan_hdd_set_no_dfs_flag_config_policy)) {
3312 hdd_err("invalid attr");
3313 return -EINVAL;
3314 }
3315
3316 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3317 hdd_err("attr dfs flag failed");
3318 return -EINVAL;
3319 }
3320
3321 no_dfs_flag = nla_get_u32(
3322 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3323
Jeff Johnson020db452016-06-29 14:37:26 -07003324 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003325
3326 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003327 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003328 return -EINVAL;
3329 }
3330
3331 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3332 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333 return ret_val;
3334}
3335
3336/**
3337 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3338 *
3339 * @wiphy: wiphy device pointer
3340 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003341 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342 * @data_len: Buffer length
3343 *
3344 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3345 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3346 *
3347 * Return: EOK or other error codes.
3348 */
3349
3350static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3351 struct wireless_dev *wdev,
3352 const void *data,
3353 int data_len)
3354{
3355 int ret;
3356
3357 cds_ssr_protect(__func__);
3358 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3359 data, data_len);
3360 cds_ssr_unprotect(__func__);
3361
3362 return ret;
3363}
3364
Manikandan Mohan80dea792016-04-28 16:36:48 -07003365static const struct nla_policy
3366wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3367 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3368};
3369
3370/**
3371 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3372 * @wiphy: wiphy device pointer
3373 * @wdev: wireless device pointer
3374 * @data: Vendor command data buffer
3375 * @data_len: Buffer length
3376 *
3377 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3378 * setup WISA Mode features.
3379 *
3380 * Return: Success(0) or reason code for failure
3381 */
3382static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3383 struct wireless_dev *wdev, const void *data, int data_len)
3384{
3385 struct net_device *dev = wdev->netdev;
3386 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3387 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3388 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3389 struct sir_wisa_params wisa;
3390 int ret_val;
3391 QDF_STATUS status;
3392 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003393 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3394 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003395
3396 ENTER_DEV(dev);
3397 ret_val = wlan_hdd_validate_context(hdd_ctx);
3398 if (ret_val)
3399 goto err;
3400
3401 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3402 hdd_err("Command not allowed in FTM mode");
3403 return -EPERM;
3404 }
3405
3406 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3407 wlan_hdd_wisa_cmd_policy)) {
3408 hdd_err("Invalid WISA cmd attributes");
3409 ret_val = -EINVAL;
3410 goto err;
3411 }
3412 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3413 hdd_err("Invalid WISA mode");
3414 ret_val = -EINVAL;
3415 goto err;
3416 }
3417
3418 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3419 hdd_info("WISA Mode: %d", wisa_mode);
3420 wisa.mode = wisa_mode;
3421 wisa.vdev_id = adapter->sessionId;
3422 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003423 if (!QDF_IS_STATUS_SUCCESS(status)) {
3424 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003425 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003426 }
3427 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003428 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003429 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3430 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003431 adapter->sessionId),
3432 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003433err:
3434 EXIT();
3435 return ret_val;
3436}
3437
3438/**
3439 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3440 * @wiphy: corestack handler
3441 * @wdev: wireless device
3442 * @data: data
3443 * @data_len: data length
3444 *
3445 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3446 * setup WISA mode features.
3447 *
3448 * Return: Success(0) or reason code for failure
3449 */
3450static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3451 struct wireless_dev *wdev,
3452 const void *data,
3453 int data_len)
3454{
3455 int ret;
3456
3457 cds_ssr_protect(__func__);
3458 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3459 cds_ssr_unprotect(__func__);
3460
3461 return ret;
3462}
3463
Anurag Chouhan96919482016-07-13 16:36:57 +05303464/*
3465 * define short names for the global vendor params
3466 * used by __wlan_hdd_cfg80211_get_station_cmd()
3467 */
3468#define STATION_INVALID \
3469 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3470#define STATION_INFO \
3471 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3472#define STATION_ASSOC_FAIL_REASON \
3473 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3474#define STATION_MAX \
3475 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3476
3477static const struct nla_policy
3478hdd_get_station_policy[STATION_MAX + 1] = {
3479 [STATION_INFO] = {.type = NLA_FLAG},
3480 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3481};
3482
3483/**
3484 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3485 * @hdd_ctx: HDD context within host driver
3486 * @wdev: wireless device
3487 *
3488 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3489 * Validate cmd attributes and send the station info to upper layers.
3490 *
3491 * Return: Success(0) or reason code for failure
3492 */
3493static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3494 hdd_adapter_t *adapter)
3495{
3496 struct sk_buff *skb = NULL;
3497 uint32_t nl_buf_len;
3498 hdd_station_ctx_t *hdd_sta_ctx;
3499
3500 nl_buf_len = NLMSG_HDRLEN;
3501 nl_buf_len += sizeof(uint32_t);
3502 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3503
3504 if (!skb) {
3505 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3506 return -ENOMEM;
3507 }
3508
3509 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3510
3511 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3512 hdd_sta_ctx->conn_info.assoc_status_code)) {
3513 hdd_err("put fail");
3514 goto fail;
3515 }
3516 return cfg80211_vendor_cmd_reply(skb);
3517fail:
3518 if (skb)
3519 kfree_skb(skb);
3520 return -EINVAL;
3521}
3522
3523/**
3524 * hdd_map_auth_type() - transform auth type specific to
3525 * vendor command
3526 * @auth_type: csr auth type
3527 *
3528 * Return: Success(0) or reason code for failure
3529 */
3530static int hdd_convert_auth_type(uint32_t auth_type)
3531{
3532 uint32_t ret_val;
3533
3534 switch (auth_type) {
3535 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3536 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3537 break;
3538 case eCSR_AUTH_TYPE_SHARED_KEY:
3539 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3540 break;
3541 case eCSR_AUTH_TYPE_WPA:
3542 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3543 break;
3544 case eCSR_AUTH_TYPE_WPA_PSK:
3545 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3546 break;
3547 case eCSR_AUTH_TYPE_AUTOSWITCH:
3548 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3549 break;
3550 case eCSR_AUTH_TYPE_WPA_NONE:
3551 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3552 break;
3553 case eCSR_AUTH_TYPE_RSN:
3554 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3555 break;
3556 case eCSR_AUTH_TYPE_RSN_PSK:
3557 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3558 break;
3559 case eCSR_AUTH_TYPE_FT_RSN:
3560 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3561 break;
3562 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3563 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3564 break;
3565 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3566 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3567 break;
3568 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3569 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3570 break;
3571 case eCSR_AUTH_TYPE_CCKM_WPA:
3572 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3573 break;
3574 case eCSR_AUTH_TYPE_CCKM_RSN:
3575 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3576 break;
3577 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3578 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3579 break;
3580 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3581 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3582 break;
3583 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3584 case eCSR_AUTH_TYPE_FAILED:
3585 case eCSR_AUTH_TYPE_NONE:
3586 default:
3587 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3588 break;
3589 }
3590 return ret_val;
3591}
3592
3593/**
3594 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3595 * vendor command
3596 * @dot11mode: dot11mode
3597 *
3598 * Return: Success(0) or reason code for failure
3599 */
3600static int hdd_convert_dot11mode(uint32_t dot11mode)
3601{
3602 uint32_t ret_val;
3603
3604 switch (dot11mode) {
3605 case eCSR_CFG_DOT11_MODE_11A:
3606 ret_val = QCA_WLAN_802_11_MODE_11A;
3607 break;
3608 case eCSR_CFG_DOT11_MODE_11B:
3609 ret_val = QCA_WLAN_802_11_MODE_11B;
3610 break;
3611 case eCSR_CFG_DOT11_MODE_11G:
3612 ret_val = QCA_WLAN_802_11_MODE_11G;
3613 break;
3614 case eCSR_CFG_DOT11_MODE_11N:
3615 ret_val = QCA_WLAN_802_11_MODE_11N;
3616 break;
3617 case eCSR_CFG_DOT11_MODE_11AC:
3618 ret_val = QCA_WLAN_802_11_MODE_11AC;
3619 break;
3620 case eCSR_CFG_DOT11_MODE_AUTO:
3621 case eCSR_CFG_DOT11_MODE_ABG:
3622 default:
3623 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3624 }
3625 return ret_val;
3626}
3627
3628/**
3629 * hdd_add_tx_bitrate() - add tx bitrate attribute
3630 * @skb: pointer to sk buff
3631 * @hdd_sta_ctx: pointer to hdd station context
3632 * @idx: attribute index
3633 *
3634 * Return: Success(0) or reason code for failure
3635 */
3636static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3637 hdd_station_ctx_t *hdd_sta_ctx,
3638 int idx)
3639{
3640 struct nlattr *nla_attr;
3641 uint32_t bitrate, bitrate_compat;
3642
3643 nla_attr = nla_nest_start(skb, idx);
3644 if (!nla_attr)
3645 goto fail;
3646 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3647 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3648
3649 /* report 16-bit bitrate only if we can */
3650 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3651 if (bitrate > 0 &&
3652 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3653 hdd_err("put fail");
3654 goto fail;
3655 }
3656 if (bitrate_compat > 0 &&
3657 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3658 hdd_err("put fail");
3659 goto fail;
3660 }
3661 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3662 hdd_sta_ctx->conn_info.txrate.nss)) {
3663 hdd_err("put fail");
3664 goto fail;
3665 }
3666 nla_nest_end(skb, nla_attr);
3667 return 0;
3668fail:
3669 return -EINVAL;
3670}
3671
3672/**
3673 * hdd_add_sta_info() - add station info attribute
3674 * @skb: pointer to sk buff
3675 * @hdd_sta_ctx: pointer to hdd station context
3676 * @idx: attribute index
3677 *
3678 * Return: Success(0) or reason code for failure
3679 */
3680static int32_t hdd_add_sta_info(struct sk_buff *skb,
3681 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3682{
3683 struct nlattr *nla_attr;
3684
3685 nla_attr = nla_nest_start(skb, idx);
3686 if (!nla_attr)
3687 goto fail;
3688 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3689 (hdd_sta_ctx->conn_info.signal + 100))) {
3690 hdd_err("put fail");
3691 goto fail;
3692 }
3693 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3694 goto fail;
3695 nla_nest_end(skb, nla_attr);
3696 return 0;
3697fail:
3698 return -EINVAL;
3699}
3700
3701/**
3702 * hdd_add_survey_info() - add survey info attribute
3703 * @skb: pointer to sk buff
3704 * @hdd_sta_ctx: pointer to hdd station context
3705 * @idx: attribute index
3706 *
3707 * Return: Success(0) or reason code for failure
3708 */
3709static int32_t hdd_add_survey_info(struct sk_buff *skb,
3710 hdd_station_ctx_t *hdd_sta_ctx,
3711 int idx)
3712{
3713 struct nlattr *nla_attr;
3714
3715 nla_attr = nla_nest_start(skb, idx);
3716 if (!nla_attr)
3717 goto fail;
3718 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3719 hdd_sta_ctx->conn_info.freq) ||
3720 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3721 (hdd_sta_ctx->conn_info.noise + 100))) {
3722 hdd_err("put fail");
3723 goto fail;
3724 }
3725 nla_nest_end(skb, nla_attr);
3726 return 0;
3727fail:
3728 return -EINVAL;
3729}
3730
3731/**
3732 * hdd_add_link_standard_info() - add link info attribute
3733 * @skb: pointer to sk buff
3734 * @hdd_sta_ctx: pointer to hdd station context
3735 * @idx: attribute index
3736 *
3737 * Return: Success(0) or reason code for failure
3738 */
3739static int32_t
3740hdd_add_link_standard_info(struct sk_buff *skb,
3741 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3742{
3743 struct nlattr *nla_attr;
3744
3745 nla_attr = nla_nest_start(skb, idx);
3746 if (!nla_attr)
3747 goto fail;
3748 if (nla_put(skb,
3749 NL80211_ATTR_SSID,
3750 hdd_sta_ctx->conn_info.SSID.SSID.length,
3751 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3752 hdd_err("put fail");
3753 goto fail;
3754 }
3755 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3756 goto fail;
3757 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3758 goto fail;
3759 nla_nest_end(skb, nla_attr);
3760 return 0;
3761fail:
3762 return -EINVAL;
3763}
3764
3765/**
3766 * hdd_add_ap_standard_info() - add ap info attribute
3767 * @skb: pointer to sk buff
3768 * @hdd_sta_ctx: pointer to hdd station context
3769 * @idx: attribute index
3770 *
3771 * Return: Success(0) or reason code for failure
3772 */
3773static int32_t
3774hdd_add_ap_standard_info(struct sk_buff *skb,
3775 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3776{
3777 struct nlattr *nla_attr;
3778
3779 nla_attr = nla_nest_start(skb, idx);
3780 if (!nla_attr)
3781 goto fail;
3782 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3783 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3784 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3785 &hdd_sta_ctx->conn_info.vht_caps)) {
3786 hdd_err("put fail");
3787 goto fail;
3788 }
3789 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3790 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3791 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3792 &hdd_sta_ctx->conn_info.ht_caps)) {
3793 hdd_err("put fail");
3794 goto fail;
3795 }
3796 nla_nest_end(skb, nla_attr);
3797 return 0;
3798fail:
3799 return -EINVAL;
3800}
3801
3802/**
3803 * hdd_get_station_info() - send BSS information to supplicant
3804 * @hdd_ctx: pointer to hdd context
3805 * @adapter: pointer to adapter
3806 *
3807 * Return: 0 if success else error status
3808 */
3809static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3810 hdd_adapter_t *adapter)
3811{
3812 struct sk_buff *skb = NULL;
3813 uint8_t *tmp_hs20 = NULL;
3814 uint32_t nl_buf_len;
3815 hdd_station_ctx_t *hdd_sta_ctx;
3816
3817 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3818
3819 nl_buf_len = NLMSG_HDRLEN;
3820 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3821 sizeof(hdd_sta_ctx->conn_info.freq) +
3822 sizeof(hdd_sta_ctx->conn_info.noise) +
3823 sizeof(hdd_sta_ctx->conn_info.signal) +
3824 (sizeof(uint32_t) * 2) +
3825 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3826 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3827 sizeof(hdd_sta_ctx->conn_info.authType) +
3828 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3829 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3830 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3831 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3832 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3833 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3834 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3835 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3836 1);
3837 }
3838 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3839 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3840 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3841 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3842
3843
3844 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3845 if (!skb) {
3846 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3847 return -ENOMEM;
3848 }
3849
3850 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3851 LINK_INFO_STANDARD_NL80211_ATTR)) {
3852 hdd_err("put fail");
3853 goto fail;
3854 }
3855 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3856 AP_INFO_STANDARD_NL80211_ATTR)) {
3857 hdd_err("put fail");
3858 goto fail;
3859 }
3860 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3861 hdd_sta_ctx->conn_info.roam_count) ||
3862 nla_put_u32(skb, INFO_AKM,
3863 hdd_convert_auth_type(
3864 hdd_sta_ctx->conn_info.authType)) ||
3865 nla_put_u32(skb, WLAN802_11_MODE,
3866 hdd_convert_dot11mode(
3867 hdd_sta_ctx->conn_info.dot11Mode))) {
3868 hdd_err("put fail");
3869 goto fail;
3870 }
3871 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3872 if (nla_put(skb, HT_OPERATION,
3873 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3874 &hdd_sta_ctx->conn_info.ht_operation)) {
3875 hdd_err("put fail");
3876 goto fail;
3877 }
3878 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3879 if (nla_put(skb, VHT_OPERATION,
3880 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3881 &hdd_sta_ctx->conn_info.vht_operation)) {
3882 hdd_err("put fail");
3883 goto fail;
3884 }
3885 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3886 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3887 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3888 tmp_hs20 + 1)) {
3889 hdd_err("put fail");
3890 goto fail;
3891 }
3892
3893 return cfg80211_vendor_cmd_reply(skb);
3894fail:
3895 if (skb)
3896 kfree_skb(skb);
3897 return -EINVAL;
3898}
3899
3900/**
3901 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3902 * @wiphy: corestack handler
3903 * @wdev: wireless device
3904 * @data: data
3905 * @data_len: data length
3906 *
3907 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3908 * Validate cmd attributes and send the station info to upper layers.
3909 *
3910 * Return: Success(0) or reason code for failure
3911 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303912static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303913__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3914 struct wireless_dev *wdev,
3915 const void *data,
3916 int data_len)
3917{
3918 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3919 struct net_device *dev = wdev->netdev;
3920 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3921 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3922 int32_t status;
3923
3924 ENTER_DEV(dev);
3925 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3926 hdd_err("Command not allowed in FTM mode");
3927 status = -EPERM;
3928 goto out;
3929 }
3930
3931 status = wlan_hdd_validate_context(hdd_ctx);
3932 if (0 != status)
3933 goto out;
3934
3935
3936 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3937 data, data_len, NULL);
3938 if (status) {
3939 hdd_err("Invalid ATTR");
3940 goto out;
3941 }
3942
3943 /* Parse and fetch Command Type*/
3944 if (tb[STATION_INFO]) {
3945 status = hdd_get_station_info(hdd_ctx, adapter);
3946 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3947 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3948 } else {
3949 hdd_err("get station info cmd type failed");
3950 status = -EINVAL;
3951 goto out;
3952 }
3953 EXIT();
3954out:
3955 return status;
3956}
3957
3958/**
3959 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3960 * @wiphy: corestack handler
3961 * @wdev: wireless device
3962 * @data: data
3963 * @data_len: data length
3964 *
3965 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3966 * Validate cmd attributes and send the station info to upper layers.
3967 *
3968 * Return: Success(0) or reason code for failure
3969 */
3970static int32_t
3971hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3972 struct wireless_dev *wdev,
3973 const void *data,
3974 int data_len)
3975{
3976 int ret;
3977
3978 cds_ssr_protect(__func__);
3979 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3980 cds_ssr_unprotect(__func__);
3981
3982 return ret;
3983}
3984
3985/*
3986 * undef short names defined for get station command
3987 * used by __wlan_hdd_cfg80211_get_station_cmd()
3988 */
3989#undef STATION_INVALID
3990#undef STATION_INFO
3991#undef STATION_ASSOC_FAIL_REASON
3992#undef STATION_MAX
3993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3995/**
3996 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3997 * @wiphy: pointer to wireless wiphy structure.
3998 * @wdev: pointer to wireless_dev structure.
3999 * @data: Pointer to the Key data
4000 * @data_len:Length of the data passed
4001 *
4002 * This is called when wlan driver needs to save the keys received via
4003 * vendor specific command.
4004 *
4005 * Return: Return the Success or Failure code.
4006 */
4007static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4008 struct wireless_dev *wdev,
4009 const void *data, int data_len)
4010{
4011 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4012 struct net_device *dev = wdev->netdev;
4013 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4014 hdd_context_t *hdd_ctx_ptr;
4015 int status;
4016
Jeff Johnson1f61b612016-02-12 16:28:33 -08004017 ENTER_DEV(dev);
4018
Anurag Chouhan6d760662016-02-20 16:05:43 +05304019 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 hdd_err("Command not allowed in FTM mode");
4021 return -EPERM;
4022 }
4023
4024 if ((data == NULL) || (data_len == 0) ||
4025 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004026 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 return -EINVAL;
4028 }
4029
4030 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4031 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004032 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 return -EINVAL;
4034 }
4035
4036 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304037 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4040 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004041 true,
4042 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304043 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4044 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4046 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4047 return 0;
4048}
4049
4050/**
4051 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4052 * @wiphy: pointer to wireless wiphy structure.
4053 * @wdev: pointer to wireless_dev structure.
4054 * @data: Pointer to the Key data
4055 * @data_len:Length of the data passed
4056 *
4057 * This is called when wlan driver needs to save the keys received via
4058 * vendor specific command.
4059 *
4060 * Return: Return the Success or Failure code.
4061 */
4062static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4063 struct wireless_dev *wdev,
4064 const void *data, int data_len)
4065{
4066 int ret;
4067
4068 cds_ssr_protect(__func__);
4069 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4070 cds_ssr_unprotect(__func__);
4071
4072 return ret;
4073}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004074#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075
4076static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4077 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4078 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4079 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004080 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081};
4082
4083/**
4084 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4085 * @wiphy: pointer to wireless wiphy structure.
4086 * @wdev: pointer to wireless_dev structure.
4087 * @data: Pointer to the data to be passed via vendor interface
4088 * @data_len:Length of the data to be passed
4089 *
4090 * This is called when wlan driver needs to send wifi driver related info
4091 * (driver/fw version) to the user space application upon request.
4092 *
4093 * Return: Return the Success or Failure code.
4094 */
4095static int
4096__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4097 struct wireless_dev *wdev,
4098 const void *data, int data_len)
4099{
4100 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4101 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004102 tSirVersionString driver_version;
4103 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004106 struct sk_buff *reply_skb;
4107 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108
Jeff Johnson1f61b612016-02-12 16:28:33 -08004109 ENTER_DEV(wdev->netdev);
4110
Anurag Chouhan6d760662016-02-20 16:05:43 +05304111 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004112 hdd_err("Command not allowed in FTM mode");
4113 return -EPERM;
4114 }
4115
4116 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304117 if (status)
4118 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119
4120 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4121 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004122 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123 return -EINVAL;
4124 }
4125
4126 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004127 hdd_err("Rcvd req for Driver version");
4128 strlcpy(driver_version, QWLAN_VERSIONSTR,
4129 sizeof(driver_version));
4130 skb_len += strlen(driver_version) + 1;
4131 count++;
4132 }
4133
4134 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4135 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004136 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4137 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004138 snprintf(firmware_version, sizeof(firmware_version),
4139 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4140 skb_len += strlen(firmware_version) + 1;
4141 count++;
4142 }
4143
4144 if (count == 0) {
4145 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146 return -EINVAL;
4147 }
4148
Ryan Hsu7ac88852016-04-28 10:20:34 -07004149 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4150 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004153 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004154 return -ENOMEM;
4155 }
4156
Ryan Hsu7ac88852016-04-28 10:20:34 -07004157 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4158 if (nla_put_string(reply_skb,
4159 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4160 driver_version))
4161 goto error_nla_fail;
4162 }
4163
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304164 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004165 if (nla_put_string(reply_skb,
4166 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4167 firmware_version))
4168 goto error_nla_fail;
4169 }
4170
4171 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4172 if (nla_put_u32(reply_skb,
4173 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4174 hdd_ctx->radio_index))
4175 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176 }
4177
4178 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004179
4180error_nla_fail:
4181 hdd_err("nla put fail");
4182 kfree_skb(reply_skb);
4183 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184}
4185
4186/**
4187 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4188 * @wiphy: pointer to wireless wiphy structure.
4189 * @wdev: pointer to wireless_dev structure.
4190 * @data: Pointer to the data to be passed via vendor interface
4191 * @data_len:Length of the data to be passed
4192 *
4193 * This is called when wlan driver needs to send wifi driver related info
4194 * (driver/fw version) to the user space application upon request.
4195 *
4196 * Return: Return the Success or Failure code.
4197 */
4198static int
4199wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4200 struct wireless_dev *wdev,
4201 const void *data, int data_len)
4202{
4203 int ret;
4204
4205 cds_ssr_protect(__func__);
4206 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4207 cds_ssr_unprotect(__func__);
4208
4209 return ret;
4210}
4211
4212/**
4213 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4214 * @wiphy: pointer to wireless wiphy structure.
4215 * @wdev: pointer to wireless_dev structure.
4216 * @data: Pointer to the data to be passed via vendor interface
4217 * @data_len:Length of the data to be passed
4218 *
4219 * This is called by userspace to know the supported logger features
4220 *
4221 * Return: Return the Success or Failure code.
4222 */
4223static int
4224__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4225 struct wireless_dev *wdev,
4226 const void *data, int data_len)
4227{
4228 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4229 int status;
4230 uint32_t features;
4231 struct sk_buff *reply_skb = NULL;
4232
Jeff Johnson1f61b612016-02-12 16:28:33 -08004233 ENTER_DEV(wdev->netdev);
4234
Anurag Chouhan6d760662016-02-20 16:05:43 +05304235 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236 hdd_err("Command not allowed in FTM mode");
4237 return -EPERM;
4238 }
4239
4240 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304241 if (status)
4242 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243
4244 features = 0;
4245
4246 if (hdd_is_memdump_supported())
4247 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4248 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4249 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4250 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4251
4252 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4253 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4254 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004255 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256 return -ENOMEM;
4257 }
4258
Jeff Johnson020db452016-06-29 14:37:26 -07004259 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4261 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004262 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 kfree_skb(reply_skb);
4264 return -EINVAL;
4265 }
4266
4267 return cfg80211_vendor_cmd_reply(reply_skb);
4268}
4269
4270/**
4271 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4272 * @wiphy: pointer to wireless wiphy structure.
4273 * @wdev: pointer to wireless_dev structure.
4274 * @data: Pointer to the data to be passed via vendor interface
4275 * @data_len:Length of the data to be passed
4276 *
4277 * This is called by userspace to know the supported logger features
4278 *
4279 * Return: Return the Success or Failure code.
4280 */
4281static int
4282wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4283 struct wireless_dev *wdev,
4284 const void *data, int data_len)
4285{
4286 int ret;
4287
4288 cds_ssr_protect(__func__);
4289 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4290 data, data_len);
4291 cds_ssr_unprotect(__func__);
4292
4293 return ret;
4294}
4295
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004296#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297/**
4298 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304299 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004300 * @bssid: pointer to bssid of roamed AP.
4301 * @req_rsn_ie: Pointer to request RSN IE
4302 * @req_rsn_len: Length of the request RSN IE
4303 * @rsp_rsn_ie: Pointer to response RSN IE
4304 * @rsp_rsn_len: Length of the response RSN IE
4305 * @roam_info_ptr: Pointer to the roaming related information
4306 *
4307 * This is called when wlan driver needs to send the roaming and
4308 * authorization information after roaming.
4309 *
4310 * The information that would be sent is the request RSN IE, response
4311 * RSN IE and BSSID of the newly roamed AP.
4312 *
4313 * If the Authorized status is authenticated, then additional parameters
4314 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4315 * supplicant.
4316 *
4317 * The supplicant upon receiving this event would ignore the legacy
4318 * cfg80211_roamed call and use the entire information from this event.
4319 * The cfg80211_roamed should still co-exist since the kernel will
4320 * make use of the parameters even if the supplicant ignores it.
4321 *
4322 * Return: Return the Success or Failure code.
4323 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304324int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4326 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4327{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304328 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004330 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331 ENTER();
4332
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304333 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004336 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004337 !roam_info_ptr->roamSynchInProgress)
4338 return 0;
4339
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004340 /*
4341 * The user space has issued a disconnect when roaming is in
4342 * progress. The disconnect should be honored gracefully.
4343 * If the roaming is complete and the roam event is sent
4344 * back to the user space, it will get confused as it is
4345 * expecting a disconnect event. So, do not send the event
4346 * and handle the disconnect later.
4347 */
4348 if (adapter->defer_disconnect) {
4349 hdd_notice("LFR3:Do not send roam auth event");
4350 return 0;
4351 }
4352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304354 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4356 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4357 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004358 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4360 GFP_KERNEL);
4361
4362 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004363 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364 return -EINVAL;
4365 }
4366
4367 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4368 ETH_ALEN, bssid) ||
4369 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4370 req_rsn_len, req_rsn_ie) ||
4371 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4372 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004373 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374 goto nla_put_failure;
4375 }
Jeff Johnson020db452016-06-29 14:37:26 -07004376 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377 if (roam_info_ptr->synchAuthStatus ==
4378 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004379 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004380 if (nla_put_u8(skb,
4381 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4382 hdd_err("nla put fail");
4383 goto nla_put_failure;
4384 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004385 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4386 /* if FT or CCKM connection: dont send replay counter */
4387 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4388 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4389 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4390 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4391 nla_put(skb,
4392 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4393 SIR_REPLAY_CTR_LEN,
4394 roam_info_ptr->replay_ctr)) {
4395 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004396 hdd_err("failed to send replay counter.");
4397 goto nla_put_failure;
4398 }
4399 if (nla_put(skb,
4400 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4401 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4402 nla_put(skb,
4403 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4404 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4405 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406 goto nla_put_failure;
4407 }
4408 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004409 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4411 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004412 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004413 goto nla_put_failure;
4414 }
4415 }
4416
Jeff Johnson020db452016-06-29 14:37:26 -07004417 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004418 roam_info_ptr->subnet_change_status);
4419
4420 /*
4421 * Add subnet change status if subnet has changed
4422 * 0 = unchanged
4423 * 1 = changed
4424 * 2 = unknown
4425 */
4426 if (roam_info_ptr->subnet_change_status) {
4427 if (nla_put_u8(skb,
4428 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4429 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004430 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004431 goto nla_put_failure;
4432 }
4433 }
4434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435 cfg80211_vendor_event(skb, GFP_KERNEL);
4436 return 0;
4437
4438nla_put_failure:
4439 kfree_skb(skb);
4440 return -EINVAL;
4441}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004442#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443
4444static const struct nla_policy
4445wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4446
4447 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4448 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4449 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304450 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304451 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4452 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004453 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4454 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4455 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4456 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4457 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304458 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459};
4460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004461/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304462 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4463 *
4464 * @adapter: Pointer to HDD adapter
4465 * @ie_data: Pointer to Scan IEs buffer
4466 * @ie_len: Length of Scan IEs
4467 *
4468 * Return: 0 on success; error number otherwise
4469 */
4470static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4471 uint8_t *ie_data, uint8_t ie_len)
4472{
4473 hdd_scaninfo_t *scan_info = NULL;
4474 scan_info = &adapter->scan_info;
4475
4476 if (scan_info->default_scan_ies) {
4477 qdf_mem_free(scan_info->default_scan_ies);
4478 scan_info->default_scan_ies = NULL;
4479 }
4480
4481 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4482 if (!scan_info->default_scan_ies)
4483 return -ENOMEM;
4484
4485 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4486 scan_info->default_scan_ies_len = ie_len;
4487 return 0;
4488}
4489
4490/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4492 * vendor command
4493 *
4494 * @wiphy: wiphy device pointer
4495 * @wdev: wireless device pointer
4496 * @data: Vendor command data buffer
4497 * @data_len: Buffer length
4498 *
4499 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4500 *
4501 * Return: Error code.
4502 */
4503static int
4504__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4505 struct wireless_dev *wdev,
4506 const void *data,
4507 int data_len)
4508{
4509 struct net_device *dev = wdev->netdev;
4510 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4511 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4512 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4513 int ret_val = 0;
4514 u32 modulated_dtim;
4515 u16 stats_avg_factor;
4516 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304517 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004518 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004519 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304520 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304521 int attr_len;
4522 int access_policy = 0;
4523 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4524 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304525 uint16_t scan_ie_len = 0;
4526 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304527 struct sir_set_tx_rx_aggregation_size request;
4528 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004529 uint8_t retry, delay;
4530 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304531 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304532
Jeff Johnson1f61b612016-02-12 16:28:33 -08004533 ENTER_DEV(dev);
4534
Anurag Chouhan6d760662016-02-20 16:05:43 +05304535 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536 hdd_err("Command not allowed in FTM mode");
4537 return -EPERM;
4538 }
4539
4540 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304541 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004542 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543
4544 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4545 data, data_len,
4546 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004547 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004548 return -EINVAL;
4549 }
4550
Krunal Sonie3531942016-04-12 17:43:53 -07004551 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4552 ftm_capab = nla_get_u32(tb[
4553 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4554 hdd_ctx->config->fine_time_meas_cap =
4555 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4556 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304557 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004558 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004559 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4560 hdd_ctx->config->fine_time_meas_cap);
Krunal Sonie3531942016-04-12 17:43:53 -07004561 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4562 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4563 hdd_ctx->config->fine_time_meas_cap);
4564 }
4565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004566 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4567 modulated_dtim = nla_get_u32(
4568 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4569
4570 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4571 adapter->sessionId,
4572 modulated_dtim);
4573
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304574 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 ret_val = -EPERM;
4576 }
4577
Kapil Gupta6213c012016-09-02 19:39:09 +05304578 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4579 qpower = nla_get_u8(
4580 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4581 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4582 ret_val = -EINVAL;
4583 }
4584
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4586 stats_avg_factor = nla_get_u16(
4587 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4588 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4589 adapter->sessionId,
4590 stats_avg_factor);
4591
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304592 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593 ret_val = -EPERM;
4594 }
4595
4596
4597 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4598 guard_time = nla_get_u32(
4599 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4600 status = sme_configure_guard_time(hdd_ctx->hHal,
4601 adapter->sessionId,
4602 guard_time);
4603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304604 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 ret_val = -EPERM;
4606 }
4607
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304608 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4609 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4610 attr_len = nla_len(
4611 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4612 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4613 hdd_info("Invalid value. attr_len %d",
4614 attr_len);
4615 return -EINVAL;
4616 }
4617
4618 nla_memcpy(&vendor_ie,
4619 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4620 attr_len);
4621 vendor_ie_present = true;
4622 hdd_info("Access policy vendor ie present.attr_len %d",
4623 attr_len);
4624 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4625 &vendor_ie[0], attr_len);
4626 }
4627
4628 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4629 access_policy = (int) nla_get_u32(
4630 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4631 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4632 (access_policy >
4633 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4634 hdd_info("Invalid value. access_policy %d",
4635 access_policy);
4636 return -EINVAL;
4637 }
4638 access_policy_present = true;
4639 hdd_info("Access policy present. access_policy %d",
4640 access_policy);
4641 }
4642
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004643 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4644 retry = nla_get_u8(tb[
4645 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4646 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4647 CFG_NON_AGG_RETRY_MAX : retry;
4648 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4649 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4650 retry, PDEV_CMD);
4651 }
4652
4653 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4654 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4655 retry = retry > CFG_AGG_RETRY_MAX ?
4656 CFG_AGG_RETRY_MAX : retry;
4657
4658 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4659 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4660 CFG_AGG_RETRY_MIN : retry;
4661 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4662 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4663 retry, PDEV_CMD);
4664 }
4665
4666 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4667 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4668 retry = retry > CFG_MGMT_RETRY_MAX ?
4669 CFG_MGMT_RETRY_MAX : retry;
4670 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4671 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4672 retry, PDEV_CMD);
4673 }
4674
4675 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4676 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4677 retry = retry > CFG_CTRL_RETRY_MAX ?
4678 CFG_CTRL_RETRY_MAX : retry;
4679 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4680 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4681 retry, PDEV_CMD);
4682 }
4683
4684 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4685 delay = nla_get_u8(tb[
4686 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4687 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4688 CFG_PROPAGATION_DELAY_MAX : delay;
4689 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4690 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4691 delay, PDEV_CMD);
4692 }
4693
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304694 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4695 tx_fail_count = nla_get_u32(
4696 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4697 if (tx_fail_count) {
4698 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4699 adapter->sessionId, tx_fail_count);
4700 if (QDF_STATUS_SUCCESS != status) {
4701 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4702 status);
4703 return -EINVAL;
4704 }
4705 }
4706 }
4707
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304708 if (vendor_ie_present && access_policy_present) {
4709 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4710 access_policy =
4711 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304712 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304713 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304714 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304715
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304716 hdd_info("calling sme_update_access_policy_vendor_ie");
4717 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4718 adapter->sessionId, &vendor_ie[0],
4719 access_policy);
4720 if (QDF_STATUS_SUCCESS != status) {
4721 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304722 return -EINVAL;
4723 }
4724 }
4725
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304726 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4727 set_value = nla_get_u8(
4728 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4729 hdd_info("set_value: %d", set_value);
4730 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4731 }
4732
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304733 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4734 scan_ie_len = nla_len(
4735 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4736 hdd_info("Received default scan IE of len %d session %d device mode %d",
4737 scan_ie_len, adapter->sessionId,
4738 adapter->device_mode);
4739 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4740 scan_ie = (uint8_t *) nla_data(tb
4741 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304742
4743 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4744 scan_ie_len))
4745 hdd_err("Failed to save default scan IEs");
4746
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304747 if (adapter->device_mode == QDF_STA_MODE) {
4748 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4749 adapter->sessionId, scan_ie,
4750 scan_ie_len);
4751 if (QDF_STATUS_SUCCESS != status)
4752 ret_val = -EPERM;
4753 }
4754 } else
4755 ret_val = -EPERM;
4756 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304757
4758 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4759 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4760 /* if one is specified, both must be specified */
4761 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4762 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4763 hdd_err("Both TX and RX MPDU Aggregation required");
4764 return -EINVAL;
4765 }
4766
4767 request.tx_aggregation_size = nla_get_u8(
4768 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4769 request.rx_aggregation_size = nla_get_u8(
4770 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4771 request.vdev_id = adapter->sessionId;
4772
4773 if (request.tx_aggregation_size >=
4774 CFG_TX_AGGREGATION_SIZE_MIN &&
4775 request.tx_aggregation_size <=
4776 CFG_TX_AGGREGATION_SIZE_MAX &&
4777 request.rx_aggregation_size >=
4778 CFG_RX_AGGREGATION_SIZE_MIN &&
4779 request.rx_aggregation_size <=
4780 CFG_RX_AGGREGATION_SIZE_MAX) {
4781 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4782 if (qdf_status != QDF_STATUS_SUCCESS) {
4783 hdd_err("failed to set aggr sizes err %d",
4784 qdf_status);
4785 ret_val = -EPERM;
4786 }
4787 } else {
4788 hdd_err("TX %d RX %d MPDU aggr size not in range",
4789 request.tx_aggregation_size,
4790 request.rx_aggregation_size);
4791 ret_val = -EINVAL;
4792 }
4793 }
4794
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304795 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4796 uint8_t ignore_assoc_disallowed;
4797
4798 ignore_assoc_disallowed
4799 = nla_get_u8(tb[
4800 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4801 hdd_info("Set ignore_assoc_disallowed value - %d",
4802 ignore_assoc_disallowed);
4803 if ((ignore_assoc_disallowed <
4804 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4805 (ignore_assoc_disallowed >
4806 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4807 return -EPERM;
4808
4809 sme_update_session_param(hdd_ctx->hHal,
4810 adapter->sessionId,
4811 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4812 ignore_assoc_disallowed);
4813 }
4814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 return ret_val;
4816}
4817
4818/**
4819 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4820 * vendor command
4821 *
4822 * @wiphy: wiphy device pointer
4823 * @wdev: wireless device pointer
4824 * @data: Vendor command data buffer
4825 * @data_len: Buffer length
4826 *
4827 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4828 *
4829 * Return: EOK or other error codes.
4830 */
4831static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4832 struct wireless_dev *wdev,
4833 const void *data,
4834 int data_len)
4835{
4836 int ret;
4837
4838 cds_ssr_protect(__func__);
4839 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4840 data, data_len);
4841 cds_ssr_unprotect(__func__);
4842
4843 return ret;
4844}
4845
4846static const struct
4847nla_policy
4848qca_wlan_vendor_wifi_logger_start_policy
4849[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4850 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4851 = {.type = NLA_U32 },
4852 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4853 = {.type = NLA_U32 },
4854 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4855 = {.type = NLA_U32 },
4856};
4857
4858/**
4859 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4860 * or disable the collection of packet statistics from the firmware
4861 * @wiphy: WIPHY structure pointer
4862 * @wdev: Wireless device structure pointer
4863 * @data: Pointer to the data received
4864 * @data_len: Length of the data received
4865 *
4866 * This function enables or disables the collection of packet statistics from
4867 * the firmware
4868 *
4869 * Return: 0 on success and errno on failure
4870 */
4871static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4872 struct wireless_dev *wdev,
4873 const void *data,
4874 int data_len)
4875{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304876 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4878 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4879 struct sir_wifi_start_log start_log;
4880
Jeff Johnson1f61b612016-02-12 16:28:33 -08004881 ENTER_DEV(wdev->netdev);
4882
Anurag Chouhan6d760662016-02-20 16:05:43 +05304883 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004884 hdd_err("Command not allowed in FTM mode");
4885 return -EPERM;
4886 }
4887
4888 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304889 if (status)
4890 return status;
4891
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304892 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4893 hdd_err("Driver Modules are closed, can not start logger");
4894 return -EINVAL;
4895 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004896
4897 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4898 data, data_len,
4899 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004900 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 return -EINVAL;
4902 }
4903
4904 /* Parse and fetch ring id */
4905 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004906 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 return -EINVAL;
4908 }
4909 start_log.ring_id = nla_get_u32(
4910 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004911 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912
4913 /* Parse and fetch verbose level */
4914 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004915 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916 return -EINVAL;
4917 }
4918 start_log.verbose_level = nla_get_u32(
4919 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004920 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921
4922 /* Parse and fetch flag */
4923 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004924 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925 return -EINVAL;
4926 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304927 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304929 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304931 /* size is buff size which can be set using iwpriv command*/
4932 start_log.size = 0;
4933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4935
4936 if (start_log.ring_id == RING_ID_WAKELOCK) {
4937 /* Start/stop wakelock events */
4938 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4939 cds_set_wakelock_logging(true);
4940 else
4941 cds_set_wakelock_logging(false);
4942 return 0;
4943 }
4944
4945 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304946 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004947 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948 status);
4949 return -EINVAL;
4950 }
4951 return 0;
4952}
4953
4954/**
4955 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4956 * or disable the collection of packet statistics from the firmware
4957 * @wiphy: WIPHY structure pointer
4958 * @wdev: Wireless device structure pointer
4959 * @data: Pointer to the data received
4960 * @data_len: Length of the data received
4961 *
4962 * This function is used to enable or disable the collection of packet
4963 * statistics from the firmware
4964 *
4965 * Return: 0 on success and errno on failure
4966 */
4967static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4968 struct wireless_dev *wdev,
4969 const void *data,
4970 int data_len)
4971{
4972 int ret = 0;
4973
4974 cds_ssr_protect(__func__);
4975 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4976 wdev, data, data_len);
4977 cds_ssr_unprotect(__func__);
4978
4979 return ret;
4980}
4981
4982static const struct
4983nla_policy
4984qca_wlan_vendor_wifi_logger_get_ring_data_policy
4985[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4986 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4987 = {.type = NLA_U32 },
4988};
4989
4990/**
4991 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4992 * @wiphy: WIPHY structure pointer
4993 * @wdev: Wireless device structure pointer
4994 * @data: Pointer to the data received
4995 * @data_len: Length of the data received
4996 *
4997 * This function is used to flush or retrieve the per packet statistics from
4998 * the driver
4999 *
5000 * Return: 0 on success and errno on failure
5001 */
5002static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5003 struct wireless_dev *wdev,
5004 const void *data,
5005 int data_len)
5006{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305007 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008 uint32_t ring_id;
5009 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5010 struct nlattr *tb
5011 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5012
Jeff Johnson1f61b612016-02-12 16:28:33 -08005013 ENTER_DEV(wdev->netdev);
5014
Anurag Chouhan6d760662016-02-20 16:05:43 +05305015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005016 hdd_err("Command not allowed in FTM mode");
5017 return -EPERM;
5018 }
5019
5020 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305021 if (status)
5022 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023
5024 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5025 data, data_len,
5026 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005027 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028 return -EINVAL;
5029 }
5030
5031 /* Parse and fetch ring id */
5032 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005033 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005034 return -EINVAL;
5035 }
5036
5037 ring_id = nla_get_u32(
5038 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5039
5040 if (ring_id == RING_ID_PER_PACKET_STATS) {
5041 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07005042 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305043 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5044 /*
5045 * As part of DRIVER ring ID, flush both driver and fw logs.
5046 * For other Ring ID's driver doesn't have any rings to flush
5047 */
5048 hdd_notice("Bug report triggered by framework");
5049
5050 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5051 WLAN_LOG_INDICATOR_FRAMEWORK,
5052 WLAN_LOG_REASON_CODE_UNUSED,
5053 true, false);
5054 if (QDF_STATUS_SUCCESS != status) {
5055 hdd_err("Failed to trigger bug report");
5056 return -EINVAL;
5057 }
5058 } else {
5059 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5060 WLAN_LOG_INDICATOR_FRAMEWORK,
5061 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005063 return 0;
5064}
5065
5066/**
5067 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5068 * @wiphy: WIPHY structure pointer
5069 * @wdev: Wireless device structure pointer
5070 * @data: Pointer to the data received
5071 * @data_len: Length of the data received
5072 *
5073 * This function is used to flush or retrieve the per packet statistics from
5074 * the driver
5075 *
5076 * Return: 0 on success and errno on failure
5077 */
5078static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5079 struct wireless_dev *wdev,
5080 const void *data,
5081 int data_len)
5082{
5083 int ret = 0;
5084
5085 cds_ssr_protect(__func__);
5086 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5087 wdev, data, data_len);
5088 cds_ssr_unprotect(__func__);
5089
5090 return ret;
5091}
5092
5093#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5094/**
5095 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5096 * @hdd_ctx: HDD context
5097 * @request_id: [input] request id
5098 * @pattern_id: [output] pattern id
5099 *
5100 * This function loops through request id to pattern id array
5101 * if the slot is available, store the request id and return pattern id
5102 * if entry exists, return the pattern id
5103 *
5104 * Return: 0 on success and errno on failure
5105 */
5106static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5107 uint32_t request_id,
5108 uint8_t *pattern_id)
5109{
5110 uint32_t i;
5111
5112 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5113 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5114 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5115 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5116 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5117 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5118 return 0;
5119 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5120 request_id) {
5121 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5122 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5123 return 0;
5124 }
5125 }
5126 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5127 return -EINVAL;
5128}
5129
5130/**
5131 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5132 * @hdd_ctx: HDD context
5133 * @request_id: [input] request id
5134 * @pattern_id: [output] pattern id
5135 *
5136 * This function loops through request id to pattern id array
5137 * reset request id to 0 (slot available again) and
5138 * return pattern id
5139 *
5140 * Return: 0 on success and errno on failure
5141 */
5142static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5143 uint32_t request_id,
5144 uint8_t *pattern_id)
5145{
5146 uint32_t i;
5147
5148 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5149 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5150 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5151 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5152 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5153 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5154 return 0;
5155 }
5156 }
5157 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5158 return -EINVAL;
5159}
5160
5161
5162/*
5163 * define short names for the global vendor params
5164 * used by __wlan_hdd_cfg80211_offloaded_packets()
5165 */
5166#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5167#define PARAM_REQUEST_ID \
5168 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5169#define PARAM_CONTROL \
5170 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5171#define PARAM_IP_PACKET \
5172 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5173#define PARAM_SRC_MAC_ADDR \
5174 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5175#define PARAM_DST_MAC_ADDR \
5176 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5177#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5178
5179/**
5180 * wlan_hdd_add_tx_ptrn() - add tx pattern
5181 * @adapter: adapter pointer
5182 * @hdd_ctx: hdd context
5183 * @tb: nl attributes
5184 *
5185 * This function reads the NL attributes and forms a AddTxPtrn message
5186 * posts it to SME.
5187 *
5188 */
5189static int
5190wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5191 struct nlattr **tb)
5192{
5193 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305194 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 uint32_t request_id, ret, len;
5196 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305197 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005198 uint16_t eth_type = htons(ETH_P_IP);
5199
5200 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005201 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 return -ENOTSUPP;
5203 }
5204
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305205 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005207 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005208 return -ENOMEM;
5209 }
5210
5211 /* Parse and fetch request Id */
5212 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005213 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214 goto fail;
5215 }
5216
5217 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5218 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005219 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 return -EINVAL;
5221 }
Jeff Johnson77848112016-06-29 14:52:06 -07005222 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223
5224 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005225 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 goto fail;
5227 }
5228 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005229 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005231 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232 goto fail;
5233 }
5234
5235 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005236 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237 goto fail;
5238 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005239 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305240 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005241 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005242 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
Anurag Chouhanc5548422016-02-24 18:33:27 +05305244 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005245 &adapter->macAddressCurrent)) {
5246 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 goto fail;
5248 }
5249
5250 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005251 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 goto fail;
5253 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305254 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005255 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 MAC_ADDR_ARRAY(dst_addr.bytes));
5257
5258 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005259 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 goto fail;
5261 }
5262 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005263 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005264
5265 if (add_req->ucPtrnSize < 0 ||
5266 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5267 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005268 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005269 add_req->ucPtrnSize);
5270 goto fail;
5271 }
5272
5273 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305274 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305275 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305276 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305277 QDF_MAC_ADDR_SIZE);
5278 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305279 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 len += 2;
5281
5282 /*
5283 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5284 * ------------------------------------------------------------
5285 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5286 * ------------------------------------------------------------
5287 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305288 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005289 nla_data(tb[PARAM_IP_PACKET]),
5290 add_req->ucPtrnSize);
5291 add_req->ucPtrnSize += len;
5292
5293 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5294 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005295 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005296 goto fail;
5297 }
5298 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005299 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300
5301 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305302 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005303 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 goto fail;
5305 }
5306
5307 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305308 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309 return 0;
5310
5311fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305312 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313 return -EINVAL;
5314}
5315
5316/**
5317 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5318 * @adapter: adapter pointer
5319 * @hdd_ctx: hdd context
5320 * @tb: nl attributes
5321 *
5322 * This function reads the NL attributes and forms a DelTxPtrn message
5323 * posts it to SME.
5324 *
5325 */
5326static int
5327wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5328 struct nlattr **tb)
5329{
5330 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305331 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 uint32_t request_id, ret;
5333 uint8_t pattern_id = 0;
5334
5335 /* Parse and fetch request Id */
5336 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005337 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338 return -EINVAL;
5339 }
5340 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5341 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005342 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 return -EINVAL;
5344 }
5345
5346 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5347 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005348 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 return -EINVAL;
5350 }
5351
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305352 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005353 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005354 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355 return -ENOMEM;
5356 }
5357
Anurag Chouhanc5548422016-02-24 18:33:27 +05305358 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005359 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005360 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005361 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362 request_id, del_req->ucPtrnId);
5363
5364 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305365 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005366 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 goto fail;
5368 }
5369
5370 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305371 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 return 0;
5373
5374fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305375 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 return -EINVAL;
5377}
5378
5379
5380/**
5381 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5382 * @wiphy: Pointer to wireless phy
5383 * @wdev: Pointer to wireless device
5384 * @data: Pointer to data
5385 * @data_len: Data length
5386 *
5387 * Return: 0 on success, negative errno on failure
5388 */
5389static int
5390__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5391 struct wireless_dev *wdev,
5392 const void *data,
5393 int data_len)
5394{
5395 struct net_device *dev = wdev->netdev;
5396 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5397 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5398 struct nlattr *tb[PARAM_MAX + 1];
5399 uint8_t control;
5400 int ret;
5401 static const struct nla_policy policy[PARAM_MAX + 1] = {
5402 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5403 [PARAM_CONTROL] = { .type = NLA_U32 },
5404 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305405 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005406 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305407 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408 [PARAM_PERIOD] = { .type = NLA_U32 },
5409 };
5410
Jeff Johnson1f61b612016-02-12 16:28:33 -08005411 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412
Anurag Chouhan6d760662016-02-20 16:05:43 +05305413 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414 hdd_err("Command not allowed in FTM mode");
5415 return -EPERM;
5416 }
5417
5418 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305419 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421
5422 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005423 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 return -ENOTSUPP;
5425 }
5426
5427 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005428 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 return -EINVAL;
5430 }
5431
5432 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005433 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 return -EINVAL;
5435 }
5436 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005437 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438
5439 if (control == WLAN_START_OFFLOADED_PACKETS)
5440 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005441 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005443
5444 hdd_err("Invalid control: %d", control);
5445
5446 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447}
5448
5449/*
5450 * done with short names for the global vendor params
5451 * used by __wlan_hdd_cfg80211_offloaded_packets()
5452 */
5453#undef PARAM_MAX
5454#undef PARAM_REQUEST_ID
5455#undef PARAM_CONTROL
5456#undef PARAM_IP_PACKET
5457#undef PARAM_SRC_MAC_ADDR
5458#undef PARAM_DST_MAC_ADDR
5459#undef PARAM_PERIOD
5460
5461/**
5462 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5463 * @wiphy: wiphy structure pointer
5464 * @wdev: Wireless device structure pointer
5465 * @data: Pointer to the data received
5466 * @data_len: Length of @data
5467 *
5468 * Return: 0 on success; errno on failure
5469 */
5470static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5471 struct wireless_dev *wdev,
5472 const void *data,
5473 int data_len)
5474{
5475 int ret = 0;
5476
5477 cds_ssr_protect(__func__);
5478 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5479 wdev, data, data_len);
5480 cds_ssr_unprotect(__func__);
5481
5482 return ret;
5483}
5484#endif
5485
5486/*
5487 * define short names for the global vendor params
5488 * used by __wlan_hdd_cfg80211_monitor_rssi()
5489 */
5490#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5491#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5492#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5493#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5494#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5495
5496/**
5497 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5498 * @wiphy: Pointer to wireless phy
5499 * @wdev: Pointer to wireless device
5500 * @data: Pointer to data
5501 * @data_len: Data length
5502 *
5503 * Return: 0 on success, negative errno on failure
5504 */
5505static int
5506__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5507 struct wireless_dev *wdev,
5508 const void *data,
5509 int data_len)
5510{
5511 struct net_device *dev = wdev->netdev;
5512 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5513 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5514 struct nlattr *tb[PARAM_MAX + 1];
5515 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305516 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517 int ret;
5518 uint32_t control;
5519 static const struct nla_policy policy[PARAM_MAX + 1] = {
5520 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5521 [PARAM_CONTROL] = { .type = NLA_U32 },
5522 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5523 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5524 };
5525
Jeff Johnson1f61b612016-02-12 16:28:33 -08005526 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305528 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5529 hdd_err("invalid session id: %d", adapter->sessionId);
5530 return -EINVAL;
5531 }
5532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305534 if (ret)
5535 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536
5537 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005538 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005539 return -ENOTSUPP;
5540 }
5541
5542 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005543 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 return -EINVAL;
5545 }
5546
5547 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005548 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 return -EINVAL;
5550 }
5551
5552 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005553 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005554 return -EINVAL;
5555 }
5556
5557 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5558 req.session_id = adapter->sessionId;
5559 control = nla_get_u32(tb[PARAM_CONTROL]);
5560
5561 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5562 req.control = true;
5563 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005564 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565 return -EINVAL;
5566 }
5567
5568 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005569 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 return -EINVAL;
5571 }
5572
5573 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5574 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5575
5576 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005577 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 req.min_rssi, req.max_rssi);
5579 return -EINVAL;
5580 }
Jeff Johnson77848112016-06-29 14:52:06 -07005581 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 req.min_rssi, req.max_rssi);
5583
5584 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5585 req.control = false;
5586 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005587 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588 return -EINVAL;
5589 }
Jeff Johnson77848112016-06-29 14:52:06 -07005590 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005591 req.request_id, req.session_id, req.control);
5592
5593 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305594 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005595 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005596 return -EINVAL;
5597 }
5598
5599 return 0;
5600}
5601
5602/*
5603 * done with short names for the global vendor params
5604 * used by __wlan_hdd_cfg80211_monitor_rssi()
5605 */
5606#undef PARAM_MAX
5607#undef PARAM_CONTROL
5608#undef PARAM_REQUEST_ID
5609#undef PARAM_MAX_RSSI
5610#undef PARAM_MIN_RSSI
5611
5612/**
5613 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5614 * @wiphy: wiphy structure pointer
5615 * @wdev: Wireless device structure pointer
5616 * @data: Pointer to the data received
5617 * @data_len: Length of @data
5618 *
5619 * Return: 0 on success; errno on failure
5620 */
5621static int
5622wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5623 const void *data, int data_len)
5624{
5625 int ret;
5626
5627 cds_ssr_protect(__func__);
5628 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5629 cds_ssr_unprotect(__func__);
5630
5631 return ret;
5632}
5633
5634/**
5635 * hdd_rssi_threshold_breached() - rssi breached NL event
5636 * @hddctx: HDD context
5637 * @data: rssi breached event data
5638 *
5639 * This function reads the rssi breached event %data and fill in the skb with
5640 * NL attributes and send up the NL event.
5641 *
5642 * Return: none
5643 */
5644void hdd_rssi_threshold_breached(void *hddctx,
5645 struct rssi_breach_event *data)
5646{
5647 hdd_context_t *hdd_ctx = hddctx;
5648 struct sk_buff *skb;
5649
5650 ENTER();
5651
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305652 if (wlan_hdd_validate_context(hdd_ctx))
5653 return;
5654 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005655 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656 return;
5657 }
5658
5659 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5660 NULL,
5661 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5662 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5663 GFP_KERNEL);
5664
5665 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005666 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667 return;
5668 }
5669
Jeff Johnson77848112016-06-29 14:52:06 -07005670 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005671 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005672 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005673 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5674
5675 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5676 data->request_id) ||
5677 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5678 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5679 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5680 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005681 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682 goto fail;
5683 }
5684
5685 cfg80211_vendor_event(skb, GFP_KERNEL);
5686 return;
5687
5688fail:
5689 kfree_skb(skb);
5690 return;
5691}
5692
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305693static const struct nla_policy
5694ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5695 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5696};
5697
5698/**
5699 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5700 * @wiphy: Pointer to wireless phy
5701 * @wdev: Pointer to wireless device
5702 * @data: Pointer to data
5703 * @data_len: Length of @data
5704 *
5705 * Return: 0 on success, negative errno on failure
5706 */
5707static int
5708__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5709 struct wireless_dev *wdev,
5710 const void *data, int data_len)
5711{
5712 int status;
5713 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5714 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005715 struct net_device *dev = wdev->netdev;
5716 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305717
5718 ENTER_DEV(wdev->netdev);
5719
5720 status = wlan_hdd_validate_context(pHddCtx);
5721 if (0 != status)
5722 return status;
5723 if (!pHddCtx->config->fhostNSOffload) {
5724 hdd_err("ND Offload not supported");
5725 return -EINVAL;
5726 }
5727
5728 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5729 (struct nlattr *)data,
5730 data_len, ns_offload_set_policy)) {
5731 hdd_err("nla_parse failed");
5732 return -EINVAL;
5733 }
5734
5735 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5736 hdd_err("ND Offload flag attribute not present");
5737 return -EINVAL;
5738 }
5739
5740 pHddCtx->ns_offload_enable =
5741 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5742
Dustin Brownd8279d22016-09-07 14:52:57 -07005743 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305744 if (pHddCtx->ns_offload_enable)
5745 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5746 else
5747 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005748
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305749 return 0;
5750}
5751
5752/**
5753 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5754 * @wiphy: pointer to wireless wiphy structure.
5755 * @wdev: pointer to wireless_dev structure.
5756 * @data: Pointer to the data to be passed via vendor interface
5757 * @data_len:Length of the data to be passed
5758 *
5759 * Return: Return the Success or Failure code.
5760 */
5761static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5762 struct wireless_dev *wdev,
5763 const void *data, int data_len)
5764{
5765 int ret;
5766
5767 cds_ssr_protect(__func__);
5768 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5769 cds_ssr_unprotect(__func__);
5770
5771 return ret;
5772}
5773
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005774/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5775 * @wiphy: Pointer to wireless phy
5776 * @wdev: Pointer to wireless device
5777 * @data: Pointer to data
5778 * @data_len: Data length
5779 *
5780 * This function return the preferred frequency list generated by the policy
5781 * manager.
5782 *
5783 * Return: success or failure code
5784 */
5785static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5786 struct wireless_dev
5787 *wdev, const void *data,
5788 int data_len)
5789{
5790 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5791 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305792 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305793 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305795 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 enum cds_con_mode intf_mode;
5797 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5798 struct sk_buff *reply_skb;
5799
Jeff Johnson1f61b612016-02-12 16:28:33 -08005800 ENTER_DEV(wdev->netdev);
5801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005802 ret = wlan_hdd_validate_context(hdd_ctx);
5803 if (ret)
5804 return -EINVAL;
5805
5806 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5807 data, data_len, NULL)) {
5808 hdd_err("Invalid ATTR");
5809 return -EINVAL;
5810 }
5811
5812 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5813 hdd_err("attr interface type failed");
5814 return -EINVAL;
5815 }
5816
5817 intf_mode = nla_get_u32(tb
5818 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5819
5820 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5821 hdd_err("Invalid interface type");
5822 return -EINVAL;
5823 }
5824
5825 hdd_debug("Userspace requested pref freq list");
5826
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305827 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5828 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305829 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830 hdd_err("Get pcl failed");
5831 return -EINVAL;
5832 }
5833
5834 /* convert channel number to frequency */
5835 for (i = 0; i < pcl_len; i++) {
5836 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5837 freq_list[i] =
5838 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005839 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840 else
5841 freq_list[i] =
5842 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005843 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 }
5845
5846 /* send the freq_list back to supplicant */
5847 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5848 sizeof(u32) *
5849 pcl_len +
5850 NLMSG_HDRLEN);
5851
5852 if (!reply_skb) {
5853 hdd_err("Allocate reply_skb failed");
5854 return -EINVAL;
5855 }
5856
5857 if (nla_put_u32(reply_skb,
5858 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5859 intf_mode) ||
5860 nla_put(reply_skb,
5861 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5862 sizeof(uint32_t) * pcl_len,
5863 freq_list)) {
5864 hdd_err("nla put fail");
5865 kfree_skb(reply_skb);
5866 return -EINVAL;
5867 }
5868
5869 return cfg80211_vendor_cmd_reply(reply_skb);
5870}
5871
5872/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5873 * @wiphy: Pointer to wireless phy
5874 * @wdev: Pointer to wireless device
5875 * @data: Pointer to data
5876 * @data_len: Data length
5877 *
5878 * This function return the preferred frequency list generated by the policy
5879 * manager.
5880 *
5881 * Return: success or failure code
5882 */
5883static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5884 struct wireless_dev
5885 *wdev, const void *data,
5886 int data_len)
5887{
5888 int ret = 0;
5889
5890 cds_ssr_protect(__func__);
5891 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5892 data, data_len);
5893 cds_ssr_unprotect(__func__);
5894
5895 return ret;
5896}
5897
5898/**
5899 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5900 * @wiphy: Pointer to wireless phy
5901 * @wdev: Pointer to wireless device
5902 * @data: Pointer to data
5903 * @data_len: Data length
5904 *
5905 * Return: 0 on success, negative errno on failure
5906 */
5907static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5908 struct wireless_dev *wdev,
5909 const void *data,
5910 int data_len)
5911{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305912 struct net_device *ndev = wdev->netdev;
5913 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005914 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5915 int ret = 0;
5916 enum cds_con_mode intf_mode;
5917 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5918 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919
Jeff Johnson1f61b612016-02-12 16:28:33 -08005920 ENTER_DEV(ndev);
5921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 ret = wlan_hdd_validate_context(hdd_ctx);
5923 if (ret)
5924 return ret;
5925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5927 data, data_len, NULL)) {
5928 hdd_err("Invalid ATTR");
5929 return -EINVAL;
5930 }
5931
5932 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5933 hdd_err("attr interface type failed");
5934 return -EINVAL;
5935 }
5936
5937 intf_mode = nla_get_u32(tb
5938 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5939
5940 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5941 hdd_err("Invalid interface type");
5942 return -EINVAL;
5943 }
5944
5945 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5946 hdd_err("attr probable freq failed");
5947 return -EINVAL;
5948 }
5949
5950 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5951 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5952
5953 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005954 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005955 channel_hint, HW_MODE_20_MHZ)) {
5956 hdd_err("Set channel hint failed due to concurrency check");
5957 return -EINVAL;
5958 }
5959
Krunal Soni09e55032016-06-07 10:06:55 -07005960 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5961 hdd_warn("Remain On Channel Pending");
5962
Krunal Soni3091bcc2016-06-23 12:28:21 -07005963 ret = qdf_reset_connection_update();
5964 if (!QDF_IS_STATUS_SUCCESS(ret))
5965 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005966
Krunal Soni3091bcc2016-06-23 12:28:21 -07005967 ret = cds_current_connections_update(adapter->sessionId,
5968 channel_hint,
5969 SIR_UPDATE_REASON_SET_OPER_CHAN);
5970 if (QDF_STATUS_E_FAILURE == ret) {
5971 /* return in the failure case */
5972 hdd_err("ERROR: connections update failed!!");
5973 return -EINVAL;
5974 }
5975
5976 if (QDF_STATUS_SUCCESS == ret) {
5977 /*
5978 * Success is the only case for which we expect hw mode
5979 * change to take place, hence we need to wait.
5980 * For any other return value it should be a pass
5981 * through
5982 */
5983 ret = qdf_wait_for_connection_update();
5984 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5985 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986 return -EINVAL;
5987 }
5988
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005989 }
5990
5991 return 0;
5992}
5993
5994/**
5995 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5996 * @wiphy: Pointer to wireless phy
5997 * @wdev: Pointer to wireless device
5998 * @data: Pointer to data
5999 * @data_len: Data length
6000 *
6001 * Return: 0 on success, negative errno on failure
6002 */
6003static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6004 struct wireless_dev *wdev,
6005 const void *data,
6006 int data_len)
6007{
6008 int ret = 0;
6009
6010 cds_ssr_protect(__func__);
6011 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6012 data, data_len);
6013 cds_ssr_unprotect(__func__);
6014
6015 return ret;
6016}
6017
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306018static const struct
6019nla_policy
6020qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6021 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6022};
6023
6024/**
6025 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6026 * @wiphy: WIPHY structure pointer
6027 * @wdev: Wireless device structure pointer
6028 * @data: Pointer to the data received
6029 * @data_len: Length of the data received
6030 *
6031 * This function is used to get link properties like nss, rate flags and
6032 * operating frequency for the active connection with the given peer.
6033 *
6034 * Return: 0 on success and errno on failure
6035 */
6036static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6037 struct wireless_dev *wdev,
6038 const void *data,
6039 int data_len)
6040{
6041 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6042 struct net_device *dev = wdev->netdev;
6043 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6044 hdd_station_ctx_t *hdd_sta_ctx;
6045 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306046 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306047 uint32_t sta_id;
6048 struct sk_buff *reply_skb;
6049 uint32_t rate_flags = 0;
6050 uint8_t nss;
6051 uint8_t final_rate_flags = 0;
6052 uint32_t freq;
6053
Jeff Johnson1f61b612016-02-12 16:28:33 -08006054 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306055
Anurag Chouhan6d760662016-02-20 16:05:43 +05306056 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306057 hdd_err("Command not allowed in FTM mode");
6058 return -EPERM;
6059 }
6060
6061 if (0 != wlan_hdd_validate_context(hdd_ctx))
6062 return -EINVAL;
6063
6064 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6065 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006066 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306067 return -EINVAL;
6068 }
6069
6070 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006071 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306072 adapter->device_mode);
6073 return -EINVAL;
6074 }
6075
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306076 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306077 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006078 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306079 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6080
Krunal Sonib4326f22016-03-10 13:05:51 -08006081 if (adapter->device_mode == QDF_STA_MODE ||
6082 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306083 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6084 if ((hdd_sta_ctx->conn_info.connState !=
6085 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306086 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306087 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006088 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306089 MAC_ADDR_ARRAY(peer_mac));
6090 return -EINVAL;
6091 }
6092
6093 nss = hdd_sta_ctx->conn_info.nss;
6094 freq = cds_chan_to_freq(
6095 hdd_sta_ctx->conn_info.operationChannel);
6096 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006097 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6098 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306099
6100 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6101 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306102 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306103 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306104 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306105 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306106 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306107 break;
6108 }
6109
6110 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006111 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306112 MAC_ADDR_ARRAY(peer_mac));
6113 return -EINVAL;
6114 }
6115
6116 nss = adapter->aStaInfo[sta_id].nss;
6117 freq = cds_chan_to_freq(
6118 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6119 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6120 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006121 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306122 MAC_ADDR_ARRAY(peer_mac));
6123 return -EINVAL;
6124 }
6125
6126 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6127 if (rate_flags & eHAL_TX_RATE_VHT80) {
6128 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006129#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306130 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006131#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306132 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6133 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006134#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306135 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006136#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306137 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6138 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6139 } else if (rate_flags &
6140 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6141 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006142#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306143 if (rate_flags & eHAL_TX_RATE_HT40)
6144 final_rate_flags |=
6145 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006146#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306147 }
6148
6149 if (rate_flags & eHAL_TX_RATE_SGI) {
6150 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6151 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6152 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6153 }
6154 }
6155
6156 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6157 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6158
6159 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006160 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306161 return -EINVAL;
6162 }
6163
6164 if (nla_put_u8(reply_skb,
6165 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6166 nss) ||
6167 nla_put_u8(reply_skb,
6168 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6169 final_rate_flags) ||
6170 nla_put_u32(reply_skb,
6171 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6172 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006173 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306174 kfree_skb(reply_skb);
6175 return -EINVAL;
6176 }
6177
6178 return cfg80211_vendor_cmd_reply(reply_skb);
6179}
6180
6181/**
6182 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6183 * properties.
6184 * @wiphy: WIPHY structure pointer
6185 * @wdev: Wireless device structure pointer
6186 * @data: Pointer to the data received
6187 * @data_len: Length of the data received
6188 *
6189 * This function is used to get link properties like nss, rate flags and
6190 * operating frequency for the active connection with the given peer.
6191 *
6192 * Return: 0 on success and errno on failure
6193 */
6194static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6195 struct wireless_dev *wdev,
6196 const void *data,
6197 int data_len)
6198{
6199 int ret = 0;
6200
6201 cds_ssr_protect(__func__);
6202 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6203 wdev, data, data_len);
6204 cds_ssr_unprotect(__func__);
6205
6206 return ret;
6207}
6208
Peng Xu278d0122015-09-24 16:34:17 -07006209static const struct
6210nla_policy
6211qca_wlan_vendor_ota_test_policy
6212[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6213 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6214};
6215
6216/**
6217 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6218 * @wiphy: Pointer to wireless phy
6219 * @wdev: Pointer to wireless device
6220 * @data: Pointer to data
6221 * @data_len: Data length
6222 *
6223 * Return: 0 on success, negative errno on failure
6224 */
6225static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6226 struct wireless_dev *wdev,
6227 const void *data,
6228 int data_len)
6229{
6230 struct net_device *dev = wdev->netdev;
6231 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6232 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6233 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6234 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6235 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306236 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006237 uint32_t current_roam_state;
6238
Jeff Johnson1f61b612016-02-12 16:28:33 -08006239 ENTER_DEV(dev);
6240
Anurag Chouhan6d760662016-02-20 16:05:43 +05306241 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006242 hdd_err("Command not allowed in FTM mode");
6243 return -EPERM;
6244 }
6245
6246 if (0 != wlan_hdd_validate_context(hdd_ctx))
6247 return -EINVAL;
6248
6249 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6250 data, data_len,
6251 qca_wlan_vendor_ota_test_policy)) {
6252 hdd_err("invalid attr");
6253 return -EINVAL;
6254 }
6255
6256 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6257 hdd_err("attr ota test failed");
6258 return -EINVAL;
6259 }
6260
6261 ota_enable = nla_get_u8(
6262 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6263
6264 hdd_info(" OTA test enable = %d", ota_enable);
6265 if (ota_enable != 1) {
6266 hdd_err("Invalid value, only enable test mode is supported!");
6267 return -EINVAL;
6268 }
6269
6270 current_roam_state =
6271 sme_get_current_roam_state(hal, adapter->sessionId);
6272 status = sme_stop_roaming(hal, adapter->sessionId,
6273 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306274 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006275 hdd_err("Enable/Disable roaming failed");
6276 return -EINVAL;
6277 }
6278
6279 status = sme_ps_enable_disable(hal, adapter->sessionId,
6280 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306281 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006282 hdd_err("Enable/Disable power save failed");
6283 /* restore previous roaming setting */
6284 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6285 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6286 status = sme_start_roaming(hal, adapter->sessionId,
6287 eCsrHddIssued);
6288 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6289 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6290 status = sme_stop_roaming(hal, adapter->sessionId,
6291 eCsrHddIssued);
6292
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306293 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006294 hdd_err("Restoring roaming state failed");
6295
6296 return -EINVAL;
6297 }
6298
6299
6300 return 0;
6301}
6302
6303/**
6304 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6305 * @wiphy: Pointer to wireless phy
6306 * @wdev: Pointer to wireless device
6307 * @data: Pointer to data
6308 * @data_len: Data length
6309 *
6310 * Return: 0 on success, negative errno on failure
6311 */
6312static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6313 struct wireless_dev *wdev,
6314 const void *data,
6315 int data_len)
6316{
6317 int ret = 0;
6318
6319 cds_ssr_protect(__func__);
6320 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6321 cds_ssr_unprotect(__func__);
6322
6323 return ret;
6324}
6325
Peng Xu4d67c8f2015-10-16 16:02:26 -07006326/**
6327 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6328 * @wiphy: Pointer to wireless phy
6329 * @wdev: Pointer to wireless device
6330 * @data: Pointer to data
6331 * @data_len: Data length
6332 *
6333 * Return: 0 on success, negative errno on failure
6334 */
6335static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6336 struct wireless_dev *wdev,
6337 const void *data,
6338 int data_len)
6339{
6340 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6341 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006342 hdd_adapter_t *adapter;
6343 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006344 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6345 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006346 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006347
Jeff Johnson1f61b612016-02-12 16:28:33 -08006348 ENTER_DEV(dev);
6349
Peng Xu4d67c8f2015-10-16 16:02:26 -07006350 ret = wlan_hdd_validate_context(hdd_ctx);
6351 if (ret)
6352 return ret;
6353
6354 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6355
6356 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6357 data, data_len, NULL)) {
6358 hdd_err("Invalid ATTR");
6359 return -EINVAL;
6360 }
6361
6362 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6363 hdd_err("attr tx power scale failed");
6364 return -EINVAL;
6365 }
6366
6367 scale_value = nla_get_u8(tb
6368 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6369
6370 if (scale_value > MAX_TXPOWER_SCALE) {
6371 hdd_err("Invalid tx power scale level");
6372 return -EINVAL;
6373 }
6374
Peng Xu62c8c432016-05-09 15:23:02 -07006375 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006376
Peng Xu62c8c432016-05-09 15:23:02 -07006377 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006378 hdd_err("Set tx power scale failed");
6379 return -EINVAL;
6380 }
6381
6382 return 0;
6383}
6384
6385/**
6386 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6387 * @wiphy: Pointer to wireless phy
6388 * @wdev: Pointer to wireless device
6389 * @data: Pointer to data
6390 * @data_len: Data length
6391 *
6392 * Return: 0 on success, negative errno on failure
6393 */
6394static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6395 struct wireless_dev *wdev,
6396 const void *data,
6397 int data_len)
6398{
Peng Xu62c8c432016-05-09 15:23:02 -07006399 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006400
6401 cds_ssr_protect(__func__);
6402 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6403 data, data_len);
6404 cds_ssr_unprotect(__func__);
6405
6406 return ret;
6407}
6408
6409/**
6410 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6411 * @wiphy: Pointer to wireless phy
6412 * @wdev: Pointer to wireless device
6413 * @data: Pointer to data
6414 * @data_len: Data length
6415 *
6416 * Return: 0 on success, negative errno on failure
6417 */
6418static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6419 struct wireless_dev *wdev,
6420 const void *data,
6421 int data_len)
6422{
6423 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6424 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006425 hdd_adapter_t *adapter;
6426 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006427 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6428 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006429 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006430
Jeff Johnson1f61b612016-02-12 16:28:33 -08006431 ENTER_DEV(dev);
6432
Peng Xu4d67c8f2015-10-16 16:02:26 -07006433 ret = wlan_hdd_validate_context(hdd_ctx);
6434 if (ret)
6435 return ret;
6436
6437 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6438
6439 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6440 data, data_len, NULL)) {
6441 hdd_err("Invalid ATTR");
6442 return -EINVAL;
6443 }
6444
6445 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6446 hdd_err("attr tx power decrease db value failed");
6447 return -EINVAL;
6448 }
6449
6450 scale_value = nla_get_u8(tb
6451 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6452
Peng Xu62c8c432016-05-09 15:23:02 -07006453 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6454 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006455
Peng Xu62c8c432016-05-09 15:23:02 -07006456 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006457 hdd_err("Set tx power decrease db failed");
6458 return -EINVAL;
6459 }
6460
6461 return 0;
6462}
6463
6464/**
6465 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6466 * @wiphy: Pointer to wireless phy
6467 * @wdev: Pointer to wireless device
6468 * @data: Pointer to data
6469 * @data_len: Data length
6470 *
6471 * Return: 0 on success, negative errno on failure
6472 */
6473static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6474 struct wireless_dev *wdev,
6475 const void *data,
6476 int data_len)
6477{
Peng Xu62c8c432016-05-09 15:23:02 -07006478 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006479
6480 cds_ssr_protect(__func__);
6481 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6482 data, data_len);
6483 cds_ssr_unprotect(__func__);
6484
6485 return ret;
6486}
Peng Xu8fdaa492016-06-22 10:20:47 -07006487
6488/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306489 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6490 * @wiphy: Pointer to wireless phy
6491 * @wdev: Pointer to wireless device
6492 * @data: Pointer to data
6493 * @data_len: Data length
6494 *
6495 * Processes the conditional channel switch request and invokes the helper
6496 * APIs to process the channel switch request.
6497 *
6498 * Return: 0 on success, negative errno on failure
6499 */
6500static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6501 struct wireless_dev *wdev,
6502 const void *data,
6503 int data_len)
6504{
6505 int ret;
6506 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6507 struct net_device *dev = wdev->netdev;
6508 hdd_adapter_t *adapter;
6509 struct nlattr
6510 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6511 uint32_t freq_len, i;
6512 uint32_t *freq;
6513 uint8_t chans[QDF_MAX_NUM_CHAN];
6514
6515 ENTER_DEV(dev);
6516
6517 ret = wlan_hdd_validate_context(hdd_ctx);
6518 if (ret)
6519 return ret;
6520
6521 if (!hdd_ctx->config->enableDFSMasterCap) {
6522 hdd_err("DFS master capability is not present in the driver");
6523 return -EINVAL;
6524 }
6525
6526 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6527 hdd_err("Command not allowed in FTM mode");
6528 return -EPERM;
6529 }
6530
6531 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6532 if (adapter->device_mode != QDF_SAP_MODE) {
6533 hdd_err("Invalid device mode %d", adapter->device_mode);
6534 return -EINVAL;
6535 }
6536
6537 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6538 data, data_len, NULL)) {
6539 hdd_err("Invalid ATTR");
6540 return -EINVAL;
6541 }
6542
6543 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6544 hdd_err("Frequency list is missing");
6545 return -EINVAL;
6546 }
6547
6548 freq_len = nla_len(
6549 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6550 sizeof(uint32_t);
6551
6552 if (freq_len > QDF_MAX_NUM_CHAN) {
6553 hdd_err("insufficient space to hold channels");
6554 return -ENOMEM;
6555 }
6556
6557 hdd_debug("freq_len=%d", freq_len);
6558
6559 freq = nla_data(
6560 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6561
6562
6563 for (i = 0; i < freq_len; i++) {
6564 if (freq[i] == 0)
6565 chans[i] = 0;
6566 else
6567 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6568
6569 hdd_debug("freq[%d]=%d", i, freq[i]);
6570 }
6571
6572 /*
6573 * The input frequency list from user space is designed to be a
6574 * priority based frequency list. This is only to accommodate any
6575 * future request. But, current requirement is only to perform CAC
6576 * on a single channel. So, the first entry from the list is picked.
6577 *
6578 * If channel is zero, any channel in the available outdoor regulatory
6579 * domain will be selected.
6580 */
6581 ret = wlan_hdd_request_pre_cac(chans[0]);
6582 if (ret) {
6583 hdd_err("pre cac request failed with reason:%d", ret);
6584 return ret;
6585 }
6586
6587 return 0;
6588}
6589
6590/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006591 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6592 * @wiphy: Pointer to wireless phy
6593 * @wdev: Pointer to wireless device
6594 * @data: Pointer to data
6595 * @data_len: Data length
6596 *
6597 * This function is to process the p2p listen offload start vendor
6598 * command. It parses the input parameters and invoke WMA API to
6599 * send the command to firmware.
6600 *
6601 * Return: 0 on success, negative errno on failure
6602 */
6603static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6604 struct wireless_dev *wdev,
6605 const void *data,
6606 int data_len)
6607{
6608 int ret;
6609 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6610 struct net_device *dev = wdev->netdev;
6611 hdd_adapter_t *adapter;
6612 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6613 struct sir_p2p_lo_start params;
6614 QDF_STATUS status;
6615
6616 ENTER_DEV(dev);
6617
6618 ret = wlan_hdd_validate_context(hdd_ctx);
6619 if (ret)
6620 return ret;
6621
6622 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6623 hdd_err("Command not allowed in FTM mode");
6624 return -EPERM;
6625 }
6626
6627 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6628 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6629 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6630 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6631 hdd_err("Invalid device mode %d", adapter->device_mode);
6632 return -EINVAL;
6633 }
6634
6635 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6636 data, data_len, NULL)) {
6637 hdd_err("Invalid ATTR");
6638 return -EINVAL;
6639 }
6640
6641 memset(&params, 0, sizeof(params));
6642
6643 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6644 params.ctl_flags = 1; /* set to default value */
6645 else
6646 params.ctl_flags = nla_get_u32(tb
6647 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6648
6649 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6650 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6651 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6652 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6653 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6654 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6655 hdd_err("Attribute parsing failed");
6656 return -EINVAL;
6657 }
6658
6659 params.vdev_id = adapter->sessionId;
6660 params.freq = nla_get_u32(tb
6661 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6662 if ((params.freq != 2412) && (params.freq != 2437) &&
6663 (params.freq != 2462)) {
6664 hdd_err("Invalid listening channel: %d", params.freq);
6665 return -EINVAL;
6666 }
6667
6668 params.period = nla_get_u32(tb
6669 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6670 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6671 hdd_err("Invalid period: %d", params.period);
6672 return -EINVAL;
6673 }
6674
6675 params.interval = nla_get_u32(tb
6676 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6677 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6678 hdd_err("Invalid interval: %d", params.interval);
6679 return -EINVAL;
6680 }
6681
6682 params.count = nla_get_u32(tb
6683 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006684 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006685 hdd_err("Invalid count: %d", params.count);
6686 return -EINVAL;
6687 }
6688
6689 params.device_types = nla_data(tb
6690 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6691 if (params.device_types == NULL) {
6692 hdd_err("Invalid device types");
6693 return -EINVAL;
6694 }
6695
6696 params.dev_types_len = nla_len(tb
6697 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6698 if (params.dev_types_len < 8) {
6699 hdd_err("Invalid device type length: %d", params.dev_types_len);
6700 return -EINVAL;
6701 }
6702
6703 params.probe_resp_tmplt = nla_data(tb
6704 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6705 if (params.probe_resp_tmplt == NULL) {
6706 hdd_err("Invalid probe response template");
6707 return -EINVAL;
6708 }
6709
6710 params.probe_resp_len = nla_len(tb
6711 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6712 if (params.probe_resp_len == 0) {
6713 hdd_err("Invalid probe resp template length: %d",
6714 params.probe_resp_len);
6715 return -EINVAL;
6716 }
6717
6718 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6719 params.freq, params.period, params.interval, params.count);
6720
6721 status = wma_p2p_lo_start(&params);
6722
6723 if (!QDF_IS_STATUS_SUCCESS(status)) {
6724 hdd_err("P2P LO start failed");
6725 return -EINVAL;
6726 }
6727
6728 return 0;
6729}
6730
6731
6732/**
6733 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6734 * @wiphy: Pointer to wireless phy
6735 * @wdev: Pointer to wireless device
6736 * @data: Pointer to data
6737 * @data_len: Data length
6738 *
6739 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6740 * to process p2p listen offload start vendor command.
6741 *
6742 * Return: 0 on success, negative errno on failure
6743 */
6744static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6745 struct wireless_dev *wdev,
6746 const void *data,
6747 int data_len)
6748{
6749 int ret = 0;
6750
6751 cds_ssr_protect(__func__);
6752 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6753 data, data_len);
6754 cds_ssr_unprotect(__func__);
6755
6756 return ret;
6757}
6758
6759/**
6760 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6761 * @wiphy: Pointer to wireless phy
6762 * @wdev: Pointer to wireless device
6763 * @data: Pointer to data
6764 * @data_len: Data length
6765 *
6766 * This function is to process the p2p listen offload stop vendor
6767 * command. It invokes WMA API to send command to firmware.
6768 *
6769 * Return: 0 on success, negative errno on failure
6770 */
6771static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6772 struct wireless_dev *wdev,
6773 const void *data,
6774 int data_len)
6775{
6776 QDF_STATUS status;
6777 hdd_adapter_t *adapter;
6778 struct net_device *dev = wdev->netdev;
6779
6780 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6781 hdd_err("Command not allowed in FTM mode");
6782 return -EPERM;
6783 }
6784
6785 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6786 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6787 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6788 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6789 hdd_err("Invalid device mode");
6790 return -EINVAL;
6791 }
6792
6793 status = wma_p2p_lo_stop(adapter->sessionId);
6794
6795 if (!QDF_IS_STATUS_SUCCESS(status)) {
6796 hdd_err("P2P LO stop failed");
6797 return -EINVAL;
6798 }
6799
6800 return 0;
6801}
6802
6803/**
6804 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6805 * @wiphy: Pointer to wireless phy
6806 * @wdev: Pointer to wireless device
6807 * @data: Pointer to data
6808 * @data_len: Data length
6809 *
6810 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6811 * to process p2p listen offload stop vendor command.
6812 *
6813 * Return: 0 on success, negative errno on failure
6814 */
6815static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6816 struct wireless_dev *wdev,
6817 const void *data,
6818 int data_len)
6819{
6820 int ret = 0;
6821
6822 cds_ssr_protect(__func__);
6823 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6824 data, data_len);
6825 cds_ssr_unprotect(__func__);
6826
6827 return ret;
6828}
6829
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306830/**
6831 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6832 * @wiphy: Pointer to wireless phy
6833 * @wdev: Pointer to wireless device
6834 * @data: Pointer to data
6835 * @data_len: Data length
6836 *
6837 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6838 * to process the conditional channel switch request.
6839 *
6840 * Return: 0 on success, negative errno on failure
6841 */
6842static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6843 struct wireless_dev *wdev,
6844 const void *data,
6845 int data_len)
6846{
6847 int ret;
6848
6849 cds_ssr_protect(__func__);
6850 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6851 data, data_len);
6852 cds_ssr_unprotect(__func__);
6853
6854 return ret;
6855}
6856
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306857/*
6858 * define short names for the global vendor params
6859 * used by __wlan_hdd_cfg80211_bpf_offload()
6860 */
6861#define BPF_INVALID \
6862 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6863#define BPF_SET_RESET \
6864 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6865#define BPF_VERSION \
6866 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6867#define BPF_FILTER_ID \
6868 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6869#define BPF_PACKET_SIZE \
6870 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6871#define BPF_CURRENT_OFFSET \
6872 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6873#define BPF_PROGRAM \
6874 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6875#define BPF_MAX \
6876 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006877
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306878static const struct nla_policy
6879wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6880 [BPF_SET_RESET] = {.type = NLA_U32},
6881 [BPF_VERSION] = {.type = NLA_U32},
6882 [BPF_FILTER_ID] = {.type = NLA_U32},
6883 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6884 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6885 [BPF_PROGRAM] = {.type = NLA_U8},
6886};
6887
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006888struct bpf_offload_priv {
6889 struct sir_bpf_get_offload bpf_get_offload;
6890};
6891
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306892/**
6893 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006894 * @context: opaque context originally passed to SME. HDD always passes
6895 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306896 * @bpf_get_offload: struct for get offload
6897 *
6898 * This function receives the response/data from the lower layer and
6899 * checks to see if the thread is still waiting then post the results to
6900 * upper layer, if the request has timed out then ignore.
6901 *
6902 * Return: None
6903 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006904static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006905 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306906{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006907 struct hdd_request *request;
6908 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306909
6910 ENTER();
6911
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006912 request = hdd_request_get(context);
6913 if (!request) {
6914 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306915 return;
6916 }
6917
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006918 priv = hdd_request_priv(request);
6919 priv->bpf_get_offload = *data;
6920 hdd_request_complete(request);
6921 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306922}
6923
6924/**
6925 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6926 * @hdd_context: hdd_context
6927 * @bpf_get_offload: struct for get offload
6928 *
6929 * Return: 0 on success, error number otherwise.
6930 */
6931static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6932 struct sir_bpf_get_offload *bpf_get_offload)
6933{
6934 struct sk_buff *skb;
6935 uint32_t nl_buf_len;
6936
6937 ENTER();
6938
6939 nl_buf_len = NLMSG_HDRLEN;
6940 nl_buf_len +=
6941 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6942 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6943
6944 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6945 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006946 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306947 return -ENOMEM;
6948 }
6949
Jeff Johnson77848112016-06-29 14:52:06 -07006950 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306951 bpf_get_offload->bpf_version,
6952 bpf_get_offload->max_bytes_for_bpf_inst);
6953
6954 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6955 bpf_get_offload->max_bytes_for_bpf_inst) ||
6956 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006957 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306958 goto nla_put_failure;
6959 }
6960
6961 cfg80211_vendor_cmd_reply(skb);
6962 EXIT();
6963 return 0;
6964
6965nla_put_failure:
6966 kfree_skb(skb);
6967 return -EINVAL;
6968}
6969
6970/**
6971 * hdd_get_bpf_offload - Get BPF offload Capabilities
6972 * @hdd_ctx: Hdd context
6973 *
6974 * Return: 0 on success, errno on failure
6975 */
6976static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6977{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306978 QDF_STATUS status;
6979 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006980 void *cookie;
6981 struct hdd_request *request;
6982 struct bpf_offload_priv *priv;
6983 static const struct hdd_request_params params = {
6984 .priv_size = sizeof(*priv),
6985 .timeout_ms = WLAN_WAIT_TIME_BPF,
6986 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306987
6988 ENTER();
6989
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006990 request = hdd_request_alloc(&params);
6991 if (!request) {
6992 hdd_err("Unable to allocate request");
6993 return -EINVAL;
6994 }
6995 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306996
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006997 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6998 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006999 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007001 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007002 ret = qdf_status_to_os_return(status);
7003 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307004 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007005 ret = hdd_request_wait_for_response(request);
7006 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007007 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007008 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307009 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007010 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307011 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007012 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307013 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007014 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307015
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007016cleanup:
7017 /*
7018 * either we never sent a request to SME, we sent a request to
7019 * SME and timed out, or we sent a request to SME, received a
7020 * response from SME, and posted the response to userspace.
7021 * regardless we are done with the request.
7022 */
7023 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307024 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007025
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307026 return ret;
7027}
7028
7029/**
7030 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7031 * @hdd_ctx: Hdd context
7032 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307033 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307034 *
7035 * Return: 0 on success; errno on failure
7036 */
7037static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7038 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307039 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307040{
7041 struct sir_bpf_set_offload *bpf_set_offload;
7042 QDF_STATUS status;
7043 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307044 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307045
7046 ENTER();
7047
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307048 if (adapter->device_mode == QDF_STA_MODE ||
7049 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7050 if (!hdd_conn_is_connected(
7051 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7052 hdd_err("Not in Connected state!");
7053 return -ENOTSUPP;
7054 }
7055 }
7056
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307057 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7058 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007059 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307060 return -ENOMEM;
7061 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307062
7063 /* Parse and fetch bpf packet size */
7064 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007065 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307066 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307067 goto fail;
7068 }
7069 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7070
7071 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007072 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307073 goto post_sme;
7074 }
7075
7076 /* Parse and fetch bpf program */
7077 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007078 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307079 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307080 goto fail;
7081 }
7082
7083 prog_len = nla_len(tb[BPF_PROGRAM]);
7084 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307085
7086 if (bpf_set_offload->program == NULL) {
7087 hdd_err("qdf_mem_malloc failed for bpf offload program");
7088 ret = -ENOMEM;
7089 goto fail;
7090 }
7091
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307092 bpf_set_offload->current_length = prog_len;
7093 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307094 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307095
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307096 hdd_info("BPF set instructions");
7097 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7098 bpf_set_offload->program, prog_len);
7099
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307100 /* Parse and fetch filter Id */
7101 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007102 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307103 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307104 goto fail;
7105 }
7106 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7107
7108 /* Parse and fetch current offset */
7109 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007110 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307111 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307112 goto fail;
7113 }
7114 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7115
7116post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007117 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 +05307118 bpf_set_offload->session_id,
7119 bpf_set_offload->version,
7120 bpf_set_offload->filter_id,
7121 bpf_set_offload->total_length,
7122 bpf_set_offload->current_length,
7123 bpf_set_offload->current_offset);
7124
7125 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7126 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007127 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307128 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307129 goto fail;
7130 }
7131 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307132
7133fail:
7134 if (bpf_set_offload->current_length)
7135 qdf_mem_free(bpf_set_offload->program);
7136 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307137 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307138}
7139
7140/**
7141 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7142 * @wiphy: wiphy structure pointer
7143 * @wdev: Wireless device structure pointer
7144 * @data: Pointer to the data received
7145 * @data_len: Length of @data
7146 *
7147 * Return: 0 on success; errno on failure
7148 */
7149static int
7150__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7151 struct wireless_dev *wdev,
7152 const void *data, int data_len)
7153{
7154 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7155 struct net_device *dev = wdev->netdev;
7156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7157 struct nlattr *tb[BPF_MAX + 1];
7158 int ret_val, packet_filter_subcmd;
7159
7160 ENTER();
7161
7162 ret_val = wlan_hdd_validate_context(hdd_ctx);
7163 if (ret_val)
7164 return ret_val;
7165
7166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007167 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307168 return -EINVAL;
7169 }
7170
7171 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007172 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307173 return -ENOTSUPP;
7174 }
7175
7176 if (nla_parse(tb, BPF_MAX, data, data_len,
7177 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007178 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307179 return -EINVAL;
7180 }
7181
7182 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007183 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307184 return -EINVAL;
7185 }
7186
7187 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7188
7189 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7190 return hdd_get_bpf_offload(hdd_ctx);
7191 else
7192 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307193 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307194}
7195
7196/**
7197 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7198 * @wiphy: wiphy structure pointer
7199 * @wdev: Wireless device structure pointer
7200 * @data: Pointer to the data received
7201 * @data_len: Length of @data
7202 *
7203 * Return: 0 on success; errno on failure
7204 */
7205
7206static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7207 struct wireless_dev *wdev,
7208 const void *data, int data_len)
7209{
7210 int ret;
7211
7212 cds_ssr_protect(__func__);
7213 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7214 cds_ssr_unprotect(__func__);
7215
7216 return ret;
7217}
7218
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307219/**
7220 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7221 * @pre_cac_adapter: AP adapter used for pre cac
7222 * @status: Status (true or false)
7223 * @handle: Global handle
7224 *
7225 * Sets the status of pre cac i.e., whether the pre cac is active or not
7226 *
7227 * Return: Zero on success, non-zero on failure
7228 */
7229static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7230 bool status, tHalHandle handle)
7231{
7232 QDF_STATUS ret;
7233
7234 ret = wlan_sap_set_pre_cac_status(
7235 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7236 if (QDF_IS_STATUS_ERROR(ret))
7237 return -EINVAL;
7238
7239 return 0;
7240}
7241
7242/**
7243 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7244 * @ap_adapter: AP adapter
7245 * @chan_before_pre_cac: Channel
7246 *
7247 * Saves the channel which the AP was beaconing on before moving to the pre
7248 * cac channel. If radar is detected on the pre cac channel, this saved
7249 * channel will be used for AP operations.
7250 *
7251 * Return: Zero on success, non-zero on failure
7252 */
7253static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7254 uint8_t chan_before_pre_cac)
7255{
7256 QDF_STATUS ret;
7257
7258 ret = wlan_sap_set_chan_before_pre_cac(
7259 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7260 if (QDF_IS_STATUS_ERROR(ret))
7261 return -EINVAL;
7262
7263 return 0;
7264}
7265
7266/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307267 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7268 * are in nol list from provided channel list
7269 * @adapter: AP adapter
7270 * @channel_count: channel count
7271 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307272 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307273 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307274 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307275static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7276 uint32_t *channel_count,
7277 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307278{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307279 uint8_t i, j;
7280 uint32_t nol_len = 0;
7281 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7282 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7283 uint32_t chan_count;
7284 bool found;
7285 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307286
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307287 if (!hdd_ctx) {
7288 hdd_err("hdd ctx not found");
7289 *channel_count = 0;
7290 return;
7291 }
7292
7293 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7294 hdd_err("invalid channel count %d", *channel_count);
7295 return;
7296 }
7297
7298 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7299 if (nol_len == 0)
7300 return;
7301
7302 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7303 chan_count = *channel_count;
7304 qdf_mem_zero(channel_list, chan_count);
7305 *channel_count = 0;
7306
7307 for (i = 0 ; i < chan_count; i++) {
7308 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7309 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7310 continue;
7311 found = false;
7312 for (j = 0; j < nol_len; j++) {
7313 if (tmp_chan_list[i] == nol[j]) {
7314 found = true;
7315 hdd_notice("skipped channel %d due to nol",
7316 nol[j]);
7317 break;
7318 }
7319 }
7320 if (!found) {
7321 channel_list[*channel_count] = tmp_chan_list[i];
7322 *channel_count = *channel_count + 1;
7323 }
7324 }
7325}
7326
7327int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7328 uint32_t *channel_count,
7329 uint8_t *channel_list)
7330{
7331 tsap_Config_t *sap_config;
7332
7333 sap_config = &adapter->sessionCtx.ap.sapConfig;
7334
7335 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7336 sap_config->acs_cfg.ch_list_count);
7337 *channel_count = sap_config->acs_cfg.ch_list_count;
7338 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7339
7340 if (*channel_count == 0) {
7341 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307342 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307343 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307344
7345 return 0;
7346}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307347
7348/**
7349 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7350 * @hdd_ctx: HDD context
7351 * @ap_adapter: AP adapter
7352 * @channel: Channel requested by userspace
7353 * @pre_cac_chan: Pointer to the pre CAC channel
7354 *
7355 * Validates the channel provided by userspace. If user provided channel 0,
7356 * a valid outdoor channel must be selected from the regulatory channel.
7357 *
7358 * Return: Zero on success and non zero value on error
7359 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007360static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7361 hdd_adapter_t *ap_adapter,
7362 uint8_t channel,
7363 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307364{
7365 uint32_t i, j;
7366 QDF_STATUS status;
7367 int ret;
7368 uint8_t nol[QDF_MAX_NUM_CHAN];
7369 uint32_t nol_len = 0, weight_len = 0;
7370 bool found;
7371 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7372 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7373 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7374
7375 if (0 == channel) {
7376 /* Channel is not obtained from PCL because PCL may not have
7377 * the entire channel list. For example: if SAP is up on
7378 * channel 6 and PCL is queried for the next SAP interface,
7379 * if SCC is preferred, the PCL will contain only the channel
7380 * 6. But, we are in need of a DFS channel. So, going with the
7381 * first channel from the valid channel list.
7382 */
7383 status = cds_get_valid_chans(channel_list, &len);
7384 if (QDF_IS_STATUS_ERROR(status)) {
7385 hdd_err("Failed to get channel list");
7386 return -EINVAL;
7387 }
7388 cds_update_with_safe_channel_list(channel_list, &len,
7389 pcl_weights, weight_len);
7390 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7391 for (i = 0; i < len; i++) {
7392 found = false;
7393 for (j = 0; j < nol_len; j++) {
7394 if (channel_list[i] == nol[j]) {
7395 found = true;
7396 break;
7397 }
7398 }
7399 if (found)
7400 continue;
7401 if (CDS_IS_DFS_CH(channel_list[i])) {
7402 *pre_cac_chan = channel_list[i];
7403 break;
7404 }
7405 }
7406 if (*pre_cac_chan == 0) {
7407 hdd_err("unable to find outdoor channel");
7408 return -EINVAL;
7409 }
7410 } else {
7411 /* Only when driver selects a channel, check is done for
7412 * unnsafe and NOL channels. When user provides a fixed channel
7413 * the user is expected to take care of this.
7414 */
7415 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7416 !CDS_IS_DFS_CH(channel)) {
7417 hdd_err("Invalid channel for pre cac:%d", channel);
7418 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307419 }
Jeff Johnson68755312017-02-10 11:46:55 -08007420
7421 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307422 }
7423 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7424 return 0;
7425}
7426
7427/**
7428 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7429 * @channel: Channel option provided by userspace
7430 *
7431 * Sets the driver to the required hardware mode and start an adapater for
7432 * pre CAC which will mimic an AP.
7433 *
7434 * Return: Zero on success, non-zero value on error
7435 */
7436int wlan_hdd_request_pre_cac(uint8_t channel)
7437{
Krunal Sonib37bb352016-12-20 14:12:21 -08007438 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307439 hdd_context_t *hdd_ctx;
7440 int ret;
7441 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7442 hdd_ap_ctx_t *hdd_ap_ctx;
7443 QDF_STATUS status;
7444 struct wiphy *wiphy;
7445 struct net_device *dev;
7446 struct cfg80211_chan_def chandef;
7447 enum nl80211_channel_type channel_type;
7448 uint32_t freq;
7449 struct ieee80211_channel *chan;
7450 tHalHandle handle;
7451 bool val;
7452
7453 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7454 if (0 != wlan_hdd_validate_context(hdd_ctx))
7455 return -EINVAL;
7456
7457 if (cds_get_connection_count() > 1) {
7458 hdd_err("pre cac not allowed in concurrency");
7459 return -EINVAL;
7460 }
7461
7462 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7463 if (!ap_adapter) {
7464 hdd_err("unable to get SAP adapter");
7465 return -EINVAL;
7466 }
7467
7468 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7469 if (!handle) {
7470 hdd_err("Invalid handle");
7471 return -EINVAL;
7472 }
7473
7474 val = wlan_sap_is_pre_cac_active(handle);
7475 if (val) {
7476 hdd_err("pre cac is already in progress");
7477 return -EINVAL;
7478 }
7479
7480 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7481 if (!hdd_ap_ctx) {
7482 hdd_err("SAP context is NULL");
7483 return -EINVAL;
7484 }
7485
7486 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7487 hdd_err("SAP is already on DFS channel:%d",
7488 hdd_ap_ctx->operatingChannel);
7489 return -EINVAL;
7490 }
7491
7492 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7493 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7494 hdd_ap_ctx->operatingChannel);
7495 return -EINVAL;
7496 }
7497
Krunal Sonib37bb352016-12-20 14:12:21 -08007498 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7499 if (!mac_addr) {
7500 hdd_err("can't add virtual intf: Not getting valid mac addr");
7501 return -EINVAL;
7502 }
7503
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307504 hdd_info("channel:%d", channel);
7505
7506 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7507 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007508 if (ret != 0) {
7509 hdd_err("can't validate pre-cac channel");
7510 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307511 }
7512
7513 hdd_debug("starting pre cac SAP adapter");
7514
7515 /* Starting a SAP adapter:
7516 * Instead of opening an adapter, we could just do a SME open session
7517 * for AP type. But, start BSS would still need an adapter.
7518 * So, this option is not taken.
7519 *
7520 * hdd open adapter is going to register this precac interface with
7521 * user space. This interface though exposed to user space will be in
7522 * DOWN state. Consideration was done to avoid this registration to the
7523 * user space. But, as part of SAP operations multiple events are sent
7524 * to user space. Some of these events received from unregistered
7525 * interface was causing crashes. So, retaining the registration.
7526 *
7527 * So, this interface would remain registered and will remain in DOWN
7528 * state for the CAC duration. We will add notes in the feature
7529 * announcement to not use this temporary interface for any activity
7530 * from user space.
7531 */
7532 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007533 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307534 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307535 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007536 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307537 }
7538
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307539 /*
7540 * This interface is internally created by the driver. So, no interface
7541 * up comes for this interface from user space and hence starting
7542 * the adapter internally.
7543 */
7544 if (hdd_start_adapter(pre_cac_adapter)) {
7545 hdd_err("error starting the pre cac adapter");
7546 goto close_pre_cac_adapter;
7547 }
7548
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307549 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7550
7551 wiphy = hdd_ctx->wiphy;
7552 dev = pre_cac_adapter->dev;
7553
7554 /* Since this is only a dummy interface lets us use the IEs from the
7555 * other active SAP interface. In regular scenarios, these IEs would
7556 * come from the user space entity
7557 */
7558 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7559 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7560 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7561 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307562 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307563 }
7564 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7565 ap_adapter->sessionCtx.ap.beacon,
7566 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7567 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7568 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7569 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7570 ap_adapter->sessionCtx.ap.sapConfig.authType;
7571
7572 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7573 * to operate on the same bandwidth as that of the 2.4GHz operations.
7574 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7575 */
7576 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7577 case CH_WIDTH_20MHZ:
7578 channel_type = NL80211_CHAN_HT20;
7579 break;
7580 case CH_WIDTH_40MHZ:
7581 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7582 ap_adapter->sessionCtx.ap.sapConfig.channel)
7583 channel_type = NL80211_CHAN_HT40PLUS;
7584 else
7585 channel_type = NL80211_CHAN_HT40MINUS;
7586 break;
7587 default:
7588 channel_type = NL80211_CHAN_NO_HT;
7589 break;
7590 }
7591
7592 freq = cds_chan_to_freq(pre_cac_chan);
7593 chan = __ieee80211_get_channel(wiphy, freq);
7594 if (!chan) {
7595 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307596 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307597 }
7598
7599 cfg80211_chandef_create(&chandef, chan, channel_type);
7600
7601 hdd_debug("orig width:%d channel_type:%d freq:%d",
7602 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7603 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007604 /*
7605 * Doing update after opening and starting pre-cac adapter will make
7606 * sure that driver won't do hardware mode change if there are any
7607 * initial hick-ups or issues in pre-cac adapter's configuration.
7608 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7609 * connection update should result in DBS mode
7610 */
7611 status = cds_update_and_wait_for_connection_update(
7612 ap_adapter->sessionId,
7613 pre_cac_chan,
7614 SIR_UPDATE_REASON_PRE_CAC);
7615 if (QDF_IS_STATUS_ERROR(status)) {
7616 hdd_err("error in moving to DBS mode");
7617 goto stop_close_pre_cac_adapter;
7618 }
7619
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307620
7621 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7622 if (0 != ret) {
7623 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307624 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307625 }
7626
7627 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7628 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007629 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307630 if (QDF_IS_STATUS_ERROR(status)) {
7631 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307632 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307633 }
7634
7635 /*
7636 * The pre cac status is set here. But, it would not be reset explicitly
7637 * anywhere, since after the pre cac success/failure, the pre cac
7638 * adapter itself would be removed.
7639 */
7640 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7641 if (0 != ret) {
7642 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307643 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307644 }
7645
7646 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7647 hdd_ap_ctx->operatingChannel);
7648 if (0 != ret) {
7649 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307650 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307651 }
7652
7653 ap_adapter->pre_cac_chan = pre_cac_chan;
7654
7655 return 0;
7656
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307657stop_close_pre_cac_adapter:
7658 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307659 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7660 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307661close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307662 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007663release_intf_addr_and_return_failure:
7664 /*
7665 * Release the interface address as the adapter
7666 * failed to start, if you don't release then next
7667 * adapter which is trying to come wouldn't get valid
7668 * mac address. Remember we have limited pool of mac addresses
7669 */
7670 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307671 return -EINVAL;
7672}
7673
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307674static const struct nla_policy
7675wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7676 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7677};
7678
Agrawal Ashish65634612016-08-18 13:24:32 +05307679static const struct nla_policy
7680wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7681 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7682 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7683};
7684
7685/**
7686 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7687 * @wiphy: Pointer to wireless phy
7688 * @wdev: Pointer to wireless device
7689 * @data: Pointer to data
7690 * @data_len: Length of @data
7691 *
7692 * This function parses the incoming NL vendor command data attributes and
7693 * updates the SAP context about channel_hint and DFS mode.
7694 * If channel_hint is set, SAP will choose that channel
7695 * as operating channel.
7696 *
7697 * If DFS mode is enabled, driver will include DFS channels
7698 * in ACS else driver will skip DFS channels.
7699 *
7700 * Return: 0 on success, negative errno on failure
7701 */
7702static int
7703__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7704 struct wireless_dev *wdev,
7705 const void *data, int data_len)
7706{
7707 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7708 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7709 int ret;
7710 struct acs_dfs_policy *acs_policy;
7711 int mode = DFS_MODE_NONE;
7712 int channel_hint = 0;
7713
7714 ENTER_DEV(wdev->netdev);
7715
7716 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7717 hdd_err("Command not allowed in FTM mode");
7718 return -EINVAL;
7719 }
7720
7721 ret = wlan_hdd_validate_context(hdd_ctx);
7722 if (0 != ret)
7723 return ret;
7724
7725 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7726 data, data_len,
7727 wlan_hdd_set_acs_dfs_config_policy)) {
7728 hdd_err("invalid attr");
7729 return -EINVAL;
7730 }
7731
7732 acs_policy = &hdd_ctx->acs_policy;
7733 /*
7734 * SCM sends this attribute to restrict SAP from choosing
7735 * DFS channels from ACS.
7736 */
7737 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7738 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7739
7740 if (!IS_DFS_MODE_VALID(mode)) {
7741 hdd_err("attr acs dfs mode is not valid");
7742 return -EINVAL;
7743 }
7744 acs_policy->acs_dfs_mode = mode;
7745
7746 /*
7747 * SCM sends this attribute to provide an active channel,
7748 * to skip redundant ACS between drivers, and save driver start up time
7749 */
7750 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7751 channel_hint = nla_get_u8(
7752 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7753
7754 if (!IS_CHANNEL_VALID(channel_hint)) {
7755 hdd_err("acs channel is not valid");
7756 return -EINVAL;
7757 }
7758 acs_policy->acs_channel = channel_hint;
7759
7760 return 0;
7761}
7762
7763/**
7764 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7765 * @wiphy: wiphy structure pointer
7766 * @wdev: Wireless device structure pointer
7767 * @data: Pointer to the data received
7768 * @data_len: Length of @data
7769 *
7770 * This function parses the incoming NL vendor command data attributes and
7771 * updates the SAP context about channel_hint and DFS mode.
7772 *
7773 * Return: 0 on success; errno on failure
7774 */
7775static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7776 struct wireless_dev *wdev,
7777 const void *data, int data_len)
7778{
7779 int ret;
7780
7781 cds_ssr_protect(__func__);
7782 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7783 cds_ssr_unprotect(__func__);
7784
7785 return ret;
7786}
7787
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307788/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307789 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7790 * @mode : cfg80211 dfs mode
7791 *
7792 * Return: return csr sta roam dfs mode else return NONE
7793 */
7794static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7795 enum dfs_mode mode)
7796{
7797 switch (mode) {
7798 case DFS_MODE_ENABLE:
7799 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7800 break;
7801 case DFS_MODE_DISABLE:
7802 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7803 break;
7804 case DFS_MODE_DEPRIORITIZE:
7805 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7806 break;
7807 default:
7808 hdd_err("STA Roam policy dfs mode is NONE");
7809 return CSR_STA_ROAM_POLICY_NONE;
7810 }
7811}
7812
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307813/*
7814 * hdd_get_sap_operating_band: Get current operating channel
7815 * for sap.
7816 * @hdd_ctx: hdd context
7817 *
7818 * Return : Corresponding band for SAP operating channel
7819 */
7820uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7821{
7822 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7823 QDF_STATUS status;
7824 hdd_adapter_t *adapter;
7825 uint8_t operating_channel = 0;
7826 uint8_t sap_operating_band = 0;
7827 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7828 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7829 adapter = adapter_node->pAdapter;
7830
7831 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7832 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7833 &next);
7834 adapter_node = next;
7835 continue;
7836 }
7837 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7838 if (IS_24G_CH(operating_channel))
7839 sap_operating_band = eCSR_BAND_24;
7840 else if (IS_5G_CH(operating_channel))
7841 sap_operating_band = eCSR_BAND_5G;
7842 else
7843 sap_operating_band = eCSR_BAND_ALL;
7844 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7845 &next);
bings373b99b2017-01-23 10:35:08 +08007846 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307847 }
7848 return sap_operating_band;
7849}
7850
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307851static const struct nla_policy
7852wlan_hdd_set_sta_roam_config_policy[
7853QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7854 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7855 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7856};
7857
7858/**
7859 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7860 * for station connection or roaming.
7861 * @wiphy: Pointer to wireless phy
7862 * @wdev: Pointer to wireless device
7863 * @data: Pointer to data
7864 * @data_len: Length of @data
7865 *
7866 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7867 * channels needs to be skipped in scanning or not.
7868 * If dfs_mode is disabled, driver will not scan DFS channels.
7869 * If skip_unsafe_channels is set, driver will skip unsafe channels
7870 * in Scanning.
7871 *
7872 * Return: 0 on success, negative errno on failure
7873 */
7874static int
7875__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7876 struct wireless_dev *wdev,
7877 const void *data, int data_len)
7878{
7879 struct net_device *dev = wdev->netdev;
7880 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7881 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7882 struct nlattr *tb[
7883 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7884 int ret;
7885 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7886 enum dfs_mode mode = DFS_MODE_NONE;
7887 bool skip_unsafe_channels = false;
7888 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307889 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307890
7891 ENTER_DEV(dev);
7892
7893 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7894 hdd_err("Command not allowed in FTM mode");
7895 return -EINVAL;
7896 }
7897
7898 ret = wlan_hdd_validate_context(hdd_ctx);
7899 if (0 != ret)
7900 return ret;
7901 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7902 data, data_len,
7903 wlan_hdd_set_sta_roam_config_policy)) {
7904 hdd_err("invalid attr");
7905 return -EINVAL;
7906 }
7907 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7908 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7909 if (!IS_DFS_MODE_VALID(mode)) {
7910 hdd_err("attr sta roam dfs mode policy is not valid");
7911 return -EINVAL;
7912 }
7913
7914 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7915
7916 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7917 skip_unsafe_channels = nla_get_u8(
7918 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307919 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307920 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307921 skip_unsafe_channels, adapter->sessionId,
7922 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307923
7924 if (!QDF_IS_STATUS_SUCCESS(status)) {
7925 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7926 return -EINVAL;
7927 }
7928 return 0;
7929}
7930
7931/**
7932 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7933 * connection and roaming for station.
7934 * @wiphy: wiphy structure pointer
7935 * @wdev: Wireless device structure pointer
7936 * @data: Pointer to the data received
7937 * @data_len: Length of @data
7938 *
7939 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7940 * channels needs to be skipped in scanning or not.
7941 * If dfs_mode is disabled, driver will not scan DFS channels.
7942 * If skip_unsafe_channels is set, driver will skip unsafe channels
7943 * in Scanning.
7944 * Return: 0 on success; errno on failure
7945 */
7946static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7947 struct wireless_dev *wdev,
7948 const void *data, int data_len)
7949{
7950 int ret;
7951
7952 cds_ssr_protect(__func__);
7953 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7954 cds_ssr_unprotect(__func__);
7955
7956 return ret;
7957}
7958
Agrawal Ashish467dde42016-09-08 18:44:22 +05307959#ifdef FEATURE_WLAN_CH_AVOID
7960/**
7961 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7962 * is on unsafe channel.
7963 * @wiphy: wiphy structure pointer
7964 * @wdev: Wireless device structure pointer
7965 * @data: Pointer to the data received
7966 * @data_len: Length of @data
7967 *
7968 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7969 * on any of unsafe channels.
7970 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7971 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7972 *
7973 * Return: 0 on success; errno on failure
7974 */
7975static int
7976__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7977 struct wireless_dev *wdev,
7978 const void *data, int data_len)
7979{
7980 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7981 int ret;
7982 uint16_t unsafe_channel_count;
7983 int unsafe_channel_index;
7984 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7985
7986 ENTER_DEV(wdev->netdev);
7987
7988 if (!qdf_ctx) {
7989 cds_err("qdf_ctx is NULL");
7990 return -EINVAL;
7991 }
7992
7993 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7994 hdd_err("Command not allowed in FTM mode");
7995 return -EINVAL;
7996 }
7997
7998 ret = wlan_hdd_validate_context(hdd_ctx);
7999 if (0 != ret)
8000 return ret;
8001 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8002 &(hdd_ctx->unsafe_channel_count),
8003 sizeof(hdd_ctx->unsafe_channel_list));
8004
8005 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8006 (uint16_t)NUM_CHANNELS);
8007 for (unsafe_channel_index = 0;
8008 unsafe_channel_index < unsafe_channel_count;
8009 unsafe_channel_index++) {
8010 hdd_info("Channel %d is not safe",
8011 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8012 }
8013 hdd_unsafe_channel_restart_sap(hdd_ctx);
8014 return 0;
8015}
8016
8017/**
8018 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8019 * is on unsafe channel.
8020 * @wiphy: wiphy structure pointer
8021 * @wdev: Wireless device structure pointer
8022 * @data: Pointer to the data received
8023 * @data_len: Length of @data
8024 *
8025 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8026 * on any of unsafe channels.
8027 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8028 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8029 *
8030 * Return: 0 on success; errno on failure
8031 */
8032static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8033 struct wireless_dev *wdev,
8034 const void *data, int data_len)
8035{
8036 int ret;
8037
8038 cds_ssr_protect(__func__);
8039 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8040 cds_ssr_unprotect(__func__);
8041
8042 return ret;
8043}
8044
8045#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308046/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308047 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8048 * SAP is on unsafe channel.
8049 * @wiphy: wiphy structure pointer
8050 * @wdev: Wireless device structure pointer
8051 * @data: Pointer to the data received
8052 * @data_len: Length of @data
8053 *
8054 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8055 * driver.
8056 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8057 * will initiate restart of sap.
8058 *
8059 * Return: 0 on success; errno on failure
8060 */
8061static int
8062__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8063 struct wireless_dev *wdev,
8064 const void *data, int data_len)
8065{
8066 struct net_device *ndev = wdev->netdev;
8067 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8068 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8069 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8070 uint8_t config_channel = 0;
8071 hdd_ap_ctx_t *ap_ctx;
8072 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308073 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308074
8075 ENTER();
8076
8077 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008078 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308079 return -EINVAL;
8080 }
8081
8082 ret = wlan_hdd_validate_context(hdd_ctx);
8083 if (0 != ret)
8084 return -EINVAL;
8085
8086 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8087 data, data_len,
8088 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008089 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308090 return -EINVAL;
8091 }
8092
8093 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8094 if (!test_bit(SOFTAP_BSS_STARTED,
8095 &hostapd_adapter->event_flags)) {
8096 hdd_err("SAP is not started yet. Restart sap will be invalid");
8097 return -EINVAL;
8098 }
8099
8100 config_channel =
8101 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8102
8103 if (!((IS_24G_CH(config_channel)) ||
8104 (IS_5G_CH(config_channel)))) {
8105 hdd_err("Channel %d is not valid to restart SAP",
8106 config_channel);
8107 return -ENOTSUPP;
8108 }
8109
8110 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8111 ap_ctx->sapConfig.channel = config_channel;
8112 ap_ctx->sapConfig.ch_params.ch_width =
8113 ap_ctx->sapConfig.ch_width_orig;
8114
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008115 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308116 ap_ctx->sapConfig.sec_ch,
8117 &ap_ctx->sapConfig.ch_params);
8118
8119 cds_restart_sap(hostapd_adapter);
8120 }
8121
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308122 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8123 uint32_t freq_len, i;
8124 uint32_t *freq;
8125 uint8_t chans[QDF_MAX_NUM_CHAN];
8126
8127 hdd_debug("setting mandatory freq/chan list");
8128
8129 freq_len = nla_len(
8130 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8131 sizeof(uint32_t);
8132
8133 if (freq_len > QDF_MAX_NUM_CHAN) {
8134 hdd_err("insufficient space to hold channels");
8135 return -ENOMEM;
8136 }
8137
8138 freq = nla_data(
8139 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8140
8141 hdd_debug("freq_len=%d", freq_len);
8142
8143 for (i = 0; i < freq_len; i++) {
8144 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8145 hdd_debug("freq[%d]=%d", i, freq[i]);
8146 }
8147
8148 status = cds_set_sap_mandatory_channels(chans, freq_len);
8149 if (QDF_IS_STATUS_ERROR(status))
8150 return -EINVAL;
8151 }
8152
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308153 return 0;
8154}
8155
8156/**
8157 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8158 * @wiphy: wiphy structure pointer
8159 * @wdev: Wireless device structure pointer
8160 * @data: Pointer to the data received
8161 * @data_len: Length of @data
8162 *
8163 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8164 * driver.
8165 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8166 * will initiate restart of sap.
8167 *
8168 * Return: 0 on success; errno on failure
8169 */
8170static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8171 struct wireless_dev *wdev,
8172 const void *data, int data_len)
8173{
8174 int ret;
8175
8176 cds_ssr_protect(__func__);
8177 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8178 wdev, data, data_len);
8179 cds_ssr_unprotect(__func__);
8180
8181 return ret;
8182}
8183
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308184#undef BPF_INVALID
8185#undef BPF_SET_RESET
8186#undef BPF_VERSION
8187#undef BPF_ID
8188#undef BPF_PACKET_SIZE
8189#undef BPF_CURRENT_OFFSET
8190#undef BPF_PROGRAM
8191#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308192
8193/**
8194 * define short names for the global vendor params
8195 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8196 */
8197#define PARAM_TOTAL_CMD_EVENT_WAKE \
8198 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8199#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8200 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8201#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8202 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8203#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8204 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8205#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8206 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8207#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8208 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8209#define PARAM_TOTAL_RX_DATA_WAKE \
8210 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8211#define PARAM_RX_UNICAST_CNT \
8212 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8213#define PARAM_RX_MULTICAST_CNT \
8214 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8215#define PARAM_RX_BROADCAST_CNT \
8216 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8217#define PARAM_ICMP_PKT \
8218 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8219#define PARAM_ICMP6_PKT \
8220 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8221#define PARAM_ICMP6_RA \
8222 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8223#define PARAM_ICMP6_NA \
8224 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8225#define PARAM_ICMP6_NS \
8226 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8227#define PARAM_ICMP4_RX_MULTICAST_CNT \
8228 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8229#define PARAM_ICMP6_RX_MULTICAST_CNT \
8230 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8231#define PARAM_OTHER_RX_MULTICAST_CNT \
8232 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308233#define PARAM_RSSI_BREACH_CNT \
8234 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8235#define PARAM_LOW_RSSI_CNT \
8236 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8237#define PARAM_GSCAN_CNT \
8238 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8239#define PARAM_PNO_COMPLETE_CNT \
8240 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8241#define PARAM_PNO_MATCH_CNT \
8242 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8243
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308244
8245
8246/**
8247 * hdd_send_wakelock_stats() - API to send wakelock stats
8248 * @ctx: context to be passed to callback
8249 * @data: data passed to callback
8250 *
8251 * This function is used to send wake lock stats to HAL layer
8252 *
8253 * Return: 0 on success, error number otherwise.
8254 */
8255static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8256 const struct sir_wake_lock_stats *data)
8257{
8258 struct sk_buff *skb;
8259 uint32_t nl_buf_len;
8260 uint32_t total_rx_data_wake, rx_multicast_cnt;
8261 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308262 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308263
8264 ENTER();
8265
8266 nl_buf_len = NLMSG_HDRLEN;
8267 nl_buf_len +=
8268 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8269 (NLMSG_HDRLEN + sizeof(uint32_t));
8270
8271 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8272
8273 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008274 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308275 return -ENOMEM;
8276 }
8277
Jeff Johnson64943bd2016-08-23 13:14:06 -07008278 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308279 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008280 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308281 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008282 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308283 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008284 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308285 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008286 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008288 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308289 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008290 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308291 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008292 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8293 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308294 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308295 hdd_info("wow_rssi_breach_wake_up_count %d",
8296 data->wow_rssi_breach_wake_up_count);
8297 hdd_info("wow_low_rssi_wake_up_count %d",
8298 data->wow_low_rssi_wake_up_count);
8299 hdd_info("wow_gscan_wake_up_count %d",
8300 data->wow_gscan_wake_up_count);
8301 hdd_info("wow_pno_complete_wake_up_count %d",
8302 data->wow_pno_complete_wake_up_count);
8303 hdd_info("wow_pno_match_wake_up_count %d",
8304 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308305
8306 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308307 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308308
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308309 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308310 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308311
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308312 rx_multicast_cnt =
8313 data->wow_ipv4_mcast_wake_up_count +
8314 ipv6_rx_multicast_addr_cnt;
8315
8316 total_rx_data_wake =
8317 data->wow_ucast_wake_up_count +
8318 data->wow_bcast_wake_up_count +
8319 rx_multicast_cnt;
8320
8321 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8322 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8323 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8324 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8325 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8326 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8327 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8328 total_rx_data_wake) ||
8329 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8330 data->wow_ucast_wake_up_count) ||
8331 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8332 rx_multicast_cnt) ||
8333 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8334 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308335 nla_put_u32(skb, PARAM_ICMP_PKT,
8336 data->wow_icmpv4_count) ||
8337 nla_put_u32(skb, PARAM_ICMP6_PKT,
8338 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308339 nla_put_u32(skb, PARAM_ICMP6_RA,
8340 data->wow_ipv6_mcast_ra_stats) ||
8341 nla_put_u32(skb, PARAM_ICMP6_NA,
8342 data->wow_ipv6_mcast_na_stats) ||
8343 nla_put_u32(skb, PARAM_ICMP6_NS,
8344 data->wow_ipv6_mcast_ns_stats) ||
8345 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8346 data->wow_ipv4_mcast_wake_up_count) ||
8347 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8348 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308349 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8350 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8351 data->wow_rssi_breach_wake_up_count) ||
8352 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8353 data->wow_low_rssi_wake_up_count) ||
8354 nla_put_u32(skb, PARAM_GSCAN_CNT,
8355 data->wow_gscan_wake_up_count) ||
8356 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8357 data->wow_pno_complete_wake_up_count) ||
8358 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8359 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008360 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308361 goto nla_put_failure;
8362 }
8363
8364 cfg80211_vendor_cmd_reply(skb);
8365
8366 EXIT();
8367 return 0;
8368
8369nla_put_failure:
8370 kfree_skb(skb);
8371 return -EINVAL;
8372}
8373
8374/**
8375 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8376 * @wiphy: wiphy pointer
8377 * @wdev: pointer to struct wireless_dev
8378 * @data: pointer to incoming NL vendor data
8379 * @data_len: length of @data
8380 *
8381 * This function parses the incoming NL vendor command data attributes and
8382 * invokes the SME Api and blocks on a completion variable.
8383 * WMA copies required data and invokes callback
8384 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8385 *
8386 * Return: 0 on success; error number otherwise.
8387 */
8388static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8389 struct wireless_dev *wdev,
8390 const void *data,
8391 int data_len)
8392{
8393 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8394 int status, ret;
8395 struct sir_wake_lock_stats wake_lock_stats;
8396 QDF_STATUS qdf_status;
8397
8398 ENTER();
8399
8400 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008401 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308402 return -EINVAL;
8403 }
8404
8405 status = wlan_hdd_validate_context(hdd_ctx);
8406 if (0 != status)
8407 return -EINVAL;
8408
8409 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8410 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008411 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308412 return -EINVAL;
8413 }
8414
8415 ret = hdd_send_wakelock_stats(hdd_ctx,
8416 &wake_lock_stats);
8417 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008418 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308419
8420 EXIT();
8421 return ret;
8422}
8423
8424/**
8425 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8426 * @wiphy: wiphy pointer
8427 * @wdev: pointer to struct wireless_dev
8428 * @data: pointer to incoming NL vendor data
8429 * @data_len: length of @data
8430 *
8431 * This function parses the incoming NL vendor command data attributes and
8432 * invokes the SME Api and blocks on a completion variable.
8433 * WMA copies required data and invokes callback
8434 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8435 *
8436 * Return: 0 on success; error number otherwise.
8437 */
8438static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8439 struct wireless_dev *wdev,
8440 const void *data, int data_len)
8441{
8442 int ret;
8443
8444 cds_ssr_protect(__func__);
8445 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8446 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008447 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308448
8449 return ret;
8450}
8451
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308452/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308453 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8454 * @wiphy: wiphy structure pointer
8455 * @wdev: Wireless device structure pointer
8456 * @data: Pointer to the data received
8457 * @data_len: Length of @data
8458 *
8459 * This function reads wmi max bus size and fill in the skb with
8460 * NL attributes and send up the NL event.
8461 * Return: 0 on success; errno on failure
8462 */
8463static int
8464__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8465 struct wireless_dev *wdev,
8466 const void *data, int data_len)
8467{
8468 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8469 int ret_val;
8470 struct sk_buff *skb;
8471 uint32_t nl_buf_len;
8472
8473 ENTER();
8474
8475 ret_val = wlan_hdd_validate_context(hdd_ctx);
8476 if (ret_val)
8477 return ret_val;
8478
8479 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8480 hdd_err("Command not allowed in FTM mode");
8481 return -EINVAL;
8482 }
8483
8484 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8485
8486 nl_buf_len = NLMSG_HDRLEN;
8487 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8488
8489 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8490 if (!skb) {
8491 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8492 return -ENOMEM;
8493 }
8494
8495 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8496 hdd_ctx->wmi_max_len)) {
8497 hdd_err("nla put failure");
8498 goto nla_put_failure;
8499 }
8500
8501 cfg80211_vendor_cmd_reply(skb);
8502
8503 EXIT();
8504
8505 return 0;
8506
8507nla_put_failure:
8508 kfree_skb(skb);
8509 return -EINVAL;
8510}
8511
8512/**
8513 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8514 * @wiphy: wiphy structure pointer
8515 * @wdev: Wireless device structure pointer
8516 * @data: Pointer to the data received
8517 * @data_len: Length of @data
8518 *
8519 * Return: 0 on success; errno on failure
8520 */
8521static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8522 struct wireless_dev *wdev,
8523 const void *data, int data_len)
8524{
8525 int ret;
8526
8527 cds_ssr_protect(__func__);
8528 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8529 cds_ssr_unprotect(__func__);
8530
8531 return ret;
8532}
8533
8534/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308535 *__wlan_hdd_cfg80211_setband() - set band
8536 * @wiphy: Pointer to wireless phy
8537 * @wdev: Pointer to wireless device
8538 * @data: Pointer to data
8539 * @data_len: Length of @data
8540 *
8541 * Return: 0 on success, negative errno on failure
8542 */
8543static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8544 struct wireless_dev *wdev,
8545 const void *data, int data_len)
8546{
8547 struct net_device *dev = wdev->netdev;
8548 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8549 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8550 int ret;
8551 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8552 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8553
8554 ENTER();
8555
8556 ret = wlan_hdd_validate_context(hdd_ctx);
8557 if (ret)
8558 return ret;
8559
8560 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8561 hdd_err(FL("Invalid ATTR"));
8562 return -EINVAL;
8563 }
8564
8565 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8566 hdd_err(FL("attr SETBAND_VALUE failed"));
8567 return -EINVAL;
8568 }
8569
8570 ret = hdd_set_band(dev,
8571 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8572
8573 EXIT();
8574 return ret;
8575}
8576
8577/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308578 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8579 * @adapter: hdd adapter
8580 * @channel: channel number
8581 *
8582 * return: QDF status based on success or failure
8583 */
8584static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8585 int channel, int chan_bw)
8586{
8587 if (QDF_STATUS_SUCCESS !=
8588 wlan_hdd_validate_operation_channel(adapter, channel))
8589 return QDF_STATUS_E_FAILURE;
8590 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8591 channel,
8592 PHY_SINGLE_CHANNEL_CENTERED))) {
8593 hdd_notice("channel %d is in nol", channel);
8594 return -EINVAL;
8595 }
8596
8597 if ((wlansap_is_channel_leaking_in_nol(
8598 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8599 channel, chan_bw))) {
8600 hdd_notice("channel %d is leaking in nol", channel);
8601 return -EINVAL;
8602 }
8603
8604 return 0;
8605
8606}
8607
Kapil Gupta8878ad92017-02-13 11:56:04 +05308608static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8609 tsap_Config_t *sap_config,
8610 struct hdd_vendor_chan_info *channel_list)
8611{
8612 sap_config->channel = channel_list->pri_ch;
8613
8614 sap_config->ch_params.center_freq_seg0 =
8615 channel_list->vht_seg0_center_ch;
8616 sap_config->ch_params.center_freq_seg1 =
8617 channel_list->vht_seg1_center_ch;
8618
8619 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8620 sap_config->ch_params.ch_width = channel_list->chan_width;
8621 if (sap_config->channel >= 36)
8622 sap_config->ch_width_orig =
8623 hdd_ctx->config->vhtChannelWidth;
8624 else
8625 sap_config->ch_width_orig =
8626 hdd_ctx->config->nChannelBondingMode24GHz ?
8627 eHT_CHANNEL_WIDTH_40MHZ :
8628 eHT_CHANNEL_WIDTH_20MHZ;
8629
8630 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8631 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8632 sap_config->acs_cfg.vht_seg0_center_ch =
8633 channel_list->vht_seg0_center_ch;
8634 sap_config->acs_cfg.vht_seg1_center_ch =
8635 channel_list->vht_seg1_center_ch;
8636 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8637}
8638
8639static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8640 uint8_t channel_cnt,
8641 struct hdd_vendor_chan_info *channel_list)
8642{
8643 tsap_Config_t *sap_config;
8644 hdd_ap_ctx_t *hdd_ap_ctx;
8645 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8646 QDF_STATUS status = QDF_STATUS_SUCCESS;
8647
8648 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8649 sap_config = &adapter->sessionCtx.ap.sapConfig;
8650
8651 if (QDF_TIMER_STATE_RUNNING ==
8652 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8653 ap.vendor_acs_timer)) {
8654 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8655 }
8656
8657 if (channel_list && channel_list->pri_ch == 0) {
8658 /* Check mode, set default channel */
8659 channel_list->pri_ch = 6;
8660 /*
8661 * sap_select_default_oper_chan(hdd_ctx->hHal,
8662 * sap_config->acs_cfg.hw_mode);
8663 */
8664 }
8665
8666 switch (reason) {
8667 /* SAP init case */
8668 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8669 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8670 /* Update Hostapd */
8671 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8672 break;
8673
8674 /* DFS detected on current channel */
8675 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8676 wlan_sap_update_next_channel(
8677 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8678 channel_list->pri_ch,
8679 channel_list->chan_width);
8680 status = sme_update_new_channel_event(
8681 WLAN_HDD_GET_HAL_CTX(adapter),
8682 adapter->sessionId);
8683 break;
8684
8685 /* LTE coex event on current channel */
8686 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8687 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8688 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8689 hdd_ap_ctx->sapConfig.ch_width_orig =
8690 channel_list->chan_width;
8691 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8692 break;
8693
8694 default:
8695 hdd_info("invalid reason for timer invoke");
8696 }
8697 qdf_mem_free(channel_list);
8698 EXIT();
8699 return status;
8700}
8701
8702/**
8703 * Define short name for vendor channel set config
8704 */
8705#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8706#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8707#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8708#define SET_CHAN_PRIMARY_CHANNEL \
8709 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8710#define SET_CHAN_SECONDARY_CHANNEL \
8711 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8712#define SET_CHAN_SEG0_CENTER_CHANNEL \
8713 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8714#define SET_CHAN_SEG1_CENTER_CHANNEL \
8715 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8716#define SET_CHAN_CHANNEL_WIDTH \
8717 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8718#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8719
8720/**
8721 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8722 * @channel_list: pointer to hdd_vendor_chan_info
8723 * @reason: channel change reason
8724 * @channel_cnt: channel count
8725 * @data: data
8726 * @data_len: data len
8727 *
8728 * Return: 0 on success, negative errno on failure
8729 */
8730static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8731 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8732 const void *data, int data_len)
8733{
8734 int rem, i = 0;
8735 struct nlattr *tb[SET_CHAN_MAX + 1];
8736 struct nlattr *tb2[SET_CHAN_MAX + 1];
8737 struct nlattr *curr_attr;
8738 struct hdd_vendor_chan_info *channel_list;
8739
8740 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8741 hdd_err("Invalid ATTR");
8742 return -EINVAL;
8743 }
8744
8745 if (tb[SET_CHAN_REASON])
8746 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8747
8748 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8749 *channel_cnt = nla_get_u8(tb[
8750 SET_CHAN_CHANNEL_COUNT]);
8751 hdd_info("channel count %d", *channel_cnt);
8752 }
8753
8754 if (!(*channel_cnt)) {
8755 hdd_err("channel count is %d", *channel_cnt);
8756 return -EINVAL;
8757 }
8758
8759 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8760 (*channel_cnt));
8761
8762 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8763 if (nla_parse(tb2,
8764 SET_CHAN_MAX,
8765 nla_data(curr_attr), nla_len(curr_attr),
8766 NULL)) {
8767 hdd_err("nla_parse failed");
8768 return -EINVAL;
8769 }
8770 /* Parse and Fetch allowed SSID list*/
8771 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8772 channel_list[i].pri_ch =
8773 nla_get_u8(
8774 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8775 }
8776 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8777 channel_list[i].ht_sec_ch =
8778 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8779 }
8780 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8781 channel_list[i].vht_seg0_center_ch =
8782 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8783 }
8784 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8785 channel_list[i].vht_seg1_center_ch =
8786 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8787 }
8788 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8789 channel_list[i].chan_width =
8790 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8791 }
8792 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8793 i, channel_list[i].pri_ch,
8794 channel_list[i].ht_sec_ch,
8795 channel_list[i].vht_seg0_center_ch,
8796 channel_list[i].vht_seg1_center_ch,
8797 channel_list[i].chan_width);
8798 i++;
8799 if (i > *channel_cnt)
8800 break;
8801 }
8802 *chan_list_ptr = channel_list;
8803
8804 return 0;
8805}
8806
8807/**
8808 * Undef short names for vendor set channel configuration
8809 */
8810#undef SET_CHAN_REASON
8811#undef SET_CHAN_CHANNEL_COUNT
8812#undef SET_CHAN_CHAN_LIST
8813#undef SET_CHAN_PRIMARY_CHANNEL
8814#undef SET_CHAN_SECONDARY_CHANNEL
8815#undef SET_CHAN_SEG0_CENTER_CHANNEL
8816#undef SET_CHAN_SEG1_CENTER_CHANNEL
8817#undef SET_CHAN_CHANNEL_WIDTH
8818#undef SET_CHAN_MAX
8819
8820/**
8821 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8822 * @wiphy: Pointer to wireless phy
8823 * @wdev: Pointer to wireless device
8824 * @data: Pointer to data
8825 * @data_len: Length of @data
8826 *
8827 * Return: 0 on success, negative errno on failure
8828 */
8829static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8830 struct wireless_dev *wdev,
8831 const void *data, int data_len)
8832{
8833 int ret_val;
8834 QDF_STATUS qdf_status;
8835 uint8_t channel_cnt = 0, reason = -1;
8836 struct hdd_vendor_chan_info *channel_list = NULL;
8837 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8838 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8839
8840 ENTER();
8841
8842 ret_val = wlan_hdd_validate_context(hdd_ctx);
8843 if (ret_val)
8844 return ret_val;
8845
8846 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8847 hdd_err("Command not allowed in FTM mode");
8848 return -EINVAL;
8849 }
8850
8851 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8852 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8853 else {
8854 hdd_err("already timeout happened for acs");
8855 return -EINVAL;
8856 }
8857
8858 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8859 &channel_cnt, data, data_len);
8860 if (ret_val)
8861 return ret_val;
8862
8863 /* Validate channel to be set */
8864 while (channel_cnt && channel_list) {
8865 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8866 channel_list->pri_ch,
8867 channel_list->chan_width);
8868 if (qdf_status == QDF_STATUS_SUCCESS)
8869 break;
8870 channel_cnt--;
8871 channel_list++;
8872 }
8873 if ((channel_cnt <= 0) || !channel_list) {
8874 hdd_err("no available channel/chanlist %p", channel_list);
8875 return -EINVAL;
8876 }
8877
8878 qdf_status = hdd_update_acs_channel(adapter, reason,
8879 channel_cnt, channel_list);
8880 return qdf_status_to_os_return(qdf_status);
8881}
8882
8883/**
8884 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8885 * @wiphy: Pointer to wireless phy
8886 * @wdev: Pointer to wireless device
8887 * @data: Pointer to data
8888 * @data_len: Length of @data
8889 *
8890 * Return: 0 on success, negative errno on failure
8891 */
8892static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8893 struct wireless_dev *wdev,
8894 const void *data, int data_len)
8895{
8896 int ret;
8897
8898 cds_ssr_protect(__func__);
8899 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8900 data_len);
8901 cds_ssr_protect(__func__);
8902
8903 return ret;
8904}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308905
8906/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308907 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8908 * @wiphy: wiphy structure pointer
8909 * @wdev: Wireless device structure pointer
8910 * @data: Pointer to the data received
8911 * @data_len: Length of @data
8912 *
8913 * Return: 0 on success; errno on failure
8914 */
8915static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8916 struct wireless_dev *wdev,
8917 const void *data, int data_len)
8918{
8919 int ret;
8920
8921 cds_ssr_protect(__func__);
8922 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8923 cds_ssr_unprotect(__func__);
8924
8925 return ret;
8926}
8927
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008928/**
8929 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8930 * @nl80211_value: Vendor command attribute value
8931 * @wmi_value: Pointer to return converted WMI return value
8932 *
8933 * Convert NL80211 vendor command value for SAR limit set to WMI value
8934 * Return: 0 on success, -1 on invalid value
8935 */
8936static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8937 u32 *wmi_value)
8938{
8939 int ret = 0;
8940
8941 switch (nl80211_value) {
8942 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8943 *wmi_value = WMI_SAR_FEATURE_OFF;
8944 break;
8945 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8946 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8947 break;
8948 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8949 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8950 break;
8951 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8952 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8953 break;
8954 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8955 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8956 break;
8957 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8958 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8959 break;
8960 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8961 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8962 break;
8963 default:
8964 ret = -1;
8965 }
8966 return ret;
8967}
8968
8969/**
8970 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8971 * @nl80211_value: Vendor command attribute value
8972 * @wmi_value: Pointer to return converted WMI return value
8973 *
8974 * Convert NL80211 vendor command value for SAR BAND to WMI value
8975 * Return: 0 on success, -1 on invalid value
8976 */
8977static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8978{
8979 int ret = 0;
8980
8981 switch (nl80211_value) {
8982 case NL80211_BAND_2GHZ:
8983 *wmi_value = WMI_SAR_2G_ID;
8984 break;
8985 case NL80211_BAND_5GHZ:
8986 *wmi_value = WMI_SAR_5G_ID;
8987 break;
8988 default:
8989 ret = -1;
8990 }
8991 return ret;
8992}
8993
8994/**
8995 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8996 * @nl80211_value: Vendor command attribute value
8997 * @wmi_value: Pointer to return converted WMI return value
8998 *
8999 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9000 * Return: 0 on success, -1 on invalid value
9001 */
9002static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9003 u32 *wmi_value)
9004{
9005 int ret = 0;
9006
9007 switch (nl80211_value) {
9008 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9009 *wmi_value = WMI_SAR_MOD_CCK;
9010 break;
9011 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9012 *wmi_value = WMI_SAR_MOD_OFDM;
9013 break;
9014 default:
9015 ret = -1;
9016 }
9017 return ret;
9018}
9019
9020
9021/**
9022 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9023 * @wiphy: Pointer to wireless phy
9024 * @wdev: Pointer to wireless device
9025 * @data: Pointer to data
9026 * @data_len: Length of @data
9027 *
9028 * This function is used to setup Specific Absorption Rate limit specs.
9029 *
9030 * Return: 0 on success, negative errno on failure
9031 */
9032static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9033 struct wireless_dev *wdev,
9034 const void *data, int data_len)
9035{
9036 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9037 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9038 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9039 *sar_spec_list;
9040 struct sar_limit_cmd_params sar_limit_cmd = {0};
9041 int ret = -EINVAL, i = 0, rem = 0;
9042
9043 ENTER();
9044
9045 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9046 hdd_err("Command not allowed in FTM mode");
9047 return -EPERM;
9048 }
9049
9050 if (wlan_hdd_validate_context(hdd_ctx))
9051 return -EINVAL;
9052
9053 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9054 data, data_len, NULL)) {
9055 hdd_err("Invalid SAR attributes");
9056 return -EINVAL;
9057 }
9058
9059 /* Vendor command manadates all SAR Specs in single call */
9060 sar_limit_cmd.commit_limits = 1;
9061 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9062 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9063 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9064 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9065 &sar_limit_cmd.sar_enable) < 0) {
9066 hdd_err("Invalid SAR Enable attr");
9067 goto fail;
9068 }
9069 }
9070 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9071
9072 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9073 sar_limit_cmd.num_limit_rows = nla_get_u32(
9074 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9075 hdd_info("attr sar num_limit_rows %d",
9076 sar_limit_cmd.num_limit_rows);
9077 }
9078 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9079 hdd_err("SAR Spec list exceed supported size");
9080 goto fail;
9081 }
9082 if (sar_limit_cmd.num_limit_rows == 0)
9083 goto send_sar_limits;
9084 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9085 struct sar_limit_cmd_row) *
9086 sar_limit_cmd.num_limit_rows);
9087 if (!sar_limit_cmd.sar_limit_row_list) {
9088 ret = -ENOMEM;
9089 goto fail;
9090 }
9091 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9092 hdd_err("Invalid SAR SPECs list");
9093 goto fail;
9094 }
9095
9096 nla_for_each_nested(sar_spec_list,
9097 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9098 if (i == sar_limit_cmd.num_limit_rows) {
9099 hdd_warn("SAR Cmd has excess SPECs in list");
9100 break;
9101 }
9102
9103 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9104 nla_data(sar_spec_list), nla_len(sar_spec_list),
9105 NULL)) {
9106 hdd_err("nla_parse failed for SAR Spec list");
9107 goto fail;
9108 }
9109 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9110 if (sar_spec[
9111 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9112 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9113 nla_get_u32(sar_spec[
9114 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9115 } else {
9116 hdd_err("SAR Spec does not have power limit value");
9117 goto fail;
9118 }
9119
9120 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9121 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9122 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9123 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9124 < 0) {
9125 hdd_err("Invalid SAR Band attr");
9126 goto fail;
9127 }
9128 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9129 WMI_SAR_BAND_ID_VALID_MASK;
9130 }
9131 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9132 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9133 nla_get_u32(sar_spec[
9134 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9135 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9136 WMI_SAR_CHAIN_ID_VALID_MASK;
9137 }
9138 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9139 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9140 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9141 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9142 < 0) {
9143 hdd_err("Invalid SAR Modulation attr");
9144 goto fail;
9145 }
9146 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9147 WMI_SAR_MOD_ID_VALID_MASK;
9148 }
9149 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9150 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9151 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9152 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9153 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9154 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9155 i++;
9156 }
9157
9158 if (i < sar_limit_cmd.num_limit_rows) {
9159 hdd_warn("SAR Cmd has less SPECs in list");
9160 sar_limit_cmd.num_limit_rows = i;
9161 }
9162
9163send_sar_limits:
9164 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9165 QDF_STATUS_SUCCESS)
9166 ret = 0;
9167fail:
9168 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9169 return ret;
9170}
9171
9172/**
9173 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9174 * @wiphy: Pointer to wireless phy
9175 * @wdev: Pointer to wireless device
9176 * @data: Pointer to data
9177 * @data_len: Length of @data
9178 *
9179 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9180 *
9181 * Return: 0 on success, negative errno on failure
9182 */
9183static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9184 struct wireless_dev *wdev,
9185 const void *data,
9186 int data_len)
9187{
9188 int ret;
9189
9190 cds_ssr_protect(__func__);
9191 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9192 data_len);
9193 cds_ssr_unprotect(__func__);
9194
9195 return ret;
9196}
9197
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309198static const struct
9199nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9200 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9201 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9202 .len = QDF_MAC_ADDR_SIZE},
9203};
9204
9205/**
9206 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9207 * @wiphy: Pointer to wireless phy
9208 * @wdev: Pointer to wireless device
9209 * @data: Pointer to data
9210 * @data_len: Length of @data
9211 *
9212 * This function is used to enable/disable roaming using vendor commands
9213 *
9214 * Return: 0 on success, negative errno on failure
9215 */
9216static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9217 struct wireless_dev *wdev,
9218 const void *data, int data_len)
9219{
9220 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9221 struct net_device *dev = wdev->netdev;
9222 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9223 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9224 uint32_t is_fast_roam_enabled;
9225 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309226 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309227
9228 ENTER_DEV(dev);
9229
9230 ret = wlan_hdd_validate_context(hdd_ctx);
9231 if (0 != ret)
9232 return ret;
9233
9234 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9235 hdd_err("Command not allowed in FTM mode");
9236 return -EINVAL;
9237 }
9238
9239 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9240 qca_wlan_vendor_attr);
9241 if (ret) {
9242 hdd_err("Invalid ATTR");
9243 return -EINVAL;
9244 }
9245
9246 /* Parse and fetch Enable flag */
9247 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9248 hdd_err("attr enable failed");
9249 return -EINVAL;
9250 }
9251
9252 is_fast_roam_enabled = nla_get_u32(
9253 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009254 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9255 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309256
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009257 if (!adapter->fast_roaming_allowed) {
9258 hdd_err("fast roaming not allowed on %s interface",
9259 adapter->dev->name);
9260 return -EINVAL;
9261 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309262 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309263 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009264 (is_fast_roam_enabled &&
9265 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309266 if (qdf_status != QDF_STATUS_SUCCESS)
9267 hdd_err("sme_config_fast_roaming failed with status=%d",
9268 qdf_status);
9269 ret = qdf_status_to_os_return(qdf_status);
9270
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309271 EXIT();
9272 return ret;
9273}
9274
9275/**
9276 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9277 * @wiphy: Pointer to wireless phy
9278 * @wdev: Pointer to wireless device
9279 * @data: Pointer to data
9280 * @data_len: Length of @data
9281 *
9282 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9283 *
9284 * Return: 0 on success, negative errno on failure
9285 */
9286static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9287 struct wireless_dev *wdev,
9288 const void *data, int data_len)
9289{
9290 int ret;
9291
9292 cds_ssr_protect(__func__);
9293 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9294 cds_ssr_unprotect(__func__);
9295
9296 return ret;
9297}
9298
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309299static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9300 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9301 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9302 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9303 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9304};
9305
9306/**
9307 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9308 * @wiphy: Pointer to wireless phy
9309 * @wdev: Pointer to wireless device
9310 * @data: Pointer to data
9311 * @data_len: Length of @data
9312 *
9313 * Return: 0 on success, negative errno on failure
9314 */
9315static int
9316__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9317 struct wireless_dev *wdev,
9318 const void *data,
9319 int data_len)
9320{
9321 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9322 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9323 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9324 struct nlattr *apth;
9325 int rem;
9326 int ret = 1;
9327 int print_idx = -1;
9328 int module_id = -1;
9329 int bit_mask = -1;
9330 int status;
9331
9332 ENTER();
9333
9334 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9335 hdd_err("Command not allowed in FTM mode");
9336 return -EINVAL;
9337 }
9338
9339 ret = wlan_hdd_validate_context(hdd_ctx);
9340 if (ret != 0)
9341 return -EINVAL;
9342
9343 print_idx = qdf_get_pidx();
9344 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9345 hdd_err("Invalid print controle object index");
9346 return -EINVAL;
9347 }
9348
9349 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9350 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9351 hdd_err("Invalid attr");
9352 return -EINVAL;
9353 }
9354
9355 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9356 hdd_err("attr trace level param failed");
9357 return -EINVAL;
9358 }
9359
9360 nla_for_each_nested(apth,
9361 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9362 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9363 nla_data(apth), nla_len(apth), NULL)) {
9364 hdd_err("Invalid attr");
9365 return -EINVAL;
9366 }
9367
9368 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9369 hdd_err("attr Module ID failed");
9370 return -EINVAL;
9371 }
9372 module_id = nla_get_u32
9373 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9374
9375 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9376 hdd_err("attr Verbose mask failed");
9377 return -EINVAL;
9378 }
9379 bit_mask = nla_get_u32
9380 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9381
9382 status = hdd_qdf_trace_enable(module_id, bit_mask);
9383
9384 if (status != 0)
9385 hdd_err("can not set verbose mask %d for the category %d",
9386 bit_mask, module_id);
9387 }
9388
9389 EXIT();
9390 return ret;
9391}
9392
9393/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309394 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9395 * @wiphy: Pointer to wireless phy
9396 * @wdev: Pointer to wireless device
9397 * @data: Pointer to data
9398 * @data_len: Length of @data
9399 *
9400 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9401 *
9402 * Return: 0 on success, negative errno on failure
9403 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309404
9405static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9406 struct wireless_dev *wdev,
9407 const void *data,
9408 int data_len)
9409{
9410 int ret;
9411
9412 cds_ssr_protect(__func__);
9413 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9414 cds_ssr_unprotect(__func__);
9415
9416 return ret;
9417}
9418
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009419const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9420 {
9421 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9422 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9423 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309424 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009425 .doit = is_driver_dfs_capable
9426 },
9427
9428#ifdef WLAN_FEATURE_NAN
9429 {
9430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9431 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9432 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9433 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9434 .doit = wlan_hdd_cfg80211_nan_request
9435 },
9436#endif
9437
9438#ifdef WLAN_FEATURE_STATS_EXT
9439 {
9440 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9441 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9442 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9443 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9444 .doit = wlan_hdd_cfg80211_stats_ext_request
9445 },
9446#endif
9447#ifdef FEATURE_WLAN_EXTSCAN
9448 {
9449 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9450 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9451 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9452 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9453 .doit = wlan_hdd_cfg80211_extscan_start
9454 },
9455 {
9456 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9457 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9458 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9459 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9460 .doit = wlan_hdd_cfg80211_extscan_stop
9461 },
9462 {
9463 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9464 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9465 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9466 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9467 },
9468 {
9469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9470 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9471 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9472 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9473 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9474 },
9475 {
9476 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9477 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9478 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9479 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9480 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9481 },
9482 {
9483 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9484 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9485 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9486 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9487 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9488 },
9489 {
9490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9491 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9492 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9493 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9494 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9495 },
9496 {
9497 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9498 .info.subcmd =
9499 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9500 .flags =
9501 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9502 WIPHY_VENDOR_CMD_NEED_RUNNING,
9503 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9504 },
9505 {
9506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9507 .info.subcmd =
9508 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9509 .flags =
9510 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9511 WIPHY_VENDOR_CMD_NEED_RUNNING,
9512 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9513 },
9514 {
9515 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9516 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9517 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9518 WIPHY_VENDOR_CMD_NEED_NETDEV |
9519 WIPHY_VENDOR_CMD_NEED_RUNNING,
9520 .doit = wlan_hdd_cfg80211_set_epno_list
9521 },
9522#endif /* FEATURE_WLAN_EXTSCAN */
9523
9524#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9529 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9530 .doit = wlan_hdd_cfg80211_ll_stats_clear
9531 },
9532
9533 {
9534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9537 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9538 .doit = wlan_hdd_cfg80211_ll_stats_set
9539 },
9540
9541 {
9542 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9543 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9544 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9545 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9546 .doit = wlan_hdd_cfg80211_ll_stats_get
9547 },
9548#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9549#ifdef FEATURE_WLAN_TDLS
9550 {
9551 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9552 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9553 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9554 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9555 .doit = wlan_hdd_cfg80211_exttdls_enable
9556 },
9557 {
9558 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9559 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9560 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9561 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9562 .doit = wlan_hdd_cfg80211_exttdls_disable
9563 },
9564 {
9565 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9566 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9567 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9568 .doit = wlan_hdd_cfg80211_exttdls_get_status
9569 },
9570#endif
9571 {
9572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9575 .doit = wlan_hdd_cfg80211_get_supported_features
9576 },
9577 {
9578 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9579 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9580 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9581 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9582 },
9583 {
9584 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9585 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9586 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309587 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009588 },
9589 {
9590 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9591 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9592 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9593 WIPHY_VENDOR_CMD_NEED_NETDEV,
9594 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9595 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009596 {
9597 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9598 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9599 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9600 WIPHY_VENDOR_CMD_NEED_NETDEV,
9601 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9602 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9607 WIPHY_VENDOR_CMD_NEED_NETDEV |
9608 WIPHY_VENDOR_CMD_NEED_RUNNING,
9609 .doit = hdd_cfg80211_get_station_cmd
9610 },
9611 {
9612 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009613 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9614 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9615 WIPHY_VENDOR_CMD_NEED_NETDEV |
9616 WIPHY_VENDOR_CMD_NEED_RUNNING,
9617 .doit = wlan_hdd_cfg80211_do_acs
9618 },
9619
9620 {
9621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9624 WIPHY_VENDOR_CMD_NEED_NETDEV,
9625 .doit = wlan_hdd_cfg80211_get_features
9626 },
9627#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9628 {
9629 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9630 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9632 WIPHY_VENDOR_CMD_NEED_NETDEV |
9633 WIPHY_VENDOR_CMD_NEED_RUNNING,
9634 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9635 },
9636#endif
9637#ifdef FEATURE_WLAN_EXTSCAN
9638 {
9639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9642 WIPHY_VENDOR_CMD_NEED_NETDEV |
9643 WIPHY_VENDOR_CMD_NEED_RUNNING,
9644 .doit = wlan_hdd_cfg80211_set_passpoint_list
9645 },
9646 {
9647 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9648 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9649 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9650 WIPHY_VENDOR_CMD_NEED_NETDEV |
9651 WIPHY_VENDOR_CMD_NEED_RUNNING,
9652 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9653 },
9654 {
9655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9656 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9657 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9658 WIPHY_VENDOR_CMD_NEED_NETDEV |
9659 WIPHY_VENDOR_CMD_NEED_RUNNING,
9660 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9661 },
9662 {
9663 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9664 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9665 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9666 WIPHY_VENDOR_CMD_NEED_NETDEV |
9667 WIPHY_VENDOR_CMD_NEED_RUNNING,
9668 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9669 },
9670#endif /* FEATURE_WLAN_EXTSCAN */
9671 {
9672 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9673 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9674 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9675 WIPHY_VENDOR_CMD_NEED_NETDEV,
9676 .doit = wlan_hdd_cfg80211_get_wifi_info
9677 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009678#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009679 {
9680 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9681 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9682 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9683 WIPHY_VENDOR_CMD_NEED_NETDEV |
9684 WIPHY_VENDOR_CMD_NEED_RUNNING,
9685 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9686 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009687#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009688 {
9689 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9690 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9691 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9692 WIPHY_VENDOR_CMD_NEED_NETDEV,
9693 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9694 },
9695 {
9696 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9697 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9698 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9699 WIPHY_VENDOR_CMD_NEED_NETDEV,
9700 .doit = wlan_hdd_cfg80211_wifi_logger_start
9701 },
9702 {
9703 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9704 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9705 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9706 WIPHY_VENDOR_CMD_NEED_NETDEV,
9707 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9708 },
9709 {
9710 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9711 .info.subcmd =
9712 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9713 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9714 WIPHY_VENDOR_CMD_NEED_NETDEV |
9715 WIPHY_VENDOR_CMD_NEED_RUNNING,
9716 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9717 },
9718 {
9719 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9720 .info.subcmd =
9721 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9722 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9723 WIPHY_VENDOR_CMD_NEED_NETDEV |
9724 WIPHY_VENDOR_CMD_NEED_RUNNING,
9725 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9726 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009727#ifdef WLAN_FEATURE_TSF
9728 {
9729 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9730 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9731 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9732 WIPHY_VENDOR_CMD_NEED_NETDEV |
9733 WIPHY_VENDOR_CMD_NEED_RUNNING,
9734 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9735 },
9736#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009737#ifdef FEATURE_WLAN_TDLS
9738 {
9739 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9740 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9741 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9742 WIPHY_VENDOR_CMD_NEED_NETDEV |
9743 WIPHY_VENDOR_CMD_NEED_RUNNING,
9744 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9745 },
9746#endif
9747#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9748 {
9749 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9750 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9751 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9752 WIPHY_VENDOR_CMD_NEED_NETDEV |
9753 WIPHY_VENDOR_CMD_NEED_RUNNING,
9754 .doit = wlan_hdd_cfg80211_offloaded_packets
9755 },
9756#endif
9757 {
9758 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9759 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9760 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9761 WIPHY_VENDOR_CMD_NEED_NETDEV |
9762 WIPHY_VENDOR_CMD_NEED_RUNNING,
9763 .doit = wlan_hdd_cfg80211_monitor_rssi
9764 },
9765 {
9766 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309767 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9769 WIPHY_VENDOR_CMD_NEED_NETDEV |
9770 WIPHY_VENDOR_CMD_NEED_RUNNING,
9771 .doit = wlan_hdd_cfg80211_set_ns_offload
9772 },
9773 {
9774 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009775 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9776 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9777 WIPHY_VENDOR_CMD_NEED_NETDEV |
9778 WIPHY_VENDOR_CMD_NEED_RUNNING,
9779 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9780 },
9781#ifdef WLAN_FEATURE_MEMDUMP
9782 {
9783 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9784 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9785 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9786 WIPHY_VENDOR_CMD_NEED_NETDEV |
9787 WIPHY_VENDOR_CMD_NEED_RUNNING,
9788 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9789 },
9790#endif /* WLAN_FEATURE_MEMDUMP */
9791 {
9792 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9793 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9794 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9795 WIPHY_VENDOR_CMD_NEED_NETDEV |
9796 WIPHY_VENDOR_CMD_NEED_RUNNING,
9797 .doit = wlan_hdd_cfg80211_vendor_scan
9798 },
9799
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309800 /* Vendor abort scan */
9801 {
9802 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9803 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9804 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9805 WIPHY_VENDOR_CMD_NEED_NETDEV |
9806 WIPHY_VENDOR_CMD_NEED_RUNNING,
9807 .doit = wlan_hdd_vendor_abort_scan
9808 },
9809
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810 /* OCB commands */
9811 {
9812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
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_set_config
9818 },
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9821 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
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_set_utc_time
9826 },
9827 {
9828 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9829 .info.subcmd =
9830 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9831 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9832 WIPHY_VENDOR_CMD_NEED_NETDEV |
9833 WIPHY_VENDOR_CMD_NEED_RUNNING,
9834 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9835 },
9836 {
9837 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9838 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9839 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9840 WIPHY_VENDOR_CMD_NEED_NETDEV |
9841 WIPHY_VENDOR_CMD_NEED_RUNNING,
9842 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9843 },
9844 {
9845 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9846 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9847 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9848 WIPHY_VENDOR_CMD_NEED_NETDEV |
9849 WIPHY_VENDOR_CMD_NEED_RUNNING,
9850 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9851 },
9852 {
9853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9856 WIPHY_VENDOR_CMD_NEED_NETDEV |
9857 WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_dcc_get_stats
9859 },
9860 {
9861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9864 WIPHY_VENDOR_CMD_NEED_NETDEV |
9865 WIPHY_VENDOR_CMD_NEED_RUNNING,
9866 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9867 },
9868 {
9869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9872 WIPHY_VENDOR_CMD_NEED_NETDEV |
9873 WIPHY_VENDOR_CMD_NEED_RUNNING,
9874 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9875 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309876 {
9877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9880 WIPHY_VENDOR_CMD_NEED_NETDEV |
9881 WIPHY_VENDOR_CMD_NEED_RUNNING,
9882 .doit = wlan_hdd_cfg80211_get_link_properties
9883 },
Peng Xu278d0122015-09-24 16:34:17 -07009884 {
Peng Xud2220962016-07-11 17:59:17 -07009885 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009886 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9887 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9888 WIPHY_VENDOR_CMD_NEED_NETDEV |
9889 WIPHY_VENDOR_CMD_NEED_RUNNING,
9890 .doit = wlan_hdd_cfg80211_set_ota_test
9891 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009892#ifdef FEATURE_LFR_SUBNET_DETECTION
9893 {
9894 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9895 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9896 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9897 WIPHY_VENDOR_CMD_NEED_NETDEV |
9898 WIPHY_VENDOR_CMD_NEED_RUNNING,
9899 .doit = wlan_hdd_cfg80211_set_gateway_params
9900 },
9901#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009902 {
Peng Xud2220962016-07-11 17:59:17 -07009903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009904 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9905 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9906 WIPHY_VENDOR_CMD_NEED_NETDEV |
9907 WIPHY_VENDOR_CMD_NEED_RUNNING,
9908 .doit = wlan_hdd_cfg80211_txpower_scale
9909 },
9910 {
9911 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9912 .info.subcmd =
9913 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9918 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309919 {
9920 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9921 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9922 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9923 WIPHY_VENDOR_CMD_NEED_NETDEV |
9924 WIPHY_VENDOR_CMD_NEED_RUNNING,
9925 .doit = wlan_hdd_cfg80211_bpf_offload
9926 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309929 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9931 WIPHY_VENDOR_CMD_NEED_NETDEV |
9932 WIPHY_VENDOR_CMD_NEED_RUNNING,
9933 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9934 },
9935 {
9936 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309937 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9938 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9939 WIPHY_VENDOR_CMD_NEED_NETDEV |
9940 WIPHY_VENDOR_CMD_NEED_RUNNING,
9941 .doit = wlan_hdd_cfg80211_sta_roam_policy
9942 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309943#ifdef FEATURE_WLAN_CH_AVOID
9944 {
9945 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9946 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9947 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9948 WIPHY_VENDOR_CMD_NEED_NETDEV |
9949 WIPHY_VENDOR_CMD_NEED_RUNNING,
9950 .doit = wlan_hdd_cfg80211_avoid_freq
9951 },
9952#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309953 {
9954 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309955 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9956 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9957 WIPHY_VENDOR_CMD_NEED_NETDEV |
9958 WIPHY_VENDOR_CMD_NEED_RUNNING,
9959 .doit = wlan_hdd_cfg80211_sap_configuration_set
9960 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009961 {
Peng Xu4225c152016-07-14 21:18:14 -07009962 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009963 .info.subcmd =
9964 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9965 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9966 WIPHY_VENDOR_CMD_NEED_NETDEV |
9967 WIPHY_VENDOR_CMD_NEED_RUNNING,
9968 .doit = wlan_hdd_cfg80211_p2p_lo_start
9969 },
9970 {
9971 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9972 .info.subcmd =
9973 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9974 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9975 WIPHY_VENDOR_CMD_NEED_NETDEV |
9976 WIPHY_VENDOR_CMD_NEED_RUNNING,
9977 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9978 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309979 {
9980 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9981 .info.subcmd =
9982 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9983 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9984 WIPHY_VENDOR_CMD_NEED_NETDEV |
9985 WIPHY_VENDOR_CMD_NEED_RUNNING,
9986 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9987 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009988#ifdef WLAN_FEATURE_NAN_DATAPATH
9989 {
9990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9991 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9992 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9993 WIPHY_VENDOR_CMD_NEED_NETDEV |
9994 WIPHY_VENDOR_CMD_NEED_RUNNING,
9995 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9996 },
9997#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309998 {
9999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10000 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10002 WIPHY_VENDOR_CMD_NEED_NETDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10005 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010006 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10010 WIPHY_VENDOR_CMD_NEED_NETDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_get_bus_size
10013 },
10014 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10018 WIPHY_VENDOR_CMD_NEED_NETDEV |
10019 WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_update_vendor_channel
10021 },
10022 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010023 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10024 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10025 WIPHY_VENDOR_CMD_NEED_NETDEV |
10026 WIPHY_VENDOR_CMD_NEED_RUNNING,
10027 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010028 },
10029 {
10030 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10031 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10032 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10033 WIPHY_VENDOR_CMD_NEED_NETDEV |
10034 WIPHY_VENDOR_CMD_NEED_RUNNING,
10035 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010036 },
10037#ifdef WLAN_FEATURE_DISA
10038 {
10039 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10040 .info.subcmd =
10041 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10042 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10043 WIPHY_VENDOR_CMD_NEED_NETDEV |
10044 WIPHY_VENDOR_CMD_NEED_RUNNING,
10045 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10046 },
10047#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010048#ifdef FEATURE_WLAN_TDLS
10049 {
10050 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10051 .info.subcmd =
10052 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10053 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10054 WIPHY_VENDOR_CMD_NEED_NETDEV |
10055 WIPHY_VENDOR_CMD_NEED_RUNNING,
10056 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010057 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010058#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010059 {
10060 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10061 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10062 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10063 WIPHY_VENDOR_CMD_NEED_RUNNING,
10064 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10065 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010066 {
10067 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10068 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10069 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10070 WIPHY_VENDOR_CMD_NEED_NETDEV |
10071 WIPHY_VENDOR_CMD_NEED_RUNNING,
10072 .doit = wlan_hdd_cfg80211_set_trace_level
10073 },
10074
Paul Zhang3a210c52016-12-08 10:18:12 +080010075#ifdef WLAN_UMAC_CONVERGENCE
10076 COMMON_VENDOR_COMMANDS
10077#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010078 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010079};
10080
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010081#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10082 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10083 defined(FEATURE_WLAN_SCAN_PNO)
10084/**
10085 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10086 * @wiphy: pointer to wiphy
10087 * @config: pointer to config
10088 *
10089 * Return: None
10090 */
10091static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10092 struct hdd_config *config)
10093{
10094 if (config->configPNOScanSupport) {
10095 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10096 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10097 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10098 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10099 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10100 if (config->max_sched_scan_plan_interval)
10101 wiphy->max_sched_scan_plan_interval =
10102 config->max_sched_scan_plan_interval;
10103 if (config->max_sched_scan_plan_iterations)
10104 wiphy->max_sched_scan_plan_iterations =
10105 config->max_sched_scan_plan_iterations;
10106 }
10107}
10108#else
10109static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10110 struct hdd_config *config)
10111{
10112}
10113#endif
10114
10115
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010116/**
10117 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10118 * @priv_size: Size of the hdd context.
10119 *
10120 * Allocate wiphy context and hdd context.
10121 *
10122 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010123 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010124hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010125{
10126 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010127 hdd_context_t *hdd_ctx;
10128
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129 ENTER();
10130
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10132
10133 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010134 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 return NULL;
10136 }
10137
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010138 hdd_ctx = wiphy_priv(wiphy);
10139
10140 hdd_ctx->wiphy = wiphy;
10141
10142 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010143}
10144
10145/*
10146 * FUNCTION: wlan_hdd_cfg80211_update_band
10147 * This function is called from the supplicant through a
10148 * private ioctl to change the band value
10149 */
10150int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10151{
10152 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010153 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010154
10155 ENTER();
10156
Dustin Browna30892e2016-10-12 17:28:36 -070010157 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010158
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010159 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010160 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161
10162 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10163 struct ieee80211_supported_band *band = wiphy->bands[i];
10164
10165 channelEnabledState =
10166 cds_get_channel_state(band->channels[j].
10167 hw_value);
10168
Dustin Browna30892e2016-10-12 17:28:36 -070010169 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170 /* 5G only */
10171#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10172 /* Enable Social channels for P2P */
10173 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10174 (band->channels[j].center_freq)
10175 && CHANNEL_STATE_ENABLE ==
10176 channelEnabledState)
10177 band->channels[j].flags &=
10178 ~IEEE80211_CHAN_DISABLED;
10179 else
10180#endif
10181 band->channels[j].flags |=
10182 IEEE80211_CHAN_DISABLED;
10183 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010184 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185 eCSR_BAND_24 == eBand) {
10186 /* 2G only */
10187 band->channels[j].flags |=
10188 IEEE80211_CHAN_DISABLED;
10189 continue;
10190 }
10191
Amar Singhal6842e8f2016-02-23 16:30:32 -080010192 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193 band->channels[j].flags &=
10194 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010195 }
10196 }
10197 return 0;
10198}
10199
Peng Xuacfdda12017-02-06 16:15:38 -080010200#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201/*
10202 * FUNCTION: wlan_hdd_cfg80211_init
10203 * This function is called by hdd_wlan_startup()
10204 * during initialization.
10205 * This function is used to initialize and register wiphy structure.
10206 */
10207int wlan_hdd_cfg80211_init(struct device *dev,
10208 struct wiphy *wiphy, struct hdd_config *pCfg)
10209{
10210 int i, j;
10211 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10212
10213 ENTER();
10214
10215 /* Now bind the underlying wlan device with wiphy */
10216 set_wiphy_dev(wiphy, dev);
10217
10218 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010220#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10221 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010222 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223#else
10224 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010225 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010226#endif
10227
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010228 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10229 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10230 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10231#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10232 | WIPHY_FLAG_4ADDR_STATION
10233#endif
10234 | WIPHY_FLAG_OFFCHAN_TX;
10235
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010236#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10237 wiphy->wowlan = &wowlan_support_cfg80211_init;
10238#else
10239 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10240 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10241 wiphy->wowlan.pattern_min_len = 1;
10242 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10243#endif
10244
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010245 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010246#ifdef FEATURE_WLAN_ESE
10247 || pCfg->isEseIniFeatureEnabled
10248#endif
10249 ) {
10250 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10251 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010252#ifdef FEATURE_WLAN_TDLS
10253 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10254 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10255#endif
10256
10257 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10258
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010259#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10260 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10261#endif
10262
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010263 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010264
10265#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010266 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010267#endif
10268
10269 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010270 * driver can still register regulatory callback and
10271 * it will get regulatory settings in wiphy->band[], but
10272 * driver need to determine what to do with both
10273 * regulatory settings
10274 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010275
10276 wiphy->reg_notifier = hdd_reg_notifier;
10277
10278#if defined QCA_WIFI_FTM
10279}
10280#endif
10281
10282 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10283
10284 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10285
10286 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10287
Arun Khandavallifae92942016-08-01 13:31:08 +053010288 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10289 | BIT(NL80211_IFTYPE_ADHOC)
10290 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10291 | BIT(NL80211_IFTYPE_P2P_GO)
10292 | BIT(NL80211_IFTYPE_AP)
10293 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010294
Arun Khandavallifae92942016-08-01 13:31:08 +053010295 if (pCfg->advertiseConcurrentOperation) {
10296 if (pCfg->enableMCC) {
10297 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010298
Arun Khandavallifae92942016-08-01 13:31:08 +053010299 for (i = 0;
10300 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10301 i++) {
10302 if (!pCfg->allowMCCGODiffBI)
10303 wlan_hdd_iface_combination[i].
10304 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010305 }
10306 }
10307 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010308 ARRAY_SIZE(wlan_hdd_iface_combination);
10309 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010310 }
10311
10312 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010313 * on ini values
10314 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315 if (!pCfg->ShortGI20MhzEnable) {
10316 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10317 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 }
10319
10320 if (!pCfg->ShortGI40MhzEnable) {
10321 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10322 }
10323
10324 if (!pCfg->nChannelBondingMode5GHz) {
10325 wlan_hdd_band_5_ghz.ht_cap.cap &=
10326 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10327 }
10328
Abhishek Singhf512bf32016-05-04 16:47:46 +053010329 /*
10330 * In case of static linked driver at the time of driver unload,
10331 * module exit doesn't happens. Module cleanup helps in cleaning
10332 * of static memory.
10333 * If driver load happens statically, at the time of driver unload,
10334 * wiphy flags don't get reset because of static memory.
10335 * It's better not to store channel in static memory.
10336 */
Dustin Browna30892e2016-10-12 17:28:36 -070010337 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10338 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010339 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010340 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010341 hdd_err("Not enough memory to allocate channels");
10342 return -ENOMEM;
10343 }
Dustin Browna30892e2016-10-12 17:28:36 -070010344 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010345 &hdd_channels_2_4_ghz[0],
10346 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010347 if ((hdd_is_5g_supported(pHddCtx)) &&
10348 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10349 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10350 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10351 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010352 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10353 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010354 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010355 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010356 hdd_err("Not enough memory to allocate channels");
10357 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010358 bands[NL80211_BAND_2GHZ]->channels);
10359 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010360 return -ENOMEM;
10361 }
Dustin Browna30892e2016-10-12 17:28:36 -070010362 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010363 &hdd_channels_5_ghz[0],
10364 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010365 }
10366
Dustin Browna30892e2016-10-12 17:28:36 -070010367 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010368
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010369 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010370 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010371
10372 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10373 struct ieee80211_supported_band *band = wiphy->bands[i];
10374
Dustin Browna30892e2016-10-12 17:28:36 -070010375 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 eCSR_BAND_5G == pCfg->nBandCapability) {
10377 /* 5G only */
10378#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10379 /* Enable social channels for P2P */
10380 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10381 (band->channels[j].center_freq))
10382 band->channels[j].flags &=
10383 ~IEEE80211_CHAN_DISABLED;
10384 else
10385#endif
10386 band->channels[j].flags |=
10387 IEEE80211_CHAN_DISABLED;
10388 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010389 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010390 eCSR_BAND_24 == pCfg->nBandCapability) {
10391 /* 2G only */
10392 band->channels[j].flags |=
10393 IEEE80211_CHAN_DISABLED;
10394 continue;
10395 }
10396 }
10397 }
10398 /*Initialise the supported cipher suite details */
10399 wiphy->cipher_suites = hdd_cipher_suites;
10400 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10401
10402 /*signal strength in mBm (100*dBm) */
10403 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10404 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10405
Anurag Chouhan6d760662016-02-20 16:05:43 +053010406 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010407 wiphy->n_vendor_commands =
10408 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10409 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10410
10411 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10412 wiphy->n_vendor_events =
10413 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10414 }
10415
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416 if (pCfg->enableDFSMasterCap) {
10417 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10418 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010419
10420 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10421
10422#ifdef QCA_HT_2040_COEX
10423 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10424#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010425 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010426
10427#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10428 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10429 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10430 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10431 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10432#endif
10433
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010434 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010435 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010437 EXIT();
10438 return 0;
10439}
10440
Abhishek Singhf512bf32016-05-04 16:47:46 +053010441/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010442 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10443 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010444 *
10445 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010446 * memory allocated in wlan_hdd_cfg80211_init also
10447 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010448 *
10449 * Return: void
10450 */
10451void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10452{
10453 int i;
10454
Dustin Browna30892e2016-10-12 17:28:36 -070010455 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010456 if (NULL != wiphy->bands[i] &&
10457 (NULL != wiphy->bands[i]->channels)) {
10458 qdf_mem_free(wiphy->bands[i]->channels);
10459 wiphy->bands[i]->channels = NULL;
10460 }
10461 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010462 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010463}
10464
Yingying Tang80e15f32016-09-27 18:23:01 +080010465/**
10466 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10467 * @hdd_ctx: HDD context
10468 *
10469 * this function will update capabilities for supported bands
10470 *
10471 * Return: void
10472 */
10473static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10474{
10475 uint32_t val32;
10476 uint16_t val16;
10477 tSirMacHTCapabilityInfo *ht_cap_info;
10478 QDF_STATUS status;
10479
10480 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10481 if (QDF_STATUS_SUCCESS != status) {
10482 hdd_err("could not get HT capability info");
10483 val32 = 0;
10484 }
10485 val16 = (uint16_t)val32;
10486 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10487
10488 if (ht_cap_info->txSTBC == true) {
10489 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10490 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10491 IEEE80211_HT_CAP_TX_STBC;
10492 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10493 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10494 IEEE80211_HT_CAP_TX_STBC;
10495 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010496
10497 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10498 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10499 vht_cap.vht_supported = 0;
10500 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10501 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10502 vht_cap.vht_supported = 0;
10503 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10504 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010505}
10506
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010507/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010508 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509 * initialization. In wlan_hdd_cfg80211_init, only the
10510 * default values will be initialized. The final initialization
10511 * of all required members can be done here.
10512 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010513void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010514{
Yingying Tang80e15f32016-09-27 18:23:01 +080010515 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10516
10517 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010518}
10519
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010520/**
10521 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10522 * @cfg: hdd cfg
10523 *
10524 * this function update 11n mode in hdd cfg
10525 *
10526 * Return: void
10527 */
10528void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10529{
10530 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10531 hdd_notice("support 11ac");
10532 } else {
10533 hdd_notice("not support 11ac");
10534 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10535 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10536 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10537 cfg->sap_p2p_11ac_override = 0;
10538 }
10539 }
10540}
10541
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010542/* In this function we are registering wiphy. */
10543int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10544{
10545 ENTER();
10546 /* Register our wiphy dev with cfg80211 */
10547 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010548 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010549 return -EIO;
10550 }
10551
10552 EXIT();
10553 return 0;
10554}
10555
10556/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010557 * HDD function to update wiphy capability based on target offload status.
10558 *
10559 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10560 * capability even before downloading firmware to the target. In discrete
10561 * case, host will get know certain offload capability (say sched_scan
10562 * caps) only after downloading firmware to the target and target boots up.
10563 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10564 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010565 */
10566void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10567{
10568#ifdef FEATURE_WLAN_SCAN_PNO
10569 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10570 struct hdd_config *pCfg = pHddCtx->config;
10571
10572 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10573 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010574 * have PNO support.
10575 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010576 if (!pCfg->PnoOffload) {
10577 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10578 wiphy->max_sched_scan_ssids = 0;
10579 wiphy->max_match_sets = 0;
10580 wiphy->max_sched_scan_ie_len = 0;
10581 }
10582#endif
10583}
10584
10585/* This function registers for all frame which supplicant is interested in */
Wu Gao84d120c2017-03-24 18:46:00 +080010586#ifdef CONVERGED_P2P_ENABLE
10587void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10588{
10589 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10590 /* Register for all P2P action, public action etc frames */
10591 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10592
10593 ENTER();
10594
10595 /* Register frame indication call back */
10596 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10597
10598 /* Register for p2p ack indication */
10599 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10600
10601 /* Right now we are registering these frame when driver is getting
10602 * initialized. Once we will move to 2.6.37 kernel, in which we have
10603 * frame register ops, we will move this code as a part of that
10604 */
10605
10606 /* GAS Initial Request */
10607 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10608 (uint8_t *) GAS_INITIAL_REQ,
10609 GAS_INITIAL_REQ_SIZE);
10610
10611 /* GAS Initial Response */
10612 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10613 (uint8_t *) GAS_INITIAL_RSP,
10614 GAS_INITIAL_RSP_SIZE);
10615
10616 /* GAS Comeback Request */
10617 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10618 (uint8_t *) GAS_COMEBACK_REQ,
10619 GAS_COMEBACK_REQ_SIZE);
10620
10621 /* GAS Comeback Response */
10622 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10623 (uint8_t *) GAS_COMEBACK_RSP,
10624 GAS_COMEBACK_RSP_SIZE);
10625
10626 /* WNM BSS Transition Request frame */
10627 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10628 (uint8_t *) WNM_BSS_ACTION_FRAME,
10629 WNM_BSS_ACTION_FRAME_SIZE);
10630
10631 /* WNM-Notification */
10632 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10633 (uint8_t *) WNM_NOTIFICATION_FRAME,
10634 WNM_NOTIFICATION_FRAME_SIZE);
10635}
10636#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010637void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10638{
10639 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10640 /* Register for all P2P action, public action etc frames */
10641 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10642
10643 ENTER();
10644
Abhishek Singh7996eb72015-12-30 17:24:02 +053010645 /* Register frame indication call back */
10646 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10647
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010648 /* Register for p2p ack indication */
10649 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10650
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010651 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010652 * initialized. Once we will move to 2.6.37 kernel, in which we have
10653 * frame register ops, we will move this code as a part of that
10654 */
10655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010656 /* GAS Initial Request */
10657 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10658 (uint8_t *) GAS_INITIAL_REQ,
10659 GAS_INITIAL_REQ_SIZE);
10660
10661 /* GAS Initial Response */
10662 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10663 (uint8_t *) GAS_INITIAL_RSP,
10664 GAS_INITIAL_RSP_SIZE);
10665
10666 /* GAS Comeback Request */
10667 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10668 (uint8_t *) GAS_COMEBACK_REQ,
10669 GAS_COMEBACK_REQ_SIZE);
10670
10671 /* GAS Comeback Response */
10672 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10673 (uint8_t *) GAS_COMEBACK_RSP,
10674 GAS_COMEBACK_RSP_SIZE);
10675
10676 /* P2P Public Action */
10677 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10678 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10679 P2P_PUBLIC_ACTION_FRAME_SIZE);
10680
10681 /* P2P Action */
10682 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10683 (uint8_t *) P2P_ACTION_FRAME,
10684 P2P_ACTION_FRAME_SIZE);
10685
10686 /* WNM BSS Transition Request frame */
10687 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10688 (uint8_t *) WNM_BSS_ACTION_FRAME,
10689 WNM_BSS_ACTION_FRAME_SIZE);
10690
10691 /* WNM-Notification */
10692 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10693 (uint8_t *) WNM_NOTIFICATION_FRAME,
10694 WNM_NOTIFICATION_FRAME_SIZE);
10695}
Wu Gao84d120c2017-03-24 18:46:00 +080010696#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697
10698void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10699{
10700 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10701 /* Register for all P2P action, public action etc frames */
10702 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10703
10704 ENTER();
10705
10706 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010707 * initialized. Once we will move to 2.6.37 kernel, in which we have
10708 * frame register ops, we will move this code as a part of that
10709 */
10710
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010711 /* GAS Initial Request */
10712
10713 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10714 (uint8_t *) GAS_INITIAL_REQ,
10715 GAS_INITIAL_REQ_SIZE);
10716
10717 /* GAS Initial Response */
10718 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10719 (uint8_t *) GAS_INITIAL_RSP,
10720 GAS_INITIAL_RSP_SIZE);
10721
10722 /* GAS Comeback Request */
10723 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10724 (uint8_t *) GAS_COMEBACK_REQ,
10725 GAS_COMEBACK_REQ_SIZE);
10726
10727 /* GAS Comeback Response */
10728 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10729 (uint8_t *) GAS_COMEBACK_RSP,
10730 GAS_COMEBACK_RSP_SIZE);
10731
10732 /* P2P Public Action */
10733 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10734 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10735 P2P_PUBLIC_ACTION_FRAME_SIZE);
10736
10737 /* P2P Action */
10738 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10739 (uint8_t *) P2P_ACTION_FRAME,
10740 P2P_ACTION_FRAME_SIZE);
10741
10742 /* WNM-Notification */
10743 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10744 (uint8_t *) WNM_NOTIFICATION_FRAME,
10745 WNM_NOTIFICATION_FRAME_SIZE);
10746}
10747
10748#ifdef FEATURE_WLAN_WAPI
10749void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10750 const uint8_t *mac_addr, const uint8_t *key,
10751 int key_Len)
10752{
10753 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10754 tCsrRoamSetKey setKey;
10755 bool isConnected = true;
10756 int status = 0;
10757 uint32_t roamId = 0xFF;
10758 uint8_t *pKeyPtr = NULL;
10759 int n = 0;
10760
Jeff Johnson46b40792016-06-29 14:03:14 -070010761 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010762 hdd_device_mode_to_string(pAdapter->device_mode),
10763 pAdapter->device_mode);
10764
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010765 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010766 setKey.keyId = key_index; /* Store Key ID */
10767 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10768 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10769 setKey.paeRole = 0; /* the PAE role */
10770 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010771 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010772 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010773 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010774 }
10775 setKey.keyLength = key_Len;
10776 pKeyPtr = setKey.Key;
10777 memcpy(pKeyPtr, key, key_Len);
10778
Jeff Johnson46b40792016-06-29 14:03:14 -070010779 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010780 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010781 hdd_notice("WAPI KEY Data[%d]:%02x ",
10782 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010783
10784 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10785 if (isConnected) {
10786 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10787 pAdapter->sessionId, &setKey, &roamId);
10788 }
10789 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010790 hdd_err("sme_roam_set_key returned ERROR status= %d",
10791 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10793 }
10794}
10795#endif /* FEATURE_WLAN_WAPI */
10796
10797uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10798 uint8_t eid)
10799{
10800 int left = length;
10801 uint8_t *ptr = (uint8_t *)ies_ptr;
10802 uint8_t elem_id, elem_len;
10803
10804 while (left >= 2) {
10805 elem_id = ptr[0];
10806 elem_len = ptr[1];
10807 left -= 2;
10808 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010809 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810 eid, elem_len, left);
10811 return NULL;
10812 }
10813 if (elem_id == eid) {
10814 return ptr;
10815 }
10816
10817 left -= elem_len;
10818 ptr += (elem_len + 2);
10819 }
10820 return NULL;
10821}
10822
10823/*
10824 * FUNCTION: wlan_hdd_validate_operation_channel
10825 * called by wlan_hdd_cfg80211_start_bss() and
10826 * wlan_hdd_set_channel()
10827 * This function validates whether given channel is part of valid
10828 * channel list.
10829 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010830QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 int channel)
10832{
10833
10834 uint32_t num_ch = 0;
10835 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10836 u32 indx = 0;
10837 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10838 uint8_t fValidChannel = false, count = 0;
10839 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10840
10841 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10842
10843 if (hdd_pConfig_ini->sapAllowAllChannel) {
10844 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010845 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010846 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847 fValidChannel = true;
10848 break;
10849 }
10850 }
10851 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010852 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010853 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010854 }
10855 } else {
10856 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10857 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010858 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010859 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010860 }
10861 for (indx = 0; indx < num_ch; indx++) {
10862 if (channel == valid_ch[indx]) {
10863 break;
10864 }
10865 }
10866
10867 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010868 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010869 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010870 }
10871 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010872 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010873
10874}
10875
10876#ifdef DHCP_SERVER_OFFLOAD
10877static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10878{
10879 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10880 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10881 uint8_t numEntries = 0;
10882 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10883 uint8_t num;
10884 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010885 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010886 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010887 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010888 return;
10889 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10891 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10892 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10893 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10894 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10895 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010896 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897 goto end;
10898 }
10899 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010900 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010901 goto end;
10902 }
10903 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010904 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010905 goto end;
10906 }
10907 for (num = 0; num < numEntries; num++) {
10908 temp = srv_ip[num];
10909 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10910 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010911 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010912 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010913 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010914 goto end;
10915 }
Jeff Johnson77848112016-06-29 14:52:06 -070010916 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010918 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919 return;
10920}
10921#endif /* DHCP_SERVER_OFFLOAD */
10922
10923static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10924 struct net_device *dev,
10925 struct bss_parameters *params)
10926{
10927 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10928 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10929 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010930 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931
10932 ENTER();
10933
Anurag Chouhan6d760662016-02-20 16:05:43 +053010934 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010935 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010936 return -EINVAL;
10937 }
10938
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010939 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10940 hdd_err("invalid session id: %d", pAdapter->sessionId);
10941 return -EINVAL;
10942 }
10943
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010944 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10946 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010947 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948 hdd_device_mode_to_string(pAdapter->device_mode),
10949 pAdapter->device_mode, params->ap_isolate);
10950
10951 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10952 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010953 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010954 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010955
Krunal Sonib4326f22016-03-10 13:05:51 -080010956 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10957 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010958 return -EOPNOTSUPP;
10959 }
10960
10961 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010962 * want to update this parameter
10963 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964 if (-1 != params->ap_isolate) {
10965 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10966 !!params->ap_isolate;
10967
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010968 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969 pAdapter->sessionId,
10970 pAdapter->sessionCtx.
10971 ap.
10972 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010973 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 ret = -EINVAL;
10975 }
10976 }
10977
10978 EXIT();
10979 return ret;
10980}
10981
Krunal Soni8c37e322016-02-03 16:08:37 -080010982/**
10983 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10984 * @ndev: pointer to net device provided by supplicant
10985 * @type: type of the interface, upper layer wanted to change
10986 *
10987 * Upper layer provides the new interface mode that needs to be changed
10988 * for given net device
10989 *
10990 * Return: success or failure in terms of integer value
10991 */
10992static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 enum nl80211_iftype type)
10994{
Krunal Soni8c37e322016-02-03 16:08:37 -080010995 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10996 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10997 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010998 hdd_wext_state_t *wext;
10999 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011000 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011001
11002 ENTER();
11003
Krunal Soni8c37e322016-02-03 16:08:37 -080011004 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011005 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 return 0;
11007 }
11008
11009 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011010 hdd_stop_adapter(hdd_ctx, adapter, true);
11011 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011012 wdev->iftype = type;
11013 /*Check for sub-string p2p to confirm its a p2p interface */
11014 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011015 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011017 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011018 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011019 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011021 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011022 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011023 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011024 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011025 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11026 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011027 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11028 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011029 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011030 adapter->scan_info.scanAddIE.length;
11031 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011032 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011033 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11034 wext->roamProfile.phyMode =
11035 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11036 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011037 EXIT();
11038 return status;
11039}
11040
11041static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11042 struct net_device *dev,
11043 struct bss_parameters *params)
11044{
11045 int ret;
11046
11047 cds_ssr_protect(__func__);
11048 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11049 cds_ssr_unprotect(__func__);
11050
11051 return ret;
11052}
11053
11054/* FUNCTION: wlan_hdd_change_country_code_cd
11055 * to wait for contry code completion
11056 */
11057void *wlan_hdd_change_country_code_cb(void *pAdapter)
11058{
11059 hdd_adapter_t *call_back_pAdapter = pAdapter;
11060 complete(&call_back_pAdapter->change_country_code);
11061 return NULL;
11062}
11063
Rajeev Kumar98edb772016-01-19 12:42:19 -080011064/**
11065 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11066 * @wiphy: Pointer to the wiphy structure
11067 * @ndev: Pointer to the net device
11068 * @type: Interface type
11069 * @flags: Flags for change interface
11070 * @params: Pointer to change interface parameters
11071 *
11072 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073 */
11074static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11075 struct net_device *ndev,
11076 enum nl80211_iftype type,
11077 u32 *flags,
11078 struct vif_params *params)
11079{
11080 struct wireless_dev *wdev;
11081 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11082 hdd_context_t *pHddCtx;
11083 tCsrRoamProfile *pRoamProfile = NULL;
11084 eCsrRoamBssType LastBSSType;
11085 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011086 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 int status;
11088
11089 ENTER();
11090
Anurag Chouhan6d760662016-02-20 16:05:43 +053011091 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011092 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011093 return -EINVAL;
11094 }
11095
11096 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11097 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011098 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011100
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011101 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011102 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11103 pAdapter->sessionId, type));
11104
Jeff Johnson77848112016-06-29 14:52:06 -070011105 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011106 pAdapter->device_mode, type);
11107
Arun Khandavallifae92942016-08-01 13:31:08 +053011108 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11109 if (status) {
11110 hdd_err("Failed to start modules");
11111 return -EINVAL;
11112 }
11113
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011114 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11116 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011117 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118 return -EINVAL;
11119 }
11120
11121 pConfig = pHddCtx->config;
11122 wdev = ndev->ieee80211_ptr;
11123
11124 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011125 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011126
Nitesh Shahe6359752017-02-23 19:57:50 +053011127 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011128 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11129 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11130 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11131 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 hdd_wext_state_t *pWextState =
11133 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11134
11135 pRoamProfile = &pWextState->roamProfile;
11136 LastBSSType = pRoamProfile->BSSType;
11137
11138 switch (type) {
11139 case NL80211_IFTYPE_STATION:
11140 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011141 case NL80211_IFTYPE_ADHOC:
11142 if (type == NL80211_IFTYPE_ADHOC) {
11143 wlan_hdd_tdls_exit(pAdapter);
11144 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011145 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011146 }
11147 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11148 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011149 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011151 if (hdd_start_adapter(pAdapter)) {
11152 hdd_err("Failed to start adapter :%d",
11153 pAdapter->device_mode);
11154 return -EINVAL;
11155 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 case NL80211_IFTYPE_AP:
11158 case NL80211_IFTYPE_P2P_GO:
11159 {
Jeff Johnson77848112016-06-29 14:52:06 -070011160 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161 (type ==
11162 NL80211_IFTYPE_AP) ? "SoftAP" :
11163 "P2pGo");
11164
11165 /* Cancel any remain on channel for GO mode */
11166 if (NL80211_IFTYPE_P2P_GO == type) {
11167 wlan_hdd_cancel_existing_remain_on_channel
11168 (pAdapter);
11169 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170
Arun Khandavallifae92942016-08-01 13:31:08 +053011171 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172 /* De-init the adapter */
11173 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11174 memset(&pAdapter->sessionCtx, 0,
11175 sizeof(pAdapter->sessionCtx));
11176 pAdapter->device_mode =
11177 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011178 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11179 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180
11181 /*
11182 * Fw will take care incase of concurrency
11183 */
11184
Krunal Sonib4326f22016-03-10 13:05:51 -080011185 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011187 /* To meet Android requirements create
11188 * a randomized MAC address of the
11189 * form 02:1A:11:Fx:xx:xx
11190 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011191 get_random_bytes(&ndev->dev_addr[3], 3);
11192 ndev->dev_addr[0] = 0x02;
11193 ndev->dev_addr[1] = 0x1A;
11194 ndev->dev_addr[2] = 0x11;
11195 ndev->dev_addr[3] |= 0xF0;
11196 memcpy(pAdapter->macAddressCurrent.
11197 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011198 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011199 pr_info("wlan: Generated HotSpot BSSID "
11200 MAC_ADDRESS_STR "\n",
11201 MAC_ADDR_ARRAY(ndev->dev_addr));
11202 }
11203
11204 hdd_set_ap_ops(pAdapter->dev);
11205
Arun Khandavallifae92942016-08-01 13:31:08 +053011206 if (hdd_start_adapter(pAdapter)) {
11207 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011208 return -EINVAL;
11209 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011210 /* Interface type changed update in wiphy structure */
11211 if (wdev) {
11212 wdev->iftype = type;
11213 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011214 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011215 return -EINVAL;
11216 }
11217 goto done;
11218 }
11219
11220 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011221 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 type);
11223 return -EOPNOTSUPP;
11224 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011225 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11226 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227 switch (type) {
11228 case NL80211_IFTYPE_STATION:
11229 case NL80211_IFTYPE_P2P_CLIENT:
11230 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011231 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11232 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011233 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011235 if (hdd_start_adapter(pAdapter)) {
11236 hdd_err("Failed to start adapter :%d",
11237 pAdapter->device_mode);
11238 return -EINVAL;
11239 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011240 goto done;
11241
11242 case NL80211_IFTYPE_AP:
11243 case NL80211_IFTYPE_P2P_GO:
11244 wdev->iftype = type;
11245 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011246 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 goto done;
11248
11249 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011250 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011251 type);
11252 return -EOPNOTSUPP;
11253 }
11254 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011255 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256 pAdapter->device_mode);
11257 return -EOPNOTSUPP;
11258 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259done:
11260 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011261 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011263 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264
11265 EXIT();
11266 return 0;
11267}
11268
Rajeev Kumar98edb772016-01-19 12:42:19 -080011269/**
11270 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11271 * @wiphy: Pointer to the wiphy structure
11272 * @ndev: Pointer to the net device
11273 * @type: Interface type
11274 * @flags: Flags for change interface
11275 * @params: Pointer to change interface parameters
11276 *
11277 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011278 */
11279static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11280 struct net_device *ndev,
11281 enum nl80211_iftype type,
11282 u32 *flags,
11283 struct vif_params *params)
11284{
11285 int ret;
11286
11287 cds_ssr_protect(__func__);
11288 ret =
11289 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11290 cds_ssr_unprotect(__func__);
11291
11292 return ret;
11293}
11294
11295#ifdef FEATURE_WLAN_TDLS
11296static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11297 int index, uint8_t match)
11298{
11299 int i;
11300 for (i = 0; i < index; i++) {
11301 if (arr[i] == match)
11302 return true;
11303 }
11304 return false;
11305}
11306#endif
11307
11308/**
11309 * __wlan_hdd_change_station() - change station
11310 * @wiphy: Pointer to the wiphy structure
11311 * @dev: Pointer to the net device.
11312 * @mac: bssid
11313 * @params: Pointer to station parameters
11314 *
11315 * Return: 0 for success, error number on failure.
11316 */
11317#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11318static int __wlan_hdd_change_station(struct wiphy *wiphy,
11319 struct net_device *dev,
11320 const uint8_t *mac,
11321 struct station_parameters *params)
11322#else
11323static int __wlan_hdd_change_station(struct wiphy *wiphy,
11324 struct net_device *dev,
11325 uint8_t *mac,
11326 struct station_parameters *params)
11327#endif
11328{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011329 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011330 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11331 hdd_context_t *pHddCtx;
11332 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011333 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011334#ifdef FEATURE_WLAN_TDLS
11335 tCsrStaParams StaParams = { 0 };
11336 uint8_t isBufSta = 0;
11337 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011338 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339#endif
11340 int ret;
11341
11342 ENTER();
11343
Anurag Chouhan6d760662016-02-20 16:05:43 +053011344 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011345 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 return -EINVAL;
11347 }
11348
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011349 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011350 TRACE_CODE_HDD_CHANGE_STATION,
11351 pAdapter->sessionId, params->listen_interval));
11352
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011353 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11354 hdd_err("invalid session id: %d", pAdapter->sessionId);
11355 return -EINVAL;
11356 }
11357
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11359 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011360 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011362
11363 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11364
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011365 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011366
Krunal Sonib4326f22016-03-10 13:05:51 -080011367 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11368 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011369 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11370 status =
11371 hdd_softap_change_sta_state(pAdapter,
11372 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011373 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011374
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011375 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011376 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 return -EINVAL;
11378 }
11379 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011380 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11381 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382#ifdef FEATURE_WLAN_TDLS
11383 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011384
11385 if (cds_is_sub_20_mhz_enabled()) {
11386 hdd_err("TDLS not allowed with sub 20 MHz");
11387 return -EINVAL;
11388 }
11389
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390 StaParams.capability = params->capability;
11391 StaParams.uapsd_queues = params->uapsd_queues;
11392 StaParams.max_sp = params->max_sp;
11393
11394 /* Convert (first channel , number of channels) tuple to
11395 * the total list of channels. This goes with the assumption
11396 * that if the first channel is < 14, then the next channels
11397 * are an incremental of 1 else an incremental of 4 till the number
11398 * of channels.
11399 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011400 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011401 if (0 != params->supported_channels_len) {
11402 int i = 0, j = 0, k = 0, no_of_channels = 0;
11403 int num_unique_channels;
11404 int next;
11405 for (i = 0;
11406 i < params->supported_channels_len
11407 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11408 int wifi_chan_index;
11409 if (!wlan_hdd_is_duplicate_channel
11410 (StaParams.supported_channels, j,
11411 params->supported_channels[i])) {
11412 StaParams.
11413 supported_channels[j] =
11414 params->
11415 supported_channels[i];
11416 } else {
11417 continue;
11418 }
11419 wifi_chan_index =
11420 ((StaParams.supported_channels[j] <=
11421 HDD_CHANNEL_14) ? 1 : 4);
11422 no_of_channels =
11423 params->supported_channels[i + 1];
11424
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011425 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 -080011426 StaParams.
11427 supported_channels[j],
11428 wifi_chan_index,
11429 no_of_channels);
11430 for (k = 1; k <= no_of_channels &&
11431 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11432 k++) {
11433 next =
11434 StaParams.
11435 supported_channels[j] +
11436 wifi_chan_index;
11437 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11438 StaParams.
11439 supported_channels[j
11440 +
11441 1]
11442 = next;
11443 } else {
11444 continue;
11445 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011446 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447 j + 1,
11448 StaParams.
11449 supported_channels[j +
11450 1]);
11451 j += 1;
11452 }
11453 }
11454 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011455 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011456 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011457 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 StaParams.
11459 supported_channels[i]);
11460 }
11461 if (MAX_CHANNEL < num_unique_channels)
11462 num_unique_channels = MAX_CHANNEL;
11463 StaParams.supported_channels_len =
11464 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011465 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011466 StaParams.supported_channels_len);
11467 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011468 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011469 params->supported_oper_classes,
11470 params->supported_oper_classes_len);
11471 StaParams.supported_oper_classes_len =
11472 params->supported_oper_classes_len;
11473
11474 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011475 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476 params->ext_capab,
11477 sizeof(StaParams.extn_capability));
11478
11479 if (NULL != params->ht_capa) {
11480 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011481 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011482 sizeof(tSirHTCap));
11483 }
11484
11485 StaParams.supported_rates_len =
11486 params->supported_rates_len;
11487
11488 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11489 * The supported_rates array , for all the structures propogating till Add Sta
11490 * to the firmware has to be modified , if the supplicant (ieee80211) is
11491 * modified to send more rates.
11492 */
11493
11494 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11495 */
11496 if (StaParams.supported_rates_len >
11497 SIR_MAC_MAX_SUPP_RATES)
11498 StaParams.supported_rates_len =
11499 SIR_MAC_MAX_SUPP_RATES;
11500
11501 if (0 != StaParams.supported_rates_len) {
11502 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011503 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011504 params->supported_rates,
11505 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011506 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011507 StaParams.supported_rates_len);
11508 for (i = 0; i < StaParams.supported_rates_len;
11509 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011510 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 StaParams.supported_rates[i]);
11512 }
11513
11514 if (NULL != params->vht_capa) {
11515 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011516 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011517 params->vht_capa,
11518 sizeof(tSirVHTCap));
11519 }
11520
11521 if (0 != params->ext_capab_len) {
11522 /*Define A Macro : TODO Sunil */
11523 if ((1 << 4) & StaParams.extn_capability[3]) {
11524 isBufSta = 1;
11525 }
11526 /* TDLS Channel Switching Support */
11527 if ((1 << 6) & StaParams.extn_capability[3]) {
11528 isOffChannelSupported = 1;
11529 }
11530 }
11531
Nitesh Shah99934ac2016-09-05 15:54:08 +053011532 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011533 (params->ht_capa || params->vht_capa ||
11534 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011535 is_qos_wmm_sta = true;
11536
11537 hdd_notice("%s: TDLS Peer is QOS capable"
11538 " is_qos_wmm_sta= %d HTcapPresent = %d",
11539 __func__, is_qos_wmm_sta,
11540 StaParams.htcap_present);
11541
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011542 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011543 &StaParams,
11544 isBufSta,
11545 isOffChannelSupported,
11546 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011547 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011548 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011549 return -EINVAL;
11550 }
11551
11552 status =
11553 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11554 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011555 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011556 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 return -EINVAL;
11558 }
11559 }
11560#endif
11561 }
11562 EXIT();
11563 return ret;
11564}
11565
11566/**
11567 * wlan_hdd_change_station() - cfg80211 change station handler function
11568 * @wiphy: Pointer to the wiphy structure
11569 * @dev: Pointer to the net device.
11570 * @mac: bssid
11571 * @params: Pointer to station parameters
11572 *
11573 * This is the cfg80211 change station handler function which invokes
11574 * the internal function @__wlan_hdd_change_station with
11575 * SSR protection.
11576 *
11577 * Return: 0 for success, error number on failure.
11578 */
11579#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11580static int wlan_hdd_change_station(struct wiphy *wiphy,
11581 struct net_device *dev,
11582 const u8 *mac,
11583 struct station_parameters *params)
11584#else
11585static int wlan_hdd_change_station(struct wiphy *wiphy,
11586 struct net_device *dev,
11587 u8 *mac,
11588 struct station_parameters *params)
11589#endif
11590{
11591 int ret;
11592
11593 cds_ssr_protect(__func__);
11594 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11595 cds_ssr_unprotect(__func__);
11596
11597 return ret;
11598}
11599
11600/*
11601 * FUNCTION: __wlan_hdd_cfg80211_add_key
11602 * This function is used to initialize the key information
11603 */
11604static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11605 struct net_device *ndev,
11606 u8 key_index, bool pairwise,
11607 const u8 *mac_addr,
11608 struct key_params *params)
11609{
11610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11611 tCsrRoamSetKey setKey;
11612 int status;
11613 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011614 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011615 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011616 hdd_context_t *pHddCtx;
11617 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11618
11619 ENTER();
11620
Anurag Chouhan6d760662016-02-20 16:05:43 +053011621 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011622 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623 return -EINVAL;
11624 }
11625
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011626 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11627 hdd_err("invalid session id: %d", pAdapter->sessionId);
11628 return -EINVAL;
11629 }
11630
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011631 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11633 pAdapter->sessionId, params->key_len));
11634 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11635 status = wlan_hdd_validate_context(pHddCtx);
11636
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011637 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 hdd_device_mode_to_string(pAdapter->device_mode),
11642 pAdapter->device_mode);
11643
11644 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011645 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011646
11647 return -EINVAL;
11648 }
11649
11650 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011651 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652
11653 return -EINVAL;
11654 }
11655
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011656 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657
11658 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011659 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011660 setKey.keyId = key_index;
11661 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011662 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663
11664 switch (params->cipher) {
11665 case WLAN_CIPHER_SUITE_WEP40:
11666 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11667 break;
11668
11669 case WLAN_CIPHER_SUITE_WEP104:
11670 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11671 break;
11672
11673 case WLAN_CIPHER_SUITE_TKIP:
11674 {
11675 u8 *pKey = &setKey.Key[0];
11676 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11677
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011678 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011679
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011680 /* Supplicant sends the 32bytes key in this order
11681 *
11682 * |--------------|----------|----------|
11683 * | Tk1 |TX-MIC | RX Mic |
11684 * |--------------|----------|----------|
11685 * <---16bytes---><--8bytes--><--8bytes-->
11686 *
11687 * Sme expects the 32 bytes key to be in the below order
11688 *
11689 * |--------------|----------|----------|
11690 * | Tk1 |RX-MIC | TX Mic |
11691 * |--------------|----------|----------|
11692 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 */
11694 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011695 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011696
11697 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011698 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699
11700 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011701 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702
11703 break;
11704 }
11705
11706 case WLAN_CIPHER_SUITE_CCMP:
11707 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11708 break;
11709
11710#ifdef FEATURE_WLAN_WAPI
11711 case WLAN_CIPHER_SUITE_SMS4:
11712 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011713 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11715 mac_addr, params->key,
11716 params->key_len);
11717 return 0;
11718 }
11719#endif
11720
11721#ifdef FEATURE_WLAN_ESE
11722 case WLAN_CIPHER_SUITE_KRK:
11723 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11724 break;
11725#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11726 case WLAN_CIPHER_SUITE_BTK:
11727 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11728 break;
11729#endif
11730#endif
11731
11732#ifdef WLAN_FEATURE_11W
11733 case WLAN_CIPHER_SUITE_AES_CMAC:
11734 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11735 break;
11736#endif
11737
11738 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011739 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740 return -EOPNOTSUPP;
11741 }
11742
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011743 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744
11745 if (!pairwise) {
11746 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011747 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011749 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011750 } else {
11751 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011752 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011753 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011754 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011756 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757 /* if a key is already installed, block all subsequent ones */
11758 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011759 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760 return 0;
11761 }
11762
11763 setKey.keyDirection = eSIR_TX_RX;
11764 /*Set the group key */
11765 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11766 pAdapter->sessionId, &setKey, &roamId);
11767
11768 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011769 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011770 return -EINVAL;
11771 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011772 /* Save the keys here and call sme_roam_set_key for setting
11773 * the PTK after peer joins the IBSS network
11774 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011775 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011776 &setKey, sizeof(tCsrRoamSetKey));
11777
11778 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11779 return status;
11780 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011781 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11782 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011783 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11784 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011785 status = wlansap_set_key_sta(
11786 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011787 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011788 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011789 __LINE__, status);
11790 }
11791 }
11792
11793 /* Save the key in ap ctx for use on START_BASS and restart */
11794 if (pairwise ||
11795 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11796 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011797 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 sizeof(tCsrRoamSetKey));
11799 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011800 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 sizeof(tCsrRoamSetKey));
11802
Krunal Sonib4326f22016-03-10 13:05:51 -080011803 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11804 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011805 hdd_wext_state_t *pWextState =
11806 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11807 hdd_station_ctx_t *pHddStaCtx =
11808 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11809
11810 if (!pairwise) {
11811 /* set group key */
11812 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011813 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011814 __func__, __LINE__);
11815 hdd_perform_roam_set_key_complete(pAdapter);
11816 }
11817 }
11818
11819 pWextState->roamProfile.Keys.KeyLength[key_index] =
11820 (u8) params->key_len;
11821
11822 pWextState->roamProfile.Keys.defaultIndex = key_index;
11823
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011824 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011825 KeyMaterial[key_index][0], params->key,
11826 params->key_len);
11827
11828 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11829
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011830 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011831 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11832 setKey.keyDirection);
11833
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011834 /* The supplicant may attempt to set the PTK once
11835 * pre-authentication is done. Save the key in the
11836 * UMAC and include it in the ADD BSS request
11837 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011838 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011840 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011841 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011843 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011844 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011845 return -EINVAL;
11846 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011847
11848 /* issue set key request to SME */
11849 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11850 pAdapter->sessionId, &setKey, &roamId);
11851
11852 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011853 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011854 pHddStaCtx->roam_info.roamingState =
11855 HDD_ROAM_STATE_NONE;
11856 return -EINVAL;
11857 }
11858
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011859 /* in case of IBSS as there was no information
11860 * available about WEP keys during IBSS join, group
11861 * key intialized with NULL key, so re-initialize
11862 * group key with correct value
11863 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011864 if ((eCSR_BSS_TYPE_START_IBSS ==
11865 pWextState->roamProfile.BSSType)
11866 &&
11867 !((IW_AUTH_KEY_MGMT_802_1X ==
11868 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11869 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11870 pHddStaCtx->conn_info.authType)
11871 )
11872 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11873 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11874 )
11875 ) {
11876 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011877 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011878
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011879 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011880 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11881 setKey.keyDirection);
11882
11883 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11884 pAdapter->sessionId, &setKey,
11885 &roamId);
11886
11887 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011888 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889 pHddStaCtx->roam_info.roamingState =
11890 HDD_ROAM_STATE_NONE;
11891 return -EINVAL;
11892 }
11893 }
11894 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011895 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011896 return 0;
11897}
11898
11899static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11900 struct net_device *ndev,
11901 u8 key_index, bool pairwise,
11902 const u8 *mac_addr,
11903 struct key_params *params)
11904{
11905 int ret;
11906 cds_ssr_protect(__func__);
11907 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11908 mac_addr, params);
11909 cds_ssr_unprotect(__func__);
11910
11911 return ret;
11912}
11913
11914/*
11915 * FUNCTION: __wlan_hdd_cfg80211_get_key
11916 * This function is used to get the key information
11917 */
11918static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11919 struct net_device *ndev,
11920 u8 key_index, bool pairwise,
11921 const u8 *mac_addr, void *cookie,
11922 void (*callback)(void *cookie,
11923 struct key_params *)
11924 )
11925{
11926 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11927 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11928 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11929 struct key_params params;
11930
11931 ENTER();
11932
Anurag Chouhan6d760662016-02-20 16:05:43 +053011933 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011934 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011935 return -EINVAL;
11936 }
11937
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011938 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011939 hdd_device_mode_to_string(pAdapter->device_mode),
11940 pAdapter->device_mode);
11941
11942 memset(&params, 0, sizeof(params));
11943
11944 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011945 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011946 key_index);
11947 return -EINVAL;
11948 }
11949
11950 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11951 case eCSR_ENCRYPT_TYPE_NONE:
11952 params.cipher = IW_AUTH_CIPHER_NONE;
11953 break;
11954
11955 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11956 case eCSR_ENCRYPT_TYPE_WEP40:
11957 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11958 break;
11959
11960 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11961 case eCSR_ENCRYPT_TYPE_WEP104:
11962 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11963 break;
11964
11965 case eCSR_ENCRYPT_TYPE_TKIP:
11966 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11967 break;
11968
11969 case eCSR_ENCRYPT_TYPE_AES:
11970 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11971 break;
11972
11973 default:
11974 params.cipher = IW_AUTH_CIPHER_NONE;
11975 break;
11976 }
11977
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011978 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011979 TRACE_CODE_HDD_CFG80211_GET_KEY,
11980 pAdapter->sessionId, params.cipher));
11981
11982 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11983 params.seq_len = 0;
11984 params.seq = NULL;
11985 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11986 callback(cookie, &params);
11987
11988 EXIT();
11989 return 0;
11990}
11991
11992static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11993 struct net_device *ndev,
11994 u8 key_index, bool pairwise,
11995 const u8 *mac_addr, void *cookie,
11996 void (*callback)(void *cookie,
11997 struct key_params *)
11998 )
11999{
12000 int ret;
12001
12002 cds_ssr_protect(__func__);
12003 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12004 mac_addr, cookie, callback);
12005 cds_ssr_unprotect(__func__);
12006
12007 return ret;
12008}
12009
12010/**
12011 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12012 * @wiphy: wiphy interface context
12013 * @ndev: pointer to net device
12014 * @key_index: Key index used in 802.11 frames
12015 * @unicast: true if it is unicast key
12016 * @multicast: true if it is multicast key
12017 *
12018 * This function is required for cfg80211_ops API.
12019 * It is used to delete the key information
12020 * Underlying hardware implementation does not have API to delete the
12021 * encryption key. It is automatically deleted when the peer is
12022 * removed. Hence this function currently does nothing.
12023 * Future implementation may interprete delete key operation to
12024 * replacing the key with a random junk value, effectively making it
12025 * useless.
12026 *
12027 * Return: status code, always 0.
12028 */
12029
12030static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12031 struct net_device *ndev,
12032 u8 key_index,
12033 bool pairwise, const u8 *mac_addr)
12034{
12035 EXIT();
12036 return 0;
12037}
12038
12039/**
12040 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12041 * @wiphy: Pointer to wiphy structure.
12042 * @dev: Pointer to net_device structure.
12043 * @key_index: key index
12044 * @pairwise: pairwise
12045 * @mac_addr: mac address
12046 *
12047 * This is the cfg80211 delete key handler function which invokes
12048 * the internal function @__wlan_hdd_cfg80211_del_key with
12049 * SSR protection.
12050 *
12051 * Return: 0 for success, error number on failure.
12052 */
12053static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12054 struct net_device *dev,
12055 u8 key_index,
12056 bool pairwise, const u8 *mac_addr)
12057{
12058 int ret;
12059
12060 cds_ssr_protect(__func__);
12061 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12062 pairwise, mac_addr);
12063 cds_ssr_unprotect(__func__);
12064
12065 return ret;
12066}
12067
12068/*
12069 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12070 * This function is used to set the default tx key index
12071 */
12072static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12073 struct net_device *ndev,
12074 u8 key_index,
12075 bool unicast, bool multicast)
12076{
12077 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12078 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12079 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12080 hdd_context_t *pHddCtx;
12081 int status;
12082
12083 ENTER();
12084
Anurag Chouhan6d760662016-02-20 16:05:43 +053012085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012086 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087 return -EINVAL;
12088 }
12089
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012090 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12091 hdd_err("invalid session id: %d", pAdapter->sessionId);
12092 return -EINVAL;
12093 }
12094
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012095 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012096 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12097 pAdapter->sessionId, key_index));
12098
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012099 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 hdd_device_mode_to_string(pAdapter->device_mode),
12101 pAdapter->device_mode, key_index);
12102
12103 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012104 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012105 return -EINVAL;
12106 }
12107
12108 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12109 status = wlan_hdd_validate_context(pHddCtx);
12110
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012111 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012112 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113
Krunal Sonib4326f22016-03-10 13:05:51 -080012114 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12115 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012116 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12117 pHddStaCtx->conn_info.ucEncryptionType) &&
12118 (eCSR_ENCRYPT_TYPE_AES !=
12119 pHddStaCtx->conn_info.ucEncryptionType)) {
12120 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012121 * then update the default key index
12122 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123
12124 tCsrRoamSetKey setKey;
12125 uint32_t roamId = 0xFF;
12126 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12127
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012128 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012129
12130 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012131 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132 setKey.keyId = key_index;
12133 setKey.keyLength = Keys->KeyLength[key_index];
12134
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012135 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 &Keys->KeyMaterial[key_index][0],
12137 Keys->KeyLength[key_index]);
12138
12139 setKey.keyDirection = eSIR_TX_RX;
12140
Anurag Chouhanc5548422016-02-24 18:33:27 +053012141 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012142 &pHddStaCtx->conn_info.bssId);
12143
12144 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12145 pWextState->roamProfile.EncryptionType.
12146 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012147 /* In the case of dynamic wep
12148 * supplicant hardcodes DWEP type to
12149 * eCSR_ENCRYPT_TYPE_WEP104 even
12150 * though ap is configured for WEP-40
12151 * encryption. In this canse the key
12152 * length is 5 but the encryption type
12153 * is 104 hence checking the key
12154 * lenght(5) and encryption type(104)
12155 * and switching encryption type to 40
12156 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012157 pWextState->roamProfile.EncryptionType.
12158 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12159 pWextState->roamProfile.mcEncryptionType.
12160 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12161 }
12162
12163 setKey.encType =
12164 pWextState->roamProfile.EncryptionType.
12165 encryptionType[0];
12166
12167 /* Issue set key request */
12168 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12169 pAdapter->sessionId, &setKey,
12170 &roamId);
12171
12172 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012173 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 status);
12175 return -EINVAL;
12176 }
12177 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012178 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012179 /* In SoftAp mode setting key direction for default mode */
12180 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12181 pWextState->roamProfile.EncryptionType.encryptionType[0])
12182 && (eCSR_ENCRYPT_TYPE_AES !=
12183 pWextState->roamProfile.EncryptionType.
12184 encryptionType[0])) {
12185 /* Saving key direction for default key index to TX default */
12186 hdd_ap_ctx_t *pAPCtx =
12187 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12188 pAPCtx->wepKey[key_index].keyDirection =
12189 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012190 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012191 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012192 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012193 }
12194 }
12195
12196 EXIT();
12197 return status;
12198}
12199
12200static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12201 struct net_device *ndev,
12202 u8 key_index,
12203 bool unicast, bool multicast)
12204{
12205 int ret;
12206 cds_ssr_protect(__func__);
12207 ret =
12208 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12209 multicast);
12210 cds_ssr_unprotect(__func__);
12211
12212 return ret;
12213}
12214
Abhishek Singhc9941602016-08-09 16:06:22 +053012215/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012216 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12217 * interface that BSS might have been lost.
12218 * @pAdapter: adaptor
12219 * @bssid: bssid which might have been lost
12220 *
12221 * Return: bss which is unlinked from kernel cache
12222 */
12223struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12224 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012225{
12226 struct net_device *dev = pAdapter->dev;
12227 struct wireless_dev *wdev = dev->ieee80211_ptr;
12228 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 struct cfg80211_bss *bss = NULL;
12230
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012231 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012232 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012234 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012235 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012236 hdd_info("cfg80211_unlink_bss called for BSSID "
12237 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 cfg80211_unlink_bss(wiphy, bss);
12239 }
12240 return bss;
12241}
12242
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012243#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12244 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12245static struct cfg80211_bss *
12246wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12247 struct ieee80211_channel *chan,
12248 struct ieee80211_mgmt *mgmt,
12249 size_t frame_len,
12250 int rssi, gfp_t gfp,
12251 uint64_t boottime_ns)
12252{
12253 struct cfg80211_bss *bss_status = NULL;
12254 struct cfg80211_inform_bss data = {0};
12255
12256 data.chan = chan;
12257 data.boottime_ns = boottime_ns;
12258 data.signal = rssi;
12259 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12260 frame_len, gfp);
12261 return bss_status;
12262}
12263#else
12264static struct cfg80211_bss *
12265wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12266 struct ieee80211_channel *chan,
12267 struct ieee80211_mgmt *mgmt,
12268 size_t frame_len,
12269 int rssi, gfp_t gfp,
12270 uint64_t boottime_ns)
12271{
12272 struct cfg80211_bss *bss_status = NULL;
12273
12274 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12275 rssi, gfp);
12276 return bss_status;
12277}
12278#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012279
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280/**
12281 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12282 * @pAdapter: Pointer to adapter
12283 * @bss_desc: Pointer to bss descriptor
12284 *
12285 * This function is used to inform the BSS details to nl80211 interface.
12286 *
12287 * Return: struct cfg80211_bss pointer
12288 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012289struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12290 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012291{
12292 /*
12293 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12294 * already exists in bss data base of cfg80211 for that particular BSS
12295 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12296 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12297 * As of now there is no possibility to get the mgmt(probe response)
12298 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12299 * and passing to cfg80211_inform_bss_frame.
12300 */
12301 struct net_device *dev = pAdapter->dev;
12302 struct wireless_dev *wdev = dev->ieee80211_ptr;
12303 struct wiphy *wiphy = wdev->wiphy;
12304 int chan_no = bss_desc->channelId;
12305#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12306 qcom_ie_age *qie_age = NULL;
12307 int ie_length =
12308 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12309#else
12310 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12311#endif
12312 const char *ie =
12313 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12314 unsigned int freq;
12315 struct ieee80211_channel *chan;
12316 struct ieee80211_mgmt *mgmt = NULL;
12317 struct cfg80211_bss *bss_status = NULL;
12318 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12319 int rssi = 0;
12320 hdd_context_t *pHddCtx;
12321 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012323 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324
12325 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12326 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012327 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012328 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012330 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012331 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012332 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012333 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 return NULL;
12335 }
12336
12337 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012340 * Instead it wants a monotonic increasing value
12341 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012342 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 mgmt->u.probe_resp.timestamp =
12344 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012345
12346 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12347 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12348
12349#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12350 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12351 /* Assuming this is the last IE, copy at the end */
12352 ie_length -= sizeof(qcom_ie_age);
12353 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12354 qie_age->element_id = QCOM_VENDOR_IE_ID;
12355 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12356 qie_age->oui_1 = QCOM_OUI1;
12357 qie_age->oui_2 = QCOM_OUI2;
12358 qie_age->oui_3 = QCOM_OUI3;
12359 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012360 /*
12361 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12362 * all bss related timestamp is in units of ms. Due to this when scan
12363 * results are sent to lowi the scan age is high.To address this,
12364 * send age in units of 1/10 ms.
12365 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012366 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012367 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012369 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12370 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012371 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12372 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373#endif
12374
12375 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12376 if (bss_desc->fProbeRsp) {
12377 mgmt->frame_control |=
12378 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12379 } else {
12380 mgmt->frame_control |=
12381 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12382 }
12383
12384 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012385 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012386 freq =
12387 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012388 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012390 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012391 freq =
12392 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012393 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012395 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012396 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012397 return NULL;
12398 }
12399
12400 chan = __ieee80211_get_channel(wiphy, freq);
12401 /* When the band is changed on the fly using the GUI, three things are done
12402 * 1. scan abort
12403 * 2. flush scan results from cache
12404 * 3. update the band with the new band user specified (refer to the
12405 * hdd_set_band_helper function) as part of the scan abort, message will be
12406 * queued to PE and we proceed with flushing and changinh the band.
12407 * PE will stop the scanning further and report back the results what ever
12408 * it had till now by calling the call back function.
12409 * if the time between update band and scandone call back is sufficient
12410 * enough the band change reflects in SME, SME validates the channels
12411 * and discards the channels correponding to previous band and calls back
12412 * with zero bss results. but if the time between band update and scan done
12413 * callback is very small then band change will not reflect in SME and SME
12414 * reports to HDD all the channels correponding to previous band.this is due
12415 * to race condition.but those channels are invalid to the new band and so
12416 * this function __ieee80211_get_channel will return NULL.Each time we
12417 * report scan result with this pointer null warning kernel trace is printed.
12418 * if the scan results contain large number of APs continuosly kernel
12419 * warning trace is printed and it will lead to apps watch dog bark.
12420 * So drop the bss and continue to next bss.
12421 */
12422 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012423 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12424 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012425 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012426 return NULL;
12427 }
12428
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012429 /* Based on .ini configuration, raw rssi can be reported for bss.
12430 * Raw rssi is typically used for estimating power.
12431 */
12432
12433 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12434 bss_desc->rssi;
12435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012437 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012439 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012440 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012441 (int)(rssi / 100),
12442 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012443
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012444 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12445 frame_len, rssi,
12446 GFP_KERNEL,
12447 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012448 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012449 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012450 return bss_status;
12451}
12452
12453/**
12454 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12455 * @pAdapter: Pointer to adapter
12456 * @pRoamInfo: Pointer to roam info
12457 *
12458 * This function is used to update the BSS data base of CFG8011
12459 *
12460 * Return: struct cfg80211_bss pointer
12461 */
12462struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12463 tCsrRoamInfo *pRoamInfo)
12464{
12465 tCsrRoamConnectedProfile roamProfile;
12466 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12467 struct cfg80211_bss *bss = NULL;
12468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12470 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12471
12472 if (NULL != roamProfile.pBssDesc) {
12473 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12474 roamProfile.pBssDesc);
12475
12476 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012477 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012478
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012479 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012481 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012482 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012483 return bss;
12484}
12485/**
12486 * wlan_hdd_cfg80211_update_bss() - update bss
12487 * @wiphy: Pointer to wiphy
12488 * @pAdapter: Pointer to adapter
12489 * @scan_time: scan request timestamp
12490 *
12491 * Return: zero if success, non-zero otherwise
12492 */
12493int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12494 hdd_adapter_t *pAdapter,
12495 uint32_t scan_time)
12496{
12497 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12498 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012499 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 tScanResultHandle pResult;
12501 struct cfg80211_bss *bss_status = NULL;
12502 hdd_context_t *pHddCtx;
12503 int ret;
12504
12505 ENTER();
12506
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012507 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12508 hdd_err("invalid session id: %d", pAdapter->sessionId);
12509 return -EINVAL;
12510 }
12511
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012512 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012513 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12514 NO_SESSION, pAdapter->sessionId));
12515
12516 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12517 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012518 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012520
12521 /* start getting scan results and populate cgf80211 BSS database */
12522 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12523
12524 /* no scan results */
12525 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012526 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012527 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528 }
12529
12530 pScanResult = sme_scan_result_get_first(hHal, pResult);
12531
12532 while (pScanResult) {
12533 /*
12534 * - cfg80211_inform_bss() is not updating ie field of bss
12535 * entry if entry already exists in bss data base of cfg80211
12536 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12537 * to update thebss entry instead of cfg80211_inform_bss,
12538 * But this call expects mgmt packet as input. As of now
12539 * there is no possibility to get the mgmt(probe response)
12540 * frame from PE, converting bss_desc to
12541 * ieee80211_mgmt(probe response) and passing to c
12542 * fg80211_inform_bss_frame.
12543 * - Update BSS only if beacon timestamp is later than
12544 * scan request timestamp.
12545 */
12546 if ((scan_time == 0) ||
12547 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012548 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 bss_status =
12550 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12551 &pScanResult->BssDescriptor);
12552
12553 if (NULL == bss_status) {
12554 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12555 } else {
12556 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012557 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012558 bss_status);
12559 }
12560 } else {
12561 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12562 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12563 }
12564 pScanResult = sme_scan_result_get_next(hHal, pResult);
12565 }
12566
12567 sme_scan_result_purge(hHal, pResult);
12568 /*
12569 * For SAP mode, scan is invoked by hostapd during SAP start
12570 * if hostapd is restarted, we need to flush previous scan
12571 * result so that it will reflect environment change
12572 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012573 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12575 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12576#endif
12577 )
12578 sme_scan_flush_result(hHal);
12579
12580 EXIT();
12581 return 0;
12582}
12583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584/**
12585 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12586 * @pAdapter: Pointer to adapter
12587 * @pRoamInfo: Pointer to roam info
12588 * @index: Index
12589 * @preauth: Preauth flag
12590 *
12591 * This function is used to notify the supplicant of a new PMKSA candidate.
12592 *
12593 * Return: 0 for success, non-zero for failure
12594 */
12595int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12596 tCsrRoamInfo *pRoamInfo,
12597 int index, bool preauth)
12598{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012599 struct net_device *dev = pAdapter->dev;
12600 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12601
12602 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012603 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012604
12605 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012606 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 return -EINVAL;
12608 }
12609
12610 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012611 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12613 cfg80211_pmksa_candidate_notify(dev, index,
12614 pRoamInfo->bssid.bytes,
12615 preauth, GFP_KERNEL);
12616 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 return 0;
12618}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012619
12620#ifdef FEATURE_WLAN_LFR_METRICS
12621/**
12622 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12623 * @pAdapter: Pointer to adapter
12624 * @pRoamInfo: Pointer to roam info
12625 *
12626 * 802.11r/LFR metrics reporting function to report preauth initiation
12627 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012628 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012629 */
12630#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012631QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012632 tCsrRoamInfo *pRoamInfo)
12633{
12634 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12635 union iwreq_data wrqu;
12636
12637 ENTER();
12638
12639 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012640 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012641 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012642 }
12643
12644 /* create the event */
12645 memset(&wrqu, 0, sizeof(wrqu));
12646 memset(metrics_notification, 0, sizeof(metrics_notification));
12647
12648 wrqu.data.pointer = metrics_notification;
12649 wrqu.data.length = scnprintf(metrics_notification,
12650 sizeof(metrics_notification),
12651 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12652 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12653
12654 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12655 metrics_notification);
12656
12657 EXIT();
12658
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012659 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012660}
12661
12662/**
12663 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12664 * @pAdapter: Pointer to adapter
12665 * @pRoamInfo: Pointer to roam info
12666 * @preauth_status: Preauth status
12667 *
12668 * 802.11r/LFR metrics reporting function to report handover initiation
12669 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012670 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012672QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012673wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12674 tCsrRoamInfo *pRoamInfo,
12675 bool preauth_status)
12676{
12677 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12678 union iwreq_data wrqu;
12679
12680 ENTER();
12681
12682 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012683 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012684 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012685 }
12686
12687 /* create the event */
12688 memset(&wrqu, 0, sizeof(wrqu));
12689 memset(metrics_notification, 0, sizeof(metrics_notification));
12690
12691 scnprintf(metrics_notification, sizeof(metrics_notification),
12692 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12693 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12694
12695 if (1 == preauth_status)
12696 strlcat(metrics_notification, " true",
12697 sizeof(metrics_notification));
12698 else
12699 strlcat(metrics_notification, " false",
12700 sizeof(metrics_notification));
12701
12702 wrqu.data.pointer = metrics_notification;
12703 wrqu.data.length = strlen(metrics_notification);
12704
12705 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12706 metrics_notification);
12707
12708 EXIT();
12709
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012710 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711}
12712
12713/**
12714 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12715 * @pAdapter: Pointer to adapter
12716 * @pRoamInfo: Pointer to roam info
12717 *
12718 * 802.11r/LFR metrics reporting function to report handover initiation
12719 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012720 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012722QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012723 tCsrRoamInfo *pRoamInfo)
12724{
12725 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12726 union iwreq_data wrqu;
12727
12728 ENTER();
12729
12730 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012731 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012732 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733 }
12734
12735 /* create the event */
12736 memset(&wrqu, 0, sizeof(wrqu));
12737 memset(metrics_notification, 0, sizeof(metrics_notification));
12738
12739 wrqu.data.pointer = metrics_notification;
12740 wrqu.data.length = scnprintf(metrics_notification,
12741 sizeof(metrics_notification),
12742 "QCOM: LFR_PREAUTH_HANDOVER "
12743 MAC_ADDRESS_STR,
12744 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12745
12746 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12747 metrics_notification);
12748
12749 EXIT();
12750
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012751 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012752}
12753#endif
12754
12755/**
12756 * hdd_select_cbmode() - select channel bonding mode
12757 * @pAdapter: Pointer to adapter
12758 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012759 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 *
12761 * Return: none
12762 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012763void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12764 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012766 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012767 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012768 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012769
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012770 /*
12771 * CDS api expects secondary channel for calculating
12772 * the channel params
12773 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012774 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012775 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12776 if (operationChannel >= 1 && operationChannel <= 5)
12777 sec_ch = operationChannel + 4;
12778 else if (operationChannel >= 6 && operationChannel <= 13)
12779 sec_ch = operationChannel - 4;
12780 }
12781
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012783 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012784
12785 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012786 eHddDot11Mode hdd_dot11_mode;
12787 uint8_t iniDot11Mode =
12788 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12789
12790 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12791 switch (iniDot11Mode) {
12792 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012793 case eHDD_DOT11_MODE_11ax:
12794 case eHDD_DOT11_MODE_11ax_ONLY:
12795 if (sme_is_feature_supported_by_fw(DOT11AX))
12796 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12797 else if (sme_is_feature_supported_by_fw(DOT11AC))
12798 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12799 else
12800 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12801 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012802 case eHDD_DOT11_MODE_11ac:
12803 case eHDD_DOT11_MODE_11ac_ONLY:
12804 if (sme_is_feature_supported_by_fw(DOT11AC))
12805 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12806 else
12807 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12808 break;
12809 case eHDD_DOT11_MODE_11n:
12810 case eHDD_DOT11_MODE_11n_ONLY:
12811 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12812 break;
12813 default:
12814 hdd_dot11_mode = iniDot11Mode;
12815 break;
12816 }
12817 ch_info->channel_width = ch_params->ch_width;
12818 ch_info->phy_mode =
12819 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012820 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012821 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012822 hdd_info("ch_info width %d, phymode %d channel %d",
12823 ch_info->channel_width, ch_info->phy_mode,
12824 ch_info->channel);
12825 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826}
12827
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012828/**
12829 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12830 * @adapter: STA adapter
12831 * @roam_profile: STA roam profile
12832 *
12833 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12834 *
12835 * Return: false if sta-sap conc is not allowed, else return true
12836 */
12837static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12838 tCsrRoamProfile *roam_profile)
12839{
12840 hdd_context_t *hdd_ctx;
12841 hdd_adapter_t *ap_adapter;
12842 hdd_ap_ctx_t *hdd_ap_ctx;
12843 hdd_hostapd_state_t *hostapd_state;
12844 uint8_t channel = 0;
12845 QDF_STATUS status;
12846
12847 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12848 if (!hdd_ctx) {
12849 hdd_err("HDD context is NULL");
12850 return true;
12851 }
12852
12853 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12854 /* probably no sap running, no handling required */
12855 if (ap_adapter == NULL)
12856 return true;
12857
12858 /*
12859 * sap is not in started state, so it is fine to go ahead with sta.
12860 * if sap is currently doing CAC then don't allow sta to go further.
12861 */
12862 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12863 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12864 return true;
12865
12866 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12867 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12868 return false;
12869 }
12870
12871 /*
12872 * log and return error, if we allow STA to go through, we don't
12873 * know what is going to happen better stop sta connection
12874 */
12875 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12876 if (NULL == hdd_ap_ctx) {
12877 hdd_err("AP context not found");
12878 return false;
12879 }
12880
12881 /* sap is on non-dfs channel, nothing to handle */
12882 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12883 hdd_info("sap is on non-dfs channel, sta is allowed");
12884 return true;
12885 }
12886 /*
12887 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012888 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012889 */
12890 status = cds_get_channel_from_scan_result(adapter,
12891 roam_profile, &channel);
12892
Nitesh Shah59774522016-09-16 15:14:21 +053012893 /*
12894 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12895 * channels for roaming case.
12896 */
12897 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12898 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12899 return true;
12900 }
12901
12902 /*
12903 * If channel is 0 or DFS then better to call pcl and find out the
12904 * best channel. If channel is non-dfs 5 GHz then better move SAP
12905 * to STA's channel to make scc, so we have room for 3port MCC
12906 * scenario.
12907 */
12908 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012909 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12910 true);
12911
12912 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12913 qdf_event_reset(&hostapd_state->qdf_event);
12914 status = wlansap_set_channel_change_with_csa(
12915 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12916 hdd_ap_ctx->sapConfig.ch_width_orig);
12917
12918 if (QDF_STATUS_SUCCESS != status) {
12919 hdd_err("Set channel with CSA IE failed, can't allow STA");
12920 return false;
12921 }
12922
12923 /*
12924 * wait here for SAP to finish the channel switch. When channel
12925 * switch happens, SAP sends few beacons with CSA_IE. After
12926 * successfully Transmission of those beacons, it will move its
12927 * state from started to disconnected and move to new channel.
12928 * once it moves to new channel, sap again moves its state
12929 * machine from disconnected to started and set this event.
12930 * wait for 10 secs to finish this.
12931 */
12932 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12933 if (!QDF_IS_STATUS_SUCCESS(status)) {
12934 hdd_err("wait for qdf_event failed, STA not allowed!!");
12935 return false;
12936 }
12937
12938 return true;
12939}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012940
Abhishek Singhcfb44482017-03-10 12:42:37 +053012941#ifdef WLAN_FEATURE_11W
12942/**
12943 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12944 * @roam_profile: pointer to roam profile
12945 *
12946 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12947 * or pmf=2 is an explicit configuration in the supplicant
12948 * configuration, drop the connection request.
12949 *
12950 * Return: 0 if check result is valid, otherwise return error code
12951 */
12952static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12953{
12954 if (roam_profile->MFPEnabled &&
12955 !(roam_profile->MFPRequired ||
12956 roam_profile->MFPCapable)) {
12957 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12958 roam_profile->MFPEnabled,
12959 roam_profile->MFPRequired,
12960 roam_profile->MFPCapable);
12961 return -EINVAL;
12962 }
12963 return 0;
12964}
12965#else
12966static inline
12967int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12968{
12969 return 0;
12970}
12971#endif
12972
Krunal Soni31949422016-07-29 17:17:53 -070012973/**
12974 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012976 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 * @ssid_len: Length of ssid
12978 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012979 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012980 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012981 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 *
12983 * This function is used to start the association process
12984 *
12985 * Return: 0 for success, non-zero for failure
12986 */
Krunal Soni31949422016-07-29 17:17:53 -070012987static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012988 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012989 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012990 u8 operatingChannel,
12991 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012992{
12993 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012994 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995 hdd_wext_state_t *pWextState;
12996 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012997 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 uint32_t roamId;
12999 tCsrRoamProfile *pRoamProfile;
13000 eCsrAuthType RSNAuthType;
13001 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013002 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013003
13004 ENTER();
13005
13006 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13007 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013008 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013009
13010 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013011 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013012 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013013
13014 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013015 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013016 status = -EINVAL;
13017 goto ret_status;
13018 }
13019
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +053013020 if (true == cds_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013021 hdd_err("Connection refused: conn in progress");
13022 status = -EINVAL;
13023 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 }
13025
13026 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013027 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13028 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029
13030 if (pRoamProfile) {
13031 hdd_station_ctx_t *pHddStaCtx;
13032 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13033
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013034 /* Restart the opportunistic timer
13035 *
13036 * If hw_mode_change_in_progress is true, then wait
13037 * till firmware sends the callback for hw_mode change.
13038 *
13039 * Else set connect_in_progress as true and proceed.
13040 */
13041 cds_restart_opportunistic_timer(false);
13042 if (cds_is_hw_mode_change_in_progress()) {
13043 status = qdf_wait_for_connection_update();
13044 if (!QDF_IS_STATUS_SUCCESS(status)) {
13045 hdd_err("qdf wait for event failed!!");
13046 status = -EINVAL;
13047 goto ret_status;
13048 }
13049 }
13050 cds_set_connection_in_progress(true);
13051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 if (HDD_WMM_USER_MODE_NO_QOS ==
13053 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13054 /*QoS not enabled in cfg file */
13055 pRoamProfile->uapsd_mask = 0;
13056 } else {
13057 /*QoS enabled, update uapsd mask from cfg file */
13058 pRoamProfile->uapsd_mask =
13059 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13060 }
13061
13062 pRoamProfile->SSIDs.numOfSSIDs = 1;
13063 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013064 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013066 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013067 ssid, ssid_len);
13068
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013069 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013070 /* cleanup bssid hint */
13071 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13072 QDF_MAC_ADDR_SIZE);
13073 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13074 QDF_MAC_ADDR_SIZE);
13075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 if (bssid) {
13077 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013078 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013079 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013080 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013081 /*
13082 * Save BSSID in seperate variable as
13083 * pRoamProfile's BSSID is getting zeroed out in the
13084 * association process. In case of join failure
13085 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013087 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013088 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013089 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013091 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13092 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013093 /*
13094 * Save BSSID in a separate variable as
13095 * pRoamProfile's BSSID is getting zeroed out in the
13096 * association process. In case of join failure
13097 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013099 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013100 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013101 hdd_info("bssid_hint is given by upper layer %pM",
13102 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013103 }
13104
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013105 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 pRoamProfile->SSIDs.SSIDList->SSID.length,
13107 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13108 operatingChannel);
13109
13110 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13111 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13114 }
13115#ifdef FEATURE_WLAN_WAPI
13116 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013117 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 switch (pAdapter->wapi_info.wapiAuthMode) {
13119 case WAPI_AUTH_MODE_PSK:
13120 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013121 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 pAdapter->wapi_info.wapiAuthMode);
13123 pRoamProfile->AuthType.authType[0] =
13124 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13125 break;
13126 }
13127 case WAPI_AUTH_MODE_CERT:
13128 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013129 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013130 pAdapter->wapi_info.wapiAuthMode);
13131 pRoamProfile->AuthType.authType[0] =
13132 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13133 break;
13134 }
13135 } /* End of switch */
13136 if (pAdapter->wapi_info.wapiAuthMode ==
13137 WAPI_AUTH_MODE_PSK
13138 || pAdapter->wapi_info.wapiAuthMode ==
13139 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013140 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013141 pRoamProfile->AuthType.numEntries = 1;
13142 pRoamProfile->EncryptionType.numEntries = 1;
13143 pRoamProfile->EncryptionType.encryptionType[0] =
13144 eCSR_ENCRYPT_TYPE_WPI;
13145 pRoamProfile->mcEncryptionType.numEntries = 1;
13146 pRoamProfile->mcEncryptionType.
13147 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13148 }
13149 }
Krunal Soni31949422016-07-29 17:17:53 -070013150#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013151 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013152 pRoamProfile->csrPersona = pAdapter->device_mode;
13153
13154 if (operatingChannel) {
13155 pRoamProfile->ChannelInfo.ChannelList =
13156 &operatingChannel;
13157 pRoamProfile->ChannelInfo.numOfChannels = 1;
13158 } else {
13159 pRoamProfile->ChannelInfo.ChannelList = NULL;
13160 pRoamProfile->ChannelInfo.numOfChannels = 0;
13161 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013162 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163 && operatingChannel) {
13164 /*
13165 * Need to post the IBSS power save parameters
13166 * to WMA. WMA will configure this parameters
13167 * to firmware if power save is enabled by the
13168 * firmware.
13169 */
13170 status = hdd_set_ibss_power_save_params(pAdapter);
13171
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013172 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013173 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013174 status = -EINVAL;
13175 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013177 pRoamProfile->ch_params.ch_width =
13178 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013179 /*
13180 * In IBSS mode while operating in 2.4 GHz,
13181 * the device supports only 20 MHz.
13182 */
13183 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13184 pRoamProfile->ch_params.ch_width =
13185 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013186 hdd_select_cbmode(pAdapter, operatingChannel,
13187 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 }
13189
Abhishek Singhcfb44482017-03-10 12:42:37 +053013190 if (wlan_hdd_cfg80211_check_pmf_valid(
13191 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013192 status = -EINVAL;
13193 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 }
13195
Krunal Soni31949422016-07-29 17:17:53 -070013196 /*
13197 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013198 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013199 * enhancements, the supplicant is not issuing the scan command
13200 * now. So the unicast frames which are sent from the host are
13201 * not having the additional IEs. If it is P2P CLIENT and there
13202 * is no additional IE present in roamProfile, then use the
13203 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 */
13205
Krunal Sonib4326f22016-03-10 13:05:51 -080013206 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 (!pRoamProfile->pAddIEScan)) {
13208 pRoamProfile->pAddIEScan =
13209 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13210 pRoamProfile->nAddIEScanLength =
13211 pAdapter->scan_info.scanAddIE.length;
13212 }
13213 /*
13214 * When policy manager is enabled from ini file, we shouldn't
13215 * check for other concurrency rules.
13216 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013217 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013218 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013219 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013220 pAdapter, pRoamProfile, &roamId)) {
13221 status = 0;
13222 goto conn_failure;
13223 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013224 }
13225
Krunal Soni3091bcc2016-06-23 12:28:21 -070013226 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013227 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13228 pRoamProfile))) {
13229 hdd_err("sap-sta conc will fail, can't allow sta");
13230 hdd_conn_set_connection_state(pAdapter,
13231 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013232 status = -ENOMEM;
13233 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013234 }
13235
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013236 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013237 if (!sme_config) {
13238 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013239 hdd_conn_set_connection_state(pAdapter,
13240 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013241 status = -ENOMEM;
13242 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013243 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013244 sme_get_config_param(pHddCtx->hHal, sme_config);
13245 /* These values are not sessionized. So, any change in these SME
13246 * configs on an older or parallel interface will affect the
13247 * cb mode. So, restoring the default INI params before starting
13248 * interfaces such as sta, cli etc.,
13249 */
13250 sme_config->csrConfig.channelBondingMode5GHz =
13251 pHddCtx->config->nChannelBondingMode5GHz;
13252 sme_config->csrConfig.channelBondingMode24GHz =
13253 pHddCtx->config->nChannelBondingMode24GHz;
13254 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013255 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013256 /*
13257 * Change conn_state to connecting before sme_roam_connect(),
13258 * because sme_roam_connect() has a direct path to call
13259 * hdd_sme_roam_callback(), which will change the conn_state
13260 * If direct path, conn_state will be accordingly changed to
13261 * NotConnected or Associated by either
13262 * hdd_association_completion_handler() or
13263 * hdd_dis_connect_handler() in sme_RoamCallback()if
13264 * sme_RomConnect is to be queued,
13265 * Connecting state will remain until it is completed.
13266 *
13267 * If connection state is not changed, connection state will
13268 * remain in eConnectionState_NotConnected state.
13269 * In hdd_association_completion_handler, "hddDisconInProgress"
13270 * is set to true if conn state is
13271 * eConnectionState_NotConnected.
13272 * If "hddDisconInProgress" is set to true then cfg80211 layer
13273 * is not informed of connect result indication which
13274 * is an issue.
13275 */
13276 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013277 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013278 hdd_conn_set_connection_state(pAdapter,
13279 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013280
Komal Seelama89be8d2016-09-29 11:09:26 +053013281 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13282 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013283 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 pAdapter->sessionId, pRoamProfile,
13285 &roamId);
13286
Rajeev Kumard31e1542017-01-13 14:37:42 -080013287 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013288 (QDF_STA_MODE == pAdapter->device_mode ||
13289 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013290 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013291 "qdf_status %d. -> NotConnected",
13292 pAdapter->sessionId, qdf_status);
13293 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294 /* change back to NotAssociated */
13295 hdd_conn_set_connection_state(pAdapter,
13296 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013297 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13298 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013299 }
13300
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013301 /* Reset connect_in_progress */
13302 cds_set_connection_in_progress(false);
13303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304 pRoamProfile->ChannelInfo.ChannelList = NULL;
13305 pRoamProfile->ChannelInfo.numOfChannels = 0;
13306
Nitesh Shah044fd672016-10-13 18:53:25 +053013307 if ((QDF_STA_MODE == pAdapter->device_mode)
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013308 && wma_is_current_hwmode_dbs() &&
13309 !wma_is_hw_dbs_2x2_capable()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013310 cds_get_channel_from_scan_result(pAdapter,
13311 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013312 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013313 if (channel)
13314 cds_checkn_update_hw_mode_single_mac_mode
13315 (channel);
13316 }
13317
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013318 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013319 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013320 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013321 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013322 goto ret_status;
13323
13324conn_failure:
13325 /* Reset connect_in_progress */
13326 cds_set_connection_in_progress(false);
13327
13328ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013329 EXIT();
13330 return status;
13331}
13332
13333/**
13334 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13335 * @pAdapter: Pointer to adapter
13336 * @auth_type: Auth type
13337 *
13338 * This function is used to set the authentication type (OPEN/SHARED).
13339 *
13340 * Return: 0 for success, non-zero for failure
13341 */
13342static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13343 enum nl80211_auth_type auth_type)
13344{
13345 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13346 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13347
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 /*set authentication type */
13349 switch (auth_type) {
13350 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013351 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013352 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13353 break;
13354
13355 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013356 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013357 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13359 break;
13360
13361 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013362 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013363 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13364 break;
13365#ifdef FEATURE_WLAN_ESE
13366 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013367 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013368 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13369 break;
13370#endif
13371
13372 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013373 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013374 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13375 return -EINVAL;
13376 }
13377
13378 pWextState->roamProfile.AuthType.authType[0] =
13379 pHddStaCtx->conn_info.authType;
13380 return 0;
13381}
13382
13383/**
13384 * wlan_hdd_set_akm_suite() - set key management type
13385 * @pAdapter: Pointer to adapter
13386 * @key_mgmt: Key management type
13387 *
13388 * This function is used to set the key mgmt type(PSK/8021x).
13389 *
13390 * Return: 0 for success, non-zero for failure
13391 */
13392static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13393{
13394 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13395
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013396#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13397#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13398 /*set key mgmt type */
13399 switch (key_mgmt) {
13400 case WLAN_AKM_SUITE_PSK:
13401 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013402 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013403 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013404 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13405 break;
13406
13407 case WLAN_AKM_SUITE_8021X_SHA256:
13408 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013409 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013410 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13412 break;
13413#ifdef FEATURE_WLAN_ESE
13414#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13415#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13416 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013417 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13419 break;
13420#endif
13421#ifndef WLAN_AKM_SUITE_OSEN
13422#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13423#endif
13424 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013425 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013426 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13427 break;
13428
13429 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013430 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013431 return -EINVAL;
13432
13433 }
13434 return 0;
13435}
13436
13437/**
13438 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13439 * @pAdapter: Pointer to adapter
13440 * @cipher: Cipher type
13441 * @ucast: Unicast flag
13442 *
13443 * This function is used to set the encryption type
13444 * (NONE/WEP40/WEP104/TKIP/CCMP).
13445 *
13446 * Return: 0 for success, non-zero for failure
13447 */
13448static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13449 u32 cipher, bool ucast)
13450{
13451 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13452 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13453 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013456 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013457 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13458 } else {
13459
13460 /*set encryption method */
13461 switch (cipher) {
13462 case IW_AUTH_CIPHER_NONE:
13463 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13464 break;
13465
13466 case WLAN_CIPHER_SUITE_WEP40:
13467 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13468 break;
13469
13470 case WLAN_CIPHER_SUITE_WEP104:
13471 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13472 break;
13473
13474 case WLAN_CIPHER_SUITE_TKIP:
13475 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13476 break;
13477
13478 case WLAN_CIPHER_SUITE_CCMP:
13479 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13480 break;
13481#ifdef FEATURE_WLAN_WAPI
13482 case WLAN_CIPHER_SUITE_SMS4:
13483 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13484 break;
13485#endif
13486
13487#ifdef FEATURE_WLAN_ESE
13488 case WLAN_CIPHER_SUITE_KRK:
13489 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13490 break;
13491#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13492 case WLAN_CIPHER_SUITE_BTK:
13493 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13494 break;
13495#endif
13496#endif
13497 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013498 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013499 return -EOPNOTSUPP;
13500 }
13501 }
13502
13503 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013504 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13506 pWextState->roamProfile.EncryptionType.numEntries = 1;
13507 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13508 encryptionType;
13509 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013510 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13512 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13513 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13514 encryptionType;
13515 }
13516
13517 return 0;
13518}
13519
13520/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013521 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13522 * @wext_state: Pointer to wext state
13523 * @gen_ie: Pointer to IE data
13524 * @len: length of IE data
13525 *
13526 * Return: 0 for success, non-zero for failure
13527 */
13528static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13529 const uint8_t *gen_ie, uint16_t len)
13530{
13531 uint16_t cur_add_ie_len =
13532 wext_state->assocAddIE.length;
13533
13534 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13535 (wext_state->assocAddIE.length + len)) {
13536 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13537 QDF_ASSERT(0);
13538 return -ENOMEM;
13539 }
13540 memcpy(wext_state->assocAddIE.addIEdata +
13541 cur_add_ie_len, gen_ie, len);
13542 wext_state->assocAddIE.length += len;
13543
13544 wext_state->roamProfile.pAddIEAssoc =
13545 wext_state->assocAddIE.addIEdata;
13546 wext_state->roamProfile.nAddIEAssocLength =
13547 wext_state->assocAddIE.length;
13548 return 0;
13549}
13550
13551/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013552 * wlan_hdd_cfg80211_set_ie() - set IEs
13553 * @pAdapter: Pointer to adapter
13554 * @ie: Pointer ot ie
13555 * @ie: IE length
13556 *
13557 * Return: 0 for success, non-zero for failure
13558 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013559static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013560 size_t ie_len)
13561{
13562 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13563 const uint8_t *genie = ie;
13564 uint16_t remLen = ie_len;
13565#ifdef FEATURE_WLAN_WAPI
13566 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13567 u16 *tmp;
13568 uint16_t akmsuiteCount;
13569 int *akmlist;
13570#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013571 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572
13573 /* clear previous assocAddIE */
13574 pWextState->assocAddIE.length = 0;
13575 pWextState->roamProfile.bWPSAssociation = false;
13576 pWextState->roamProfile.bOSENAssociation = false;
13577
13578 while (remLen >= 2) {
13579 uint16_t eLen = 0;
13580 uint8_t elementId;
13581 elementId = *genie++;
13582 eLen = *genie++;
13583 remLen -= 2;
13584
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013585 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013586
13587 switch (elementId) {
13588 case DOT11F_EID_WPA:
13589 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 -070013590 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013591 return -EINVAL;
13592 } else if (0 ==
13593 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13594 uint16_t curAddIELen =
13595 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013596 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013597
13598 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13599 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013600 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013601 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013602 return -ENOMEM;
13603 }
13604 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13605 memcpy(pWextState->assocAddIE.addIEdata +
13606 curAddIELen, genie - 2, eLen + 2);
13607 pWextState->assocAddIE.length += eLen + 2;
13608
13609 pWextState->roamProfile.bWPSAssociation = true;
13610 pWextState->roamProfile.pAddIEAssoc =
13611 pWextState->assocAddIE.addIEdata;
13612 pWextState->roamProfile.nAddIEAssocLength =
13613 pWextState->assocAddIE.length;
13614 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013615 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013616 memset(pWextState->WPARSNIE, 0,
13617 MAX_WPA_RSN_IE_LEN);
13618 memcpy(pWextState->WPARSNIE, genie - 2,
13619 (eLen + 2));
13620 pWextState->roamProfile.pWPAReqIE =
13621 pWextState->WPARSNIE;
13622 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13623 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13624 P2P_OUI_TYPE_SIZE))) {
13625 uint16_t curAddIELen =
13626 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013627 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013628
13629 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13630 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013631 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013632 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013633 return -ENOMEM;
13634 }
13635 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13636 memcpy(pWextState->assocAddIE.addIEdata +
13637 curAddIELen, genie - 2, eLen + 2);
13638 pWextState->assocAddIE.length += eLen + 2;
13639
13640 pWextState->roamProfile.pAddIEAssoc =
13641 pWextState->assocAddIE.addIEdata;
13642 pWextState->roamProfile.nAddIEAssocLength =
13643 pWextState->assocAddIE.length;
13644 }
13645#ifdef WLAN_FEATURE_WFD
13646 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13647 WFD_OUI_TYPE_SIZE)) &&
13648 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013649 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013650 pAdapter->device_mode)) {
13651 uint16_t curAddIELen =
13652 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013653 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654
13655 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13656 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013657 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013658 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 return -ENOMEM;
13660 }
13661 /* WFD IE is saved to Additional IE ; it should
13662 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013663 * WFD IE
13664 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 memcpy(pWextState->assocAddIE.addIEdata +
13666 curAddIELen, genie - 2, eLen + 2);
13667 pWextState->assocAddIE.length += eLen + 2;
13668
13669 pWextState->roamProfile.pAddIEAssoc =
13670 pWextState->assocAddIE.addIEdata;
13671 pWextState->roamProfile.nAddIEAssocLength =
13672 pWextState->assocAddIE.length;
13673 }
13674#endif
13675 /* Appending HS 2.0 Indication Element in Assiciation Request */
13676 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13677 HS20_OUI_TYPE_SIZE))) {
13678 uint16_t curAddIELen =
13679 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013680 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681
13682 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13683 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013684 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013685 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013686 return -ENOMEM;
13687 }
13688 memcpy(pWextState->assocAddIE.addIEdata +
13689 curAddIELen, genie - 2, eLen + 2);
13690 pWextState->assocAddIE.length += eLen + 2;
13691
13692 pWextState->roamProfile.pAddIEAssoc =
13693 pWextState->assocAddIE.addIEdata;
13694 pWextState->roamProfile.nAddIEAssocLength =
13695 pWextState->assocAddIE.length;
13696 }
13697 /* Appending OSEN Information Element in Assiciation Request */
13698 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13699 OSEN_OUI_TYPE_SIZE))) {
13700 uint16_t curAddIELen =
13701 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013702 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703
13704 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13705 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013706 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013707 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013708 return -ENOMEM;
13709 }
13710 memcpy(pWextState->assocAddIE.addIEdata +
13711 curAddIELen, genie - 2, eLen + 2);
13712 pWextState->assocAddIE.length += eLen + 2;
13713
13714 pWextState->roamProfile.bOSENAssociation = true;
13715 pWextState->roamProfile.pAddIEAssoc =
13716 pWextState->assocAddIE.addIEdata;
13717 pWextState->roamProfile.nAddIEAssocLength =
13718 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013719 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13720 MBO_OUI_TYPE_SIZE))){
13721 hdd_info("Set MBO IE(len %d)", eLen + 2);
13722 status = wlan_hdd_add_assoc_ie(pWextState,
13723 genie - 2, eLen + 2);
13724 if (status)
13725 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 } else {
13727 uint16_t add_ie_len =
13728 pWextState->assocAddIE.length;
13729
13730 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13731
13732 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13733 (pWextState->assocAddIE.length + eLen)) {
13734 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013735 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013736 return -ENOMEM;
13737 }
13738
13739 memcpy(pWextState->assocAddIE.addIEdata +
13740 add_ie_len, genie - 2, eLen + 2);
13741 pWextState->assocAddIE.length += eLen + 2;
13742
13743 pWextState->roamProfile.pAddIEAssoc =
13744 pWextState->assocAddIE.addIEdata;
13745 pWextState->roamProfile.nAddIEAssocLength =
13746 pWextState->assocAddIE.length;
13747 }
13748 break;
13749 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013750 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013751 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13752 memcpy(pWextState->WPARSNIE, genie - 2,
13753 (eLen + 2));
13754 pWextState->roamProfile.pRSNReqIE =
13755 pWextState->WPARSNIE;
13756 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13757 break;
13758 /*
13759 * Appending Extended Capabilities with Interworking bit set
13760 * in Assoc Req.
13761 *
13762 * In assoc req this EXT Cap will only be taken into account if
13763 * interworkingService bit is set to 1. Currently
13764 * driver is only interested in interworkingService capability
13765 * from supplicant. If in future any other EXT Cap info is
13766 * required from supplicat, it needs to be handled while
13767 * sending Assoc Req in LIM.
13768 */
13769 case DOT11F_EID_EXTCAP:
13770 {
13771 uint16_t curAddIELen =
13772 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013773 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013774
13775 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13776 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013777 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013778 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013779 return -ENOMEM;
13780 }
13781 memcpy(pWextState->assocAddIE.addIEdata +
13782 curAddIELen, genie - 2, eLen + 2);
13783 pWextState->assocAddIE.length += eLen + 2;
13784
13785 pWextState->roamProfile.pAddIEAssoc =
13786 pWextState->assocAddIE.addIEdata;
13787 pWextState->roamProfile.nAddIEAssocLength =
13788 pWextState->assocAddIE.length;
13789 break;
13790 }
13791#ifdef FEATURE_WLAN_WAPI
13792 case WLAN_EID_WAPI:
13793 /* Setting WAPI Mode to ON=1 */
13794 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013795 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013796 tmp = (u16 *) ie;
13797 tmp = tmp + 2; /* Skip element Id and Len, Version */
13798 akmsuiteCount = WPA_GET_LE16(tmp);
13799 tmp = tmp + 1;
13800 akmlist = (int *)(tmp);
13801 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13802 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13803 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013804 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013805 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013806 return -EINVAL;
13807 }
13808
13809 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013810 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013811 pAdapter->wapi_info.wapiAuthMode =
13812 WAPI_AUTH_MODE_PSK;
13813 }
13814 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013815 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013816 pAdapter->wapi_info.wapiAuthMode =
13817 WAPI_AUTH_MODE_CERT;
13818 }
13819 break;
13820#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013821 case DOT11F_EID_SUPPOPERATINGCLASSES:
13822 {
13823 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13824 status = wlan_hdd_add_assoc_ie(pWextState,
13825 genie - 2, eLen + 2);
13826 if (status)
13827 return status;
13828 break;
13829 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013831 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013832 /* when Unknown IE is received we break
13833 * and continue to the next IE in the buffer
13834 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835 break;
13836 }
13837 genie += eLen;
13838 remLen -= eLen;
13839 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840 return 0;
13841}
13842
13843/**
13844 * hdd_is_wpaie_present() - check for WPA ie
13845 * @ie: Pointer to ie
13846 * @ie_len: Ie length
13847 *
13848 * Parse the received IE to find the WPA IE
13849 *
13850 * Return: true if wpa ie is found else false
13851 */
13852static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13853{
13854 uint8_t eLen = 0;
13855 uint16_t remLen = ie_len;
13856 uint8_t elementId = 0;
13857
13858 while (remLen >= 2) {
13859 elementId = *ie++;
13860 eLen = *ie++;
13861 remLen -= 2;
13862 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013863 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013864 return false;
13865 }
13866 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13867 /* OUI - 0x00 0X50 0XF2
13868 * WPA Information Element - 0x01
13869 * WPA version - 0x01
13870 */
13871 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13872 return true;
13873 }
13874 ie += eLen;
13875 remLen -= eLen;
13876 }
13877 return false;
13878}
13879
13880/**
13881 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13882 * @pAdapter: Pointer to adapter
13883 * @req: Pointer to security parameters
13884 *
13885 * Return: 0 for success, non-zero for failure
13886 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013887static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13888 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013889{
13890 int status = 0;
13891 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13892 ENTER();
13893
13894 /*set wpa version */
13895 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13896
13897 if (req->crypto.wpa_versions) {
13898 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13899 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13900 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13901 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13902 }
13903 }
13904
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013905 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013906
13907 /*set authentication type */
13908 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13909
13910 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013911 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912 return status;
13913 }
13914
13915 /*set key mgmt type */
13916 if (req->crypto.n_akm_suites) {
13917 status =
13918 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13919 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013920 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013921 return status;
13922 }
13923 }
13924
13925 /*set pairwise cipher type */
13926 if (req->crypto.n_ciphers_pairwise) {
13927 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13928 req->crypto.
13929 ciphers_pairwise[0],
13930 true);
13931 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013932 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013933 return status;
13934 }
13935 } else {
13936 /*Reset previous cipher suite to none */
13937 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13938 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013939 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013940 return status;
13941 }
13942 }
13943
13944 /*set group cipher type */
13945 status =
13946 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13947 false);
13948
13949 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013950 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013951 return status;
13952 }
13953#ifdef WLAN_FEATURE_11W
13954 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13955#endif
13956
13957 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13958 if (req->ie_len) {
13959 status =
13960 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13961 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013962 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013963 return status;
13964 }
13965 }
13966
13967 /*incase of WEP set default key information */
13968 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013969 u8 key_len = req->key_len;
13970 u8 key_idx = req->key_idx;
13971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013972 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13973 || (WLAN_CIPHER_SUITE_WEP104 ==
13974 req->crypto.ciphers_pairwise[0])
13975 ) {
13976 if (IW_AUTH_KEY_MGMT_802_1X
13977 ==
13978 (pWextState->
13979 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013980 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013982 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983
Jeff Johnson68755312017-02-10 11:46:55 -080013984 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13985 && (CSR_MAX_NUM_KEY > key_idx)) {
13986 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13987 key_idx, key_len);
13988 qdf_mem_copy(&pWextState->roamProfile.
13989 Keys.
13990 KeyMaterial[key_idx][0],
13991 req->key, key_len);
13992 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013993 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013994 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013996 }
13997 }
13998 }
13999
14000 return status;
14001}
14002
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014003int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004{
14005 unsigned long rc;
14006 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014007 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014008 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009
14010 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014011 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14012 if (pAdapter->device_mode == QDF_STA_MODE) {
14013 hdd_notice("Stop firmware roaming");
14014 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14015 }
14016 /*
14017 * If firmware has already started roaming process, driver
14018 * needs to defer the processing of this disconnect request.
14019 *
14020 */
14021 if (hdd_is_roaming_in_progress(pAdapter)) {
14022 /*
14023 * Defer the disconnect action until firmware roaming
14024 * result is received. If STA is in connected state after
14025 * that, send the disconnect command to CSR, otherwise
14026 * CSR would have already sent disconnect event to upper
14027 * layer.
14028 */
14029
14030 hdd_err("Roaming in progress, <try disconnect> deferred.");
14031 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14032 pAdapter->cfg80211_disconnect_reason =
14033 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14034 return 0;
14035 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036
Jeff Johnson9edf9572016-10-03 15:24:49 -070014037 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014038 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14039 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14040 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014041 hdd_conn_set_connection_state(pAdapter,
14042 eConnectionState_Disconnecting);
14043 /* Issue disconnect to CSR */
14044 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014045
14046 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14047 pAdapter->sessionId,
14048 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14049 /*
14050 * Wait here instead of returning directly, this will block the
14051 * next connect command and allow processing of the scan for
14052 * ssid and the previous connect command in CSR. Else we might
14053 * hit some race conditions leading to SME and HDD out of sync.
14054 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014055 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014056 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
14057 } else if (0 != status) {
14058 hdd_err("csrRoamDisconnect failure, returned %d",
14059 (int)status);
14060 pHddStaCtx->staDebugState = status;
14061 result = -EINVAL;
14062 goto disconnected;
14063 }
14064
14065 rc = wait_for_completion_timeout(
14066 &pAdapter->disconnect_comp_var,
14067 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014068 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014069 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
14070 pAdapter->sessionId, pHddStaCtx->staDebugState);
14071 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014072 }
14073 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014074 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014075 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014076 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014078 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014079 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014080 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081 }
14082 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014083disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014084 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14085 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014086}
14087
14088/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014089 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14090 * @adapter: Pointer to the HDD adapter
14091 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014092 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014093 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014094 * This function will start reassociation if prev_bssid is set and bssid/
14095 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014096 *
Naveen Rawat07332902016-07-27 09:13:17 -070014097 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014098 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014099#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14100 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014101static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14102 struct cfg80211_connect_params *req,
14103 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014104{
Naveen Rawat07332902016-07-27 09:13:17 -070014105 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014106 const uint8_t *bssid = NULL;
14107 uint16_t channel = 0;
14108
14109 if (req->bssid)
14110 bssid = req->bssid;
14111 else if (req->bssid_hint)
14112 bssid = req->bssid_hint;
14113
14114 if (req->channel)
14115 channel = req->channel->hw_value;
14116 else if (req->channel_hint)
14117 channel = req->channel_hint->hw_value;
14118
14119 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014120 reassoc = true;
14121 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014122 channel, MAC_ADDR_ARRAY(bssid));
14123 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014124 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014125 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014126 }
Naveen Rawat07332902016-07-27 09:13:17 -070014127 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014128}
14129#else
Naveen Rawat07332902016-07-27 09:13:17 -070014130static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14131 struct cfg80211_connect_params *req,
14132 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014133{
Naveen Rawat07332902016-07-27 09:13:17 -070014134 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014135}
14136#endif
14137
14138/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014139 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14140 * @wiphy: Pointer to wiphy
14141 * @dev: Pointer to network device
14142 * @req: Pointer to cfg80211 connect request
14143 *
14144 * This function is used to start the association process
14145 *
14146 * Return: 0 for success, non-zero for failure
14147 */
14148static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14149 struct net_device *ndev,
14150 struct cfg80211_connect_params *req)
14151{
14152 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014153 u16 channel;
14154#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14155 const u8 *bssid_hint = req->bssid_hint;
14156#else
14157 const u8 *bssid_hint = NULL;
14158#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14160 hdd_context_t *pHddCtx;
14161
14162 ENTER();
14163
Anurag Chouhan6d760662016-02-20 16:05:43 +053014164 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014165 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014166 return -EINVAL;
14167 }
14168
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014169 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14170 hdd_err("invalid session id: %d", pAdapter->sessionId);
14171 return -EINVAL;
14172 }
14173
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014174 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014175 TRACE_CODE_HDD_CFG80211_CONNECT,
14176 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014177 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014178 hdd_device_mode_to_string(pAdapter->device_mode),
14179 pAdapter->device_mode);
14180
Krunal Sonib4326f22016-03-10 13:05:51 -080014181 if (pAdapter->device_mode != QDF_STA_MODE &&
14182 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014183 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014184 hdd_device_mode_to_string(pAdapter->device_mode),
14185 pAdapter->device_mode);
14186 return -EINVAL;
14187 }
14188
14189 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14190 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014191 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014192 return -EINVAL;
14193 }
14194
14195 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014196 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014198
Naveen Rawat07332902016-07-27 09:13:17 -070014199 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014200 return status;
14201
Agrawal Ashishf156e942016-08-04 14:54:47 +053014202 /* Try disconnecting if already in connected state */
14203 status = wlan_hdd_try_disconnect(pAdapter);
14204 if (0 > status) {
14205 hdd_err("Failed to disconnect the existing connection");
14206 return -EALREADY;
14207 }
14208
14209 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014211 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014212 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014213 pAdapter->device_mode),
14214 req->channel->hw_value, HW_MODE_20_MHZ)) {
14215 hdd_err("This concurrency combination is not allowed");
14216 return -ECONNREFUSED;
14217 }
14218 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014219 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014220 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014221 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14222 hdd_err("This concurrency combination is not allowed");
14223 return -ECONNREFUSED;
14224 }
14225 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014226
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227 /*initialise security parameters */
14228 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14229
14230 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014231 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 return status;
14233 }
14234
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014235 if (req->channel)
14236 channel = req->channel->hw_value;
14237 else
14238 channel = 0;
14239 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14240 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014241 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014242 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014243 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 return status;
14245 }
14246 EXIT();
14247 return status;
14248}
14249
14250/**
14251 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14252 * @wiphy: Pointer to wiphy
14253 * @dev: Pointer to network device
14254 * @req: Pointer to cfg80211 connect request
14255 *
14256 * Return: 0 for success, non-zero for failure
14257 */
14258static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14259 struct net_device *ndev,
14260 struct cfg80211_connect_params *req)
14261{
14262 int ret;
14263 cds_ssr_protect(__func__);
14264 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14265 cds_ssr_unprotect(__func__);
14266
14267 return ret;
14268}
14269
14270/**
14271 * wlan_hdd_disconnect() - hdd disconnect api
14272 * @pAdapter: Pointer to adapter
14273 * @reason: Disconnect reason code
14274 *
14275 * This function is used to issue a disconnect request to SME
14276 *
14277 * Return: 0 for success, non-zero for failure
14278 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014279static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014280{
14281 int status, result = 0;
14282 unsigned long rc;
14283 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14284 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014285 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014286 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014288 ENTER();
14289
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014290 status = wlan_hdd_validate_context(pHddCtx);
14291
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014292 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014293 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014294 if (pAdapter->device_mode == QDF_STA_MODE) {
14295 hdd_notice("Stop firmware roaming");
14296 status = sme_stop_roaming(hal, pAdapter->sessionId,
14297 eCsrHddIssued);
14298 }
14299 /*
14300 * If firmware has already started roaming process, driver
14301 * needs to defer the processing of this disconnect request.
14302 */
14303 if (hdd_is_roaming_in_progress(pAdapter)) {
14304 /*
14305 * Defer the disconnect action until firmware roaming
14306 * result is received. If STA is in connected state after
14307 * that, send the disconnect command to CSR, otherwise
14308 * CSR would have already sent disconnect event to upper
14309 * layer.
14310 */
14311 hdd_err("Roaming in progress, disconnect command deferred.");
14312 pAdapter->defer_disconnect =
14313 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14314 pAdapter->cfg80211_disconnect_reason = reason;
14315 return 0;
14316 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014318 prev_conn_state = pHddStaCtx->conn_info.connState;
14319
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014320 /* stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014321 hdd_notice("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014322 wlan_hdd_netif_queue_control(pAdapter,
14323 WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014324 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14326 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14327
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014328 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014329
14330 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14331 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014332 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14333 prev_conn_state != eConnectionState_Connecting) {
14334 hdd_notice("status = %d, already disconnected", status);
14335 result = 0;
14336 goto disconnected;
14337 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14338 /*
14339 * Wait here instead of returning directly, this will block the
14340 * next connect command and allow processing of the scan for
14341 * ssid and the previous connect command in CSR. Else we might
14342 * hit some race conditions leading to SME and HDD out of sync.
14343 */
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014344 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014345 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014346 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 (int)status);
14348 pHddStaCtx->staDebugState = status;
14349 result = -EINVAL;
14350 goto disconnected;
14351 }
14352 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14353 msecs_to_jiffies
14354 (WLAN_WAIT_TIME_DISCONNECT));
14355
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014356 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014357 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014358 result = -ETIMEDOUT;
14359 }
14360disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014361 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14362#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14363 /* Sending disconnect event to userspace for kernel version < 3.11
14364 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14365 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014366 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014367 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14368 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014369#endif
14370
14371 return result;
14372}
14373
14374/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014375 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14376 * @reason: ieee80211 reason code.
14377 *
14378 * This utility function helps log string conversion of reason code.
14379 *
14380 * Return: string conversion of reason code, if match found;
14381 * "Unknown" otherwise.
14382 */
14383static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14384{
14385 switch (reason) {
14386 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14387 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14388 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14389 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14390 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14391 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14392 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14393 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14394 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14395 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14396 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14397 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14398 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14399 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14400 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14401 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14402 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14403 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14404 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14405 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14406 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14407 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14408 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14409 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14410 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14411 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14412 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14413 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14414 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14415 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14416 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14417 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14418 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14419 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14420 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14421 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14422 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14423 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14424 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14425 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14426 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14427 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14428 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14429 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14430 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14431 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14432 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14433 default:
14434 return "Unknown";
14435 }
14436}
14437
14438/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014439 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14440 * @wiphy: Pointer to wiphy
14441 * @dev: Pointer to network device
14442 * @reason: Disconnect reason code
14443 *
14444 * This function is used to issue a disconnect request to SME
14445 *
14446 * Return: 0 for success, non-zero for failure
14447 */
14448static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14449 struct net_device *dev, u16 reason)
14450{
14451 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14452 int status;
14453 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14454 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14455#ifdef FEATURE_WLAN_TDLS
14456 uint8_t staIdx;
14457#endif
14458
14459 ENTER();
14460
Anurag Chouhan6d760662016-02-20 16:05:43 +053014461 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014462 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014463 return -EINVAL;
14464 }
14465
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014466 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14467 hdd_err("invalid session id: %d", pAdapter->sessionId);
14468 return -EINVAL;
14469 }
14470
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014471 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014472 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14473 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014474 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475 hdd_device_mode_to_string(pAdapter->device_mode),
14476 pAdapter->device_mode, reason);
14477
14478 status = wlan_hdd_validate_context(pHddCtx);
14479
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014480 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014482
14483 /* Issue disconnect request to SME, if station is in connected state */
14484 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14485 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14486 eCsrRoamDisconnectReason reasonCode =
14487 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14488 hdd_scaninfo_t *pScanInfo;
14489
14490 switch (reason) {
14491 case WLAN_REASON_MIC_FAILURE:
14492 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14493 break;
14494
14495 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14496 case WLAN_REASON_DISASSOC_AP_BUSY:
14497 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14498 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14499 break;
14500
14501 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14502 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14503 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14504 break;
14505
14506 case WLAN_REASON_DEAUTH_LEAVING:
14507 reasonCode =
14508 pHddCtx->config->
14509 gEnableDeauthToDisassocMap ?
14510 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14511 eCSR_DISCONNECT_REASON_DEAUTH;
14512 break;
14513 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14514 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14515 break;
14516 default:
14517 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14518 break;
14519 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014520 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014521 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014522 pScanInfo = &pAdapter->scan_info;
14523 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014524 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014525 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014526 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014527 eCSR_SCAN_ABORT_DEFAULT);
14528 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014529 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014530#ifdef FEATURE_WLAN_TDLS
14531 /* First clean up the tdls peers if any */
14532 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14533 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14534 pAdapter->sessionId)
14535 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14536 uint8_t *mac;
14537 mac =
14538 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014539 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14540 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541 pHddCtx->tdlsConnInfo[staIdx].staId,
14542 pAdapter->sessionId,
14543 MAC_ADDR_ARRAY(mac));
14544 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14545 (pAdapter),
14546 pAdapter->sessionId, mac);
14547 }
14548 }
14549#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014550 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014552 hdd_info("Disconnect request from user space with reason: %s",
14553 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14555 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014556 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014557 return -EINVAL;
14558 }
14559 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014560 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 pHddStaCtx->conn_info.connState);
14562 }
14563
14564 return status;
14565}
14566
14567/**
14568 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14569 * @wiphy: Pointer to wiphy
14570 * @dev: Pointer to network device
14571 * @reason: Disconnect reason code
14572 *
14573 * Return: 0 for success, non-zero for failure
14574 */
14575static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14576 struct net_device *dev, u16 reason)
14577{
14578 int ret;
14579 cds_ssr_protect(__func__);
14580 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14581 cds_ssr_unprotect(__func__);
14582
14583 return ret;
14584}
14585
14586/**
14587 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14588 * @pAdapter: Pointer to adapter
14589 * @param: Pointer to IBSS parameters
14590 *
14591 * This function is used to initialize the security settings in IBSS mode
14592 *
14593 * Return: 0 for success, non-zero for failure
14594 */
14595static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14596 struct cfg80211_ibss_params
14597 *params)
14598{
14599 int status = 0;
14600 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14601 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14602 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14603
14604 ENTER();
14605
14606 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014607 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 pHddStaCtx->ibss_enc_key_installed = 0;
14609
14610 if (params->ie_len && (NULL != params->ie)) {
14611 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14612 params->ie_len, WLAN_EID_RSN)) {
14613 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14614 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14615 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14616 tDot11fIEWPA dot11WPAIE;
14617 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14618 u8 *ie;
14619
14620 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14621 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14622 params->ie_len,
14623 DOT11F_EID_WPA);
14624 if (NULL != ie) {
14625 pWextState->wpaVersion =
14626 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014627 /* Unpack the WPA IE
14628 * Skip past the EID byte and length byte
14629 * and four byte WiFi OUI
14630 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014631 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14632 &ie[2 + 4],
14633 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014634 /* Extract the multicast cipher, the
14635 * encType for unicast cipher for
14636 * wpa-none is none
14637 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014638 encryptionType =
14639 hdd_translate_wpa_to_csr_encryption_type
14640 (dot11WPAIE.multicast_cipher);
14641 }
14642 }
14643
14644 status =
14645 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14646 params->ie_len);
14647
14648 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014649 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014650 return status;
14651 }
14652 }
14653
14654 pWextState->roamProfile.AuthType.authType[0] =
14655 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14656
14657 if (params->privacy) {
14658 /* Security enabled IBSS, At this time there is no information
14659 * available about the security paramters, so initialise the
14660 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14661 * The correct security parameters will be updated later in
14662 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14663 * set inorder enable privacy bit in beacons
14664 */
14665
14666 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14667 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014668 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014669 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14670 pWextState->roamProfile.EncryptionType.numEntries = 1;
14671 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14672 encryptionType;
14673 return status;
14674}
14675
14676/**
14677 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14678 * @wiphy: Pointer to wiphy
14679 * @dev: Pointer to network device
14680 * @param: Pointer to IBSS join parameters
14681 *
14682 * This function is used to create/join an IBSS network
14683 *
14684 * Return: 0 for success, non-zero for failure
14685 */
14686static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14687 struct net_device *dev,
14688 struct cfg80211_ibss_params *params)
14689{
14690 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14691 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14692 tCsrRoamProfile *pRoamProfile;
14693 int status;
14694 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14695 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014696 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014697 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698
14699 ENTER();
14700
Anurag Chouhan6d760662016-02-20 16:05:43 +053014701 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014702 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703 return -EINVAL;
14704 }
14705
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014706 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14707 hdd_err("invalid session id: %d", pAdapter->sessionId);
14708 return -EINVAL;
14709 }
14710
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014711 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14713 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014714 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014715 hdd_device_mode_to_string(pAdapter->device_mode),
14716 pAdapter->device_mode);
14717
14718 status = wlan_hdd_validate_context(pHddCtx);
14719
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014720 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014721 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722
14723 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014724 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014725 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14726 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14727 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14728 int indx;
14729
14730 /* Get channel number */
14731 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014732 params->
14733 chandef.
14734 chan->
14735 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736
14737 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14738 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014739 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014740 return -EOPNOTSUPP;
14741 }
14742
14743 for (indx = 0; indx < numChans; indx++) {
14744 if (channelNum == validChan[indx]) {
14745 break;
14746 }
14747 }
14748 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014749 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750 return -EINVAL;
14751 }
14752 }
14753
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014754 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014755 HW_MODE_20_MHZ)) {
14756 hdd_err("This concurrency combination is not allowed");
14757 return -ECONNREFUSED;
14758 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014759
Krunal Soni3091bcc2016-06-23 12:28:21 -070014760 status = qdf_reset_connection_update();
14761 if (!QDF_IS_STATUS_SUCCESS(status))
14762 hdd_err("ERR: clear event failed");
14763
14764 status = cds_current_connections_update(pAdapter->sessionId,
14765 channelNum,
14766 SIR_UPDATE_REASON_JOIN_IBSS);
14767 if (QDF_STATUS_E_FAILURE == status) {
14768 hdd_err("ERROR: connections update failed!!");
14769 return -EINVAL;
14770 }
14771
14772 if (QDF_STATUS_SUCCESS == status) {
14773 status = qdf_wait_for_connection_update();
14774 if (!QDF_IS_STATUS_SUCCESS(status)) {
14775 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014776 return -EINVAL;
14777 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014778 }
14779
14780 /*Try disconnecting if already in connected state */
14781 status = wlan_hdd_try_disconnect(pAdapter);
14782 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014783 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014784 return -EALREADY;
14785 }
14786
14787 pRoamProfile = &pWextState->roamProfile;
14788
14789 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014790 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014791 return -EINVAL;
14792 }
14793
14794 /* enable selected protection checks in IBSS mode */
14795 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14796
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014797 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14799 pHddCtx->config->
14800 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014801 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014802 }
14803
14804 /* BSSID is provided by upper layers hence no need to AUTO generate */
14805 if (NULL != params->bssid) {
14806 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014807 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014808 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 return -EIO;
14810 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014811 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14813 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014814 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014815 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014816 return -EIO;
14817 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014818 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014819 }
14820 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14821 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14822 pRoamProfile->beaconInterval = params->beacon_interval;
14823 else {
14824 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014825 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014826 params->beacon_interval, pRoamProfile->beaconInterval);
14827 }
14828
14829 /* Set Channel */
14830 if (channelNum) {
14831 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014832 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014833 pRoamProfile->ChannelInfo.numOfChannels = 1;
14834 pHddStaCtx->conn_info.operationChannel = channelNum;
14835 pRoamProfile->ChannelInfo.ChannelList =
14836 &pHddStaCtx->conn_info.operationChannel;
14837 }
14838
14839 /* Initialize security parameters */
14840 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14841 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014842 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014843 return status;
14844 }
14845
14846 /* Issue connect start */
14847 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14848 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014849 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014851 operationChannel,
14852 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853
14854 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014855 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856 return status;
14857 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014858 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014859 return 0;
14860}
14861
14862/**
14863 * wlan_hdd_cfg80211_join_ibss() - join ibss
14864 * @wiphy: Pointer to wiphy
14865 * @dev: Pointer to network device
14866 * @param: Pointer to IBSS join parameters
14867 *
14868 * This function is used to create/join an IBSS network
14869 *
14870 * Return: 0 for success, non-zero for failure
14871 */
14872static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14873 struct net_device *dev,
14874 struct cfg80211_ibss_params *params)
14875{
14876 int ret = 0;
14877
14878 cds_ssr_protect(__func__);
14879 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14880 cds_ssr_unprotect(__func__);
14881
14882 return ret;
14883}
14884
14885/**
14886 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14887 * @wiphy: Pointer to wiphy
14888 * @dev: Pointer to network device
14889 *
14890 * This function is used to leave an IBSS network
14891 *
14892 * Return: 0 for success, non-zero for failure
14893 */
14894static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14895 struct net_device *dev)
14896{
14897 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14898 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14899 tCsrRoamProfile *pRoamProfile;
14900 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14901 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014902 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014903 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014904 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014905
14906 ENTER();
14907
Anurag Chouhan6d760662016-02-20 16:05:43 +053014908 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014909 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014910 return -EINVAL;
14911 }
14912
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014913 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14914 hdd_err("invalid session id: %d", pAdapter->sessionId);
14915 return -EINVAL;
14916 }
14917
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014918 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14920 pAdapter->sessionId,
14921 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14922 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014923 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014924 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014925
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014926 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014927 hdd_device_mode_to_string(pAdapter->device_mode),
14928 pAdapter->device_mode);
14929 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014930 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014931 return -EIO;
14932 }
14933
14934 pRoamProfile = &pWextState->roamProfile;
14935
14936 /* Issue disconnect only if interface type is set to IBSS */
14937 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014938 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014939 return -EINVAL;
14940 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014941 /* Clearing add IE of beacon */
14942 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14943 sizeof(tSirMacAddr));
14944 updateIE.smeSessionId = pAdapter->sessionId;
14945 updateIE.ieBufferlength = 0;
14946 updateIE.pAdditionIEBuffer = NULL;
14947 updateIE.append = true;
14948 updateIE.notify = true;
14949 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14950 &updateIE,
14951 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014952 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014953 }
14954
14955 /* Reset WNI_CFG_PROBE_RSP Flags */
14956 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957
14958 /* Issue Disconnect request */
14959 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14960 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14961 pAdapter->sessionId,
14962 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014963 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014964 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014965 hal_status);
14966 return -EAGAIN;
14967 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014968
14969 /* wait for mc thread to cleanup and then return to upper stack
14970 * so by the time upper layer calls the change interface, we are
14971 * all set to proceed further
14972 */
14973 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14974 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14975 if (!rc) {
14976 hdd_err("Failed to disconnect, timed out");
14977 return -ETIMEDOUT;
14978 }
14979
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014980 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014981 return 0;
14982}
14983
14984/**
14985 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14986 * @wiphy: Pointer to wiphy
14987 * @dev: Pointer to network device
14988 *
14989 * This function is used to leave an IBSS network
14990 *
14991 * Return: 0 for success, non-zero for failure
14992 */
14993static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14994 struct net_device *dev)
14995{
14996 int ret = 0;
14997
14998 cds_ssr_protect(__func__);
14999 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15000 cds_ssr_unprotect(__func__);
15001
15002 return ret;
15003}
15004
15005/**
15006 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15007 * @wiphy: Pointer to wiphy
15008 * @changed: Parameters changed
15009 *
15010 * This function is used to set the phy parameters. RTS Threshold/FRAG
15011 * Threshold/Retry Count etc.
15012 *
15013 * Return: 0 for success, non-zero for failure
15014 */
15015static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15016 u32 changed)
15017{
15018 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15019 tHalHandle hHal = pHddCtx->hHal;
15020 int status;
15021
15022 ENTER();
15023
Anurag Chouhan6d760662016-02-20 16:05:43 +053015024 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015025 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 return -EINVAL;
15027 }
15028
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015029 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15031 NO_SESSION, wiphy->rts_threshold));
15032 status = wlan_hdd_validate_context(pHddCtx);
15033
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015034 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015035 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036
15037 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15038 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15039 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15040
15041 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15042 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015043 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015044 rts_threshold);
15045 return -EINVAL;
15046 }
15047
15048 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15049 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015050 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015051 rts_threshold);
15052 return -EIO;
15053 }
15054
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015055 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015056 }
15057
15058 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15059 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15060 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15061 wiphy->frag_threshold;
15062
15063 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15064 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015065 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015066 frag_threshold);
15067 return -EINVAL;
15068 }
15069
15070 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15071 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015072 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015073 frag_threshold);
15074 return -EIO;
15075 }
15076
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015077 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015078 }
15079
15080 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15081 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15082 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15083 wiphy->retry_short : wiphy->retry_long;
15084
15085 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15086 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015087 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015088 return -EINVAL;
15089 }
15090
15091 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15092 if (0 != sme_cfg_set_int(hHal,
15093 WNI_CFG_LONG_RETRY_LIMIT,
15094 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015095 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 retry_value);
15097 return -EIO;
15098 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015099 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015100 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15101 if (0 != sme_cfg_set_int(hHal,
15102 WNI_CFG_SHORT_RETRY_LIMIT,
15103 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015104 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015105 retry_value);
15106 return -EIO;
15107 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015108 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015109 }
15110 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015111 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015112 return 0;
15113}
15114
15115/**
15116 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15117 * @wiphy: Pointer to wiphy
15118 * @changed: Parameters changed
15119 *
15120 * Return: 0 for success, non-zero for failure
15121 */
15122static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15123{
15124 int ret;
15125
15126 cds_ssr_protect(__func__);
15127 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15128 cds_ssr_unprotect(__func__);
15129
15130 return ret;
15131}
15132
15133/**
15134 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15135 * key
15136 * @wiphy: Pointer to wiphy
15137 * @dev: Pointer to network device
15138 * @key_index: Key index
15139 *
15140 * Return: 0
15141 */
15142static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15143 struct net_device *netdev,
15144 u8 key_index)
15145{
15146 ENTER();
15147 return 0;
15148}
15149
15150/**
15151 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15152 * wlan_hdd_set_default_mgmt_key
15153 * @wiphy: pointer to wiphy
15154 * @netdev: pointer to net_device structure
15155 * @key_index: key index
15156 *
15157 * Return: 0 on success, error number on failure
15158 */
15159static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15160 struct net_device *netdev,
15161 u8 key_index)
15162{
15163 int ret;
15164
15165 cds_ssr_protect(__func__);
15166 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15167 cds_ssr_unprotect(__func__);
15168
15169 return ret;
15170}
15171
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015172/**
15173 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15174 * @wiphy: Pointer to wiphy
15175 * @dev: Pointer to network device
15176 * @params: Pointer to tx queue parameters
15177 *
15178 * Return: 0
15179 */
15180static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15181 struct net_device *dev,
15182 struct ieee80211_txq_params *params)
15183{
15184 ENTER();
15185 return 0;
15186}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187
15188/**
15189 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15190 * @wiphy: pointer to wiphy
15191 * @netdev: pointer to net_device structure
15192 * @params: pointer to ieee80211_txq_params
15193 *
15194 * Return: 0 on success, error number on failure
15195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015196static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15197 struct net_device *dev,
15198 struct ieee80211_txq_params *params)
15199{
15200 int ret;
15201
15202 cds_ssr_protect(__func__);
15203 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15204 cds_ssr_unprotect(__func__);
15205
15206 return ret;
15207}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208
15209/**
15210 * __wlan_hdd_cfg80211_del_station() - delete station v2
15211 * @wiphy: Pointer to wiphy
15212 * @param: Pointer to delete station parameter
15213 *
15214 * Return: 0 for success, non-zero for failure
15215 */
15216static
15217int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15218 struct net_device *dev,
15219 struct tagCsrDelStaParams *pDelStaParams)
15220{
15221 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15222 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015223 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015224 hdd_hostapd_state_t *hapd_state;
15225 int status;
15226 uint8_t staId;
15227 uint8_t *mac;
15228
15229 ENTER();
15230
Anurag Chouhan6d760662016-02-20 16:05:43 +053015231 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015232 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233 return -EINVAL;
15234 }
15235
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015236 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15237 hdd_err("invalid session id: %d", pAdapter->sessionId);
15238 return -EINVAL;
15239 }
15240
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015241 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015242 TRACE_CODE_HDD_CFG80211_DEL_STA,
15243 pAdapter->sessionId, pAdapter->device_mode));
15244
15245 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15246 status = wlan_hdd_validate_context(pHddCtx);
15247
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015248 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015249 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015250
15251 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15252
Krunal Sonib4326f22016-03-10 13:05:51 -080015253 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15254 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255
15256 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15257 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015258 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015259 return 0;
15260 }
15261
Anurag Chouhanc5548422016-02-24 18:33:27 +053015262 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015263 uint16_t i;
15264 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15265 if ((pAdapter->aStaInfo[i].isUsed) &&
15266 (!pAdapter->aStaInfo[i].
15267 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015268 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015269 mac,
15270 pAdapter->aStaInfo[i].
15271 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015272 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015273 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15274 hdd_ipa_wlan_evt(pAdapter,
15275 pAdapter->
15276 aStaInfo[i].
15277 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015278 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015279 mac);
15280 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015281 hdd_notice("Delete STA with MAC::"
15282 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015283 MAC_ADDR_ARRAY(mac));
15284
15285 if (pHddCtx->dev_dfs_cac_status ==
15286 DFS_CAC_IN_PROGRESS)
15287 goto fn_end;
15288
Wei Song2f76f642016-11-18 16:32:53 +080015289 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015290 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015291 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015292 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 hdd_softap_sta_deauth(pAdapter,
15294 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015295 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015296 pAdapter->aStaInfo[i].
15297 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015298 qdf_status =
15299 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015300 &hapd_state->
15301 qdf_sta_disassoc_event,
15302 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015303 if (!QDF_IS_STATUS_SUCCESS(
15304 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015305 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015306 }
15307 }
15308 }
15309 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015310 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015312 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015313 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015314 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015315 hdd_notice("Skip DEL STA as this is not used::"
15316 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015317 MAC_ADDR_ARRAY(mac));
15318 return -ENOENT;
15319 }
15320
15321 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15322 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015323 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 }
15325
15326 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15327 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015328 hdd_notice("Skip DEL STA as deauth is in progress::"
15329 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015330 MAC_ADDR_ARRAY(mac));
15331 return -ENOENT;
15332 }
15333
15334 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15335
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015336 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015337 MAC_ADDR_ARRAY(mac));
15338
15339 /* Case: SAP in ACS selected DFS ch and client connected
15340 * Now Radar detected. Then if random channel is another
15341 * DFS ch then new CAC is initiated and no TX allowed.
15342 * So do not send any mgmt frames as it will timeout
15343 * during CAC.
15344 */
15345
15346 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15347 goto fn_end;
15348
Wei Song2f76f642016-11-18 16:32:53 +080015349 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015350 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15351 (pAdapter), pAdapter->sessionId,
15352 (uint8_t *)&pDelStaParams->peerMacAddr,
15353 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015354 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015355 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015356 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015357 pAdapter->aStaInfo[staId].isDeauthInProgress =
15358 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015359 hdd_notice("STA removal failed for ::"
15360 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015361 MAC_ADDR_ARRAY(mac));
15362 return -ENOENT;
15363 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015364 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015365 &hapd_state->
15366 qdf_sta_disassoc_event,
15367 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015368 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015369 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015370 }
15371 }
15372 }
15373
15374fn_end:
15375 EXIT();
15376 return 0;
15377}
15378
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015379#if defined(USE_CFG80211_DEL_STA_V2)
15380/**
15381 * wlan_hdd_del_station() - delete station wrapper
15382 * @adapter: pointer to the hdd adapter
15383 *
15384 * Return: None
15385 */
15386void wlan_hdd_del_station(hdd_adapter_t *adapter)
15387{
15388 struct station_del_parameters del_sta;
15389 del_sta.mac = NULL;
15390 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15391 del_sta.reason_code = eCsrForcedDeauthSta;
15392
15393 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15394 &del_sta);
15395}
15396#else
15397void wlan_hdd_del_station(hdd_adapter_t *adapter)
15398{
15399 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15400}
15401#endif
15402
15403#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015404/**
15405 * wlan_hdd_cfg80211_del_station() - delete station v2
15406 * @wiphy: Pointer to wiphy
15407 * @param: Pointer to delete station parameter
15408 *
15409 * Return: 0 for success, non-zero for failure
15410 */
15411int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15412 struct net_device *dev,
15413 struct station_del_parameters *param)
15414#else
15415/**
15416 * wlan_hdd_cfg80211_del_station() - delete station
15417 * @wiphy: Pointer to wiphy
15418 * @mac: Pointer to station mac address
15419 *
15420 * Return: 0 for success, non-zero for failure
15421 */
15422#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15423int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15424 struct net_device *dev,
15425 const uint8_t *mac)
15426#else
15427int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15428 struct net_device *dev,
15429 uint8_t *mac)
15430#endif
15431#endif
15432{
15433 int ret;
15434 struct tagCsrDelStaParams delStaParams;
15435
15436 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015437#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015438 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015439 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015440 return -EINVAL;
15441 }
15442 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15443 param->subtype, &delStaParams);
15444#else
15445 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15446 (SIR_MAC_MGMT_DEAUTH >> 4),
15447 &delStaParams);
15448#endif
15449 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15450 cds_ssr_unprotect(__func__);
15451
15452 return ret;
15453}
15454
15455/**
15456 * __wlan_hdd_cfg80211_add_station() - add station
15457 * @wiphy: Pointer to wiphy
15458 * @mac: Pointer to station mac address
15459 * @pmksa: Pointer to add station parameter
15460 *
15461 * Return: 0 for success, non-zero for failure
15462 */
15463static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15464 struct net_device *dev,
15465 const uint8_t *mac,
15466 struct station_parameters *params)
15467{
15468 int status = -EPERM;
15469#ifdef FEATURE_WLAN_TDLS
15470 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15471 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15472 u32 mask, set;
15473
15474 ENTER();
15475
Anurag Chouhan6d760662016-02-20 16:05:43 +053015476 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015477 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015478 return -EINVAL;
15479 }
15480
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015481 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15482 hdd_err("invalid session id: %d", pAdapter->sessionId);
15483 return -EINVAL;
15484 }
15485
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015486 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015487 TRACE_CODE_HDD_CFG80211_ADD_STA,
15488 pAdapter->sessionId, params->listen_interval));
15489
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015490 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015492
15493 mask = params->sta_flags_mask;
15494
15495 set = params->sta_flags_set;
15496
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015497 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015498 MAC_ADDR_ARRAY(mac));
15499
15500 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15501 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15502 status =
15503 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15504 }
15505 }
15506#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015507 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015508 return status;
15509}
15510
15511/**
15512 * wlan_hdd_cfg80211_add_station() - add station
15513 * @wiphy: Pointer to wiphy
15514 * @mac: Pointer to station mac address
15515 * @pmksa: Pointer to add station parameter
15516 *
15517 * Return: 0 for success, non-zero for failure
15518 */
15519#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15520static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15521 struct net_device *dev,
15522 const uint8_t *mac,
15523 struct station_parameters *params)
15524#else
15525static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15526 struct net_device *dev, uint8_t *mac,
15527 struct station_parameters *params)
15528#endif
15529{
15530 int ret;
15531
15532 cds_ssr_protect(__func__);
15533 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15534 cds_ssr_unprotect(__func__);
15535
15536 return ret;
15537}
15538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015539/**
15540 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15541 * @wiphy: Pointer to wiphy
15542 * @dev: Pointer to network device
15543 * @pmksa: Pointer to set pmksa parameter
15544 *
15545 * Return: 0 for success, non-zero for failure
15546 */
15547static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15548 struct net_device *dev,
15549 struct cfg80211_pmksa *pmksa)
15550{
15551 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15552 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15553 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015554 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015555 int status;
15556 tPmkidCacheInfo pmk_id;
15557
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015558 ENTER();
15559
Anurag Chouhan6d760662016-02-20 16:05:43 +053015560 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015561 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562 return -EINVAL;
15563 }
15564
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015565 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15566 hdd_err("invalid session id: %d", pAdapter->sessionId);
15567 return -EINVAL;
15568 }
15569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015570 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015571 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015572 return -EINVAL;
15573 }
15574
15575 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015576 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 pmksa->bssid, pmksa->pmkid);
15578 return -EINVAL;
15579 }
15580
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015581 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015582 MAC_ADDR_ARRAY(pmksa->bssid));
15583
15584 status = wlan_hdd_validate_context(pHddCtx);
15585
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015586 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015587 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015588
15589 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15590
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015591 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15592 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015593
15594 /* Add to the PMKSA ID Cache in CSR */
15595 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15596 &pmk_id, 1, false);
15597
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015598 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015599 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15600 pAdapter->sessionId, result));
15601
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015602 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015603 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015604}
15605
15606/**
15607 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15608 * @wiphy: Pointer to wiphy
15609 * @dev: Pointer to network device
15610 * @pmksa: Pointer to set pmksa parameter
15611 *
15612 * Return: 0 for success, non-zero for failure
15613 */
15614static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15615 struct net_device *dev,
15616 struct cfg80211_pmksa *pmksa)
15617{
15618 int ret;
15619
15620 cds_ssr_protect(__func__);
15621 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15622 cds_ssr_unprotect(__func__);
15623
15624 return ret;
15625}
15626
15627/**
15628 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15629 * @wiphy: Pointer to wiphy
15630 * @dev: Pointer to network device
15631 * @pmksa: Pointer to pmksa parameter
15632 *
15633 * Return: 0 for success, non-zero for failure
15634 */
15635static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15636 struct net_device *dev,
15637 struct cfg80211_pmksa *pmksa)
15638{
15639 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15640 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15641 tHalHandle halHandle;
15642 int status = 0;
15643
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015644 ENTER();
15645
Anurag Chouhan6d760662016-02-20 16:05:43 +053015646 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015647 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015648 return -EINVAL;
15649 }
15650
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015651 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15652 hdd_err("invalid session id: %d", pAdapter->sessionId);
15653 return -EINVAL;
15654 }
15655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015656 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015657 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015658 return -EINVAL;
15659 }
15660
15661 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015662 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015663 return -EINVAL;
15664 }
15665
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015666 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015667 MAC_ADDR_ARRAY(pmksa->bssid));
15668
15669 status = wlan_hdd_validate_context(pHddCtx);
15670
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015671 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015672 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015673
15674 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15675
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015676 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015677 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15678 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015679 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015680 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015681 sme_roam_del_pmkid_from_cache(halHandle,
15682 pAdapter->sessionId, pmksa->bssid,
15683 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015684 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015685 MAC_ADDR_ARRAY(pmksa->bssid));
15686 status = -EINVAL;
15687 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015688 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015689 return status;
15690}
15691
15692/**
15693 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15694 * @wiphy: Pointer to wiphy
15695 * @dev: Pointer to network device
15696 * @pmksa: Pointer to pmksa parameter
15697 *
15698 * Return: 0 for success, non-zero for failure
15699 */
15700static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15701 struct net_device *dev,
15702 struct cfg80211_pmksa *pmksa)
15703{
15704 int ret;
15705
15706 cds_ssr_protect(__func__);
15707 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15708 cds_ssr_unprotect(__func__);
15709
15710 return ret;
15711
15712}
15713
15714/**
15715 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15716 * @wiphy: Pointer to wiphy
15717 * @dev: Pointer to network device
15718 *
15719 * Return: 0 for success, non-zero for failure
15720 */
15721static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15722 struct net_device *dev)
15723{
15724 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15725 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15726 tHalHandle halHandle;
15727 int status = 0;
15728
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015729 ENTER();
15730
Anurag Chouhan6d760662016-02-20 16:05:43 +053015731 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015732 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015733 return -EINVAL;
15734 }
15735
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015736 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15737 hdd_err("invalid session id: %d", pAdapter->sessionId);
15738 return -EINVAL;
15739 }
15740
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015741 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015742
15743 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15744 status = wlan_hdd_validate_context(pHddCtx);
15745
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015746 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015747 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748
15749 /* Retrieve halHandle */
15750 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15751
15752 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015753 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015754 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15755 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015756 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757 status = -EINVAL;
15758 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015759 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015760 return status;
15761}
15762
15763/**
15764 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15765 * @wiphy: Pointer to wiphy
15766 * @dev: Pointer to network device
15767 *
15768 * Return: 0 for success, non-zero for failure
15769 */
15770static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15771 struct net_device *dev)
15772{
15773 int ret;
15774
15775 cds_ssr_protect(__func__);
15776 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15777 cds_ssr_unprotect(__func__);
15778
15779 return ret;
15780}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015782#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015783/**
15784 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15785 * @wiphy: Pointer to wiphy
15786 * @dev: Pointer to network device
15787 * @ftie: Pointer to fast transition ie parameter
15788 *
15789 * Return: 0 for success, non-zero for failure
15790 */
15791static int
15792__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15793 struct net_device *dev,
15794 struct cfg80211_update_ft_ies_params *ftie)
15795{
15796 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15797 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15798 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15799 int status;
15800
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015801 ENTER();
15802
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015803 status = wlan_hdd_validate_context(hdd_ctx);
15804 if (status)
15805 return status;
15806
Anurag Chouhan6d760662016-02-20 16:05:43 +053015807 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015808 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015809 return -EINVAL;
15810 }
15811
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015812 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15813 hdd_err("invalid session id: %d", pAdapter->sessionId);
15814 return -EINVAL;
15815 }
15816
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015817 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015818 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15819 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15820 /* Added for debug on reception of Re-assoc Req. */
15821 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015822 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015823 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015824 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015826 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015828
15829 /* Pass the received FT IEs to SME */
15830 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15831 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015832 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015833 return 0;
15834}
15835
15836/**
15837 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15838 * @wiphy: Pointer to wiphy
15839 * @dev: Pointer to network device
15840 * @ftie: Pointer to fast transition ie parameter
15841 *
15842 * Return: 0 for success, non-zero for failure
15843 */
15844static int
15845wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15846 struct net_device *dev,
15847 struct cfg80211_update_ft_ies_params *ftie)
15848{
15849 int ret;
15850
15851 cds_ssr_protect(__func__);
15852 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15853 cds_ssr_unprotect(__func__);
15854
15855 return ret;
15856}
15857#endif
15858
Mukul Sharma3d36c392017-01-18 18:39:12 +053015859void wlan_hdd_cfg80211_update_replay_counter_callback(
15860 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015862{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015863 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15864 uint8_t temp_replay_counter[8];
15865 int i;
15866 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015867
15868 ENTER();
15869
Mukul Sharma3d36c392017-01-18 18:39:12 +053015870 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015871 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015872 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015873 }
15874
Mukul Sharma3d36c392017-01-18 18:39:12 +053015875 if (!gtk_rsp_param) {
15876 hdd_err("gtk_rsp_param is Null");
15877 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015878 }
15879
Mukul Sharma3d36c392017-01-18 18:39:12 +053015880 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015881 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015882 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883 }
15884
Mukul Sharma3d36c392017-01-18 18:39:12 +053015885 hdd_notice("updated replay counter: %llu from fwr",
15886 gtk_rsp_param->replay_counter);
15887 /* convert little to big endian since supplicant works on big endian */
15888 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15889 for (i = 0; i < 8; i++)
15890 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015891
Mukul Sharma3d36c392017-01-18 18:39:12 +053015892 hdd_notice("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015893 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015894 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015895 gtk_rsp_param->bssid.bytes,
15896 temp_replay_counter, GFP_KERNEL);
15897out:
15898 EXIT();
15899
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015900}
15901
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015902static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015903int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015904 struct net_device *dev,
15905 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015906{
15907 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015908 int result, i;
15909 struct pmo_gtk_req *gtk_req = NULL;
15910 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15911 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015912 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015913
15914 ENTER();
15915
Anurag Chouhan6d760662016-02-20 16:05:43 +053015916 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015917 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015918 result = -EINVAL;
15919 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015920 }
15921
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015922 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15923 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015924 result = -EINVAL;
15925 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015926 }
15927
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015928 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015929 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15930 pAdapter->sessionId, pAdapter->device_mode));
15931
Mukul Sharma3d36c392017-01-18 18:39:12 +053015932 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015933 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015934 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015935
Mukul Sharma3d36c392017-01-18 18:39:12 +053015936 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15937 if (!gtk_req) {
15938 hdd_err("cannot allocate gtk_req");
15939 result = -ENOMEM;
15940 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015941 }
15942
Mukul Sharma3d36c392017-01-18 18:39:12 +053015943 /* convert big to little endian since driver work on little endian */
15944 buf = (uint8_t *)&gtk_req->replay_counter;
15945 for (i = 0; i < 8; i++)
15946 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015947
Mukul Sharma3d36c392017-01-18 18:39:12 +053015948 hdd_notice("current replay counter: %llu in user space",
15949 gtk_req->replay_counter);
15950 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15951 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15952 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15953 if (status != QDF_STATUS_SUCCESS) {
15954 hdd_err("Failed to cache GTK Offload");
15955 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015956 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015957out:
15958 if (gtk_req)
15959 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015960 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015962 return result;
15963}
15964
15965/**
15966 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15967 * @wiphy: Pointer to wiphy
15968 * @dev: Pointer to network device
15969 * @data: Pointer to rekey data
15970 *
15971 * This function is used to offload GTK rekeying job to the firmware.
15972 *
15973 * Return: 0 for success, non-zero for failure
15974 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015975static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015976int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15977 struct net_device *dev,
15978 struct cfg80211_gtk_rekey_data *data)
15979{
15980 int ret;
15981
15982 cds_ssr_protect(__func__);
15983 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15984 cds_ssr_unprotect(__func__);
15985
15986 return ret;
15987}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015988
15989/**
15990 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15991 * @wiphy: Pointer to wiphy
15992 * @dev: Pointer to network device
15993 * @param: Pointer to access control parameter
15994 *
15995 * Return: 0 for success, non-zero for failure
15996 */
15997static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15998 struct net_device *dev,
15999 const struct cfg80211_acl_data *params)
16000{
16001 int i;
16002 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16003 hdd_hostapd_state_t *pHostapdState;
16004 tsap_Config_t *pConfig;
16005 v_CONTEXT_t p_cds_context = NULL;
16006 hdd_context_t *pHddCtx;
16007 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016008 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016009
16010 ENTER();
16011
Anurag Chouhan6d760662016-02-20 16:05:43 +053016012 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016013 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016014 return -EINVAL;
16015 }
16016
16017 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016018 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016019 return -EINVAL;
16020 }
16021
16022 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16023 status = wlan_hdd_validate_context(pHddCtx);
16024
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016025 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016026 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016027
16028 p_cds_context = pHddCtx->pcds_context;
16029 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16030
16031 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016032 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 return -EINVAL;
16034 }
16035
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016036 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016037 params->n_acl_entries);
16038
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016039 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016040 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16041 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016042 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016043 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16044
16045 /* default value */
16046 pConfig->num_accept_mac = 0;
16047 pConfig->num_deny_mac = 0;
16048
16049 /**
16050 * access control policy
16051 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16052 * listed in hostapd.deny file.
16053 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16054 * listed in hostapd.accept file.
16055 */
16056 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16057 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16058 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16059 params->acl_policy) {
16060 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16061 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016062 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016063 params->acl_policy);
16064 return -ENOTSUPP;
16065 }
16066
16067 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16068 pConfig->num_accept_mac = params->n_acl_entries;
16069 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016070 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
16071 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016072 MAC_ADDR_ARRAY(
16073 params->mac_addrs[i].addr));
16074
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016075 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076 params->mac_addrs[i].addr,
16077 sizeof(qcmacaddr));
16078 }
16079 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16080 pConfig->num_deny_mac = params->n_acl_entries;
16081 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016082 hdd_notice("** Add ACL MAC entry %i in BlackList :"
16083 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016084 MAC_ADDR_ARRAY(
16085 params->mac_addrs[i].addr));
16086
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016087 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016088 params->mac_addrs[i].addr,
16089 sizeof(qcmacaddr));
16090 }
16091 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016092 qdf_status = wlansap_set_mac_acl(
16093 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016094 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016095 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016096 return -EINVAL;
16097 }
16098 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016099 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016100 hdd_device_mode_to_string(pAdapter->device_mode),
16101 pAdapter->device_mode);
16102 return -EINVAL;
16103 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016104 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016105 return 0;
16106}
16107
16108/**
16109 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16110 * __wlan_hdd_cfg80211_set_mac_acl
16111 * @wiphy: pointer to wiphy structure
16112 * @dev: pointer to net_device
16113 * @params: pointer to cfg80211_acl_data
16114 *
16115 * Return; 0 on success, error number otherwise
16116 */
16117static int
16118wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16119 struct net_device *dev,
16120 const struct cfg80211_acl_data *params)
16121{
16122 int ret;
16123
16124 cds_ssr_protect(__func__);
16125 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16126 cds_ssr_unprotect(__func__);
16127
16128 return ret;
16129}
16130
16131#ifdef WLAN_NL80211_TESTMODE
16132#ifdef FEATURE_WLAN_LPHB
16133/**
16134 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16135 * @pHddCtx: Pointer to hdd context
16136 * @lphbInd: Pointer to low power heart beat indication parameter
16137 *
16138 * Return: none
16139 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016140static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
16141 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016142{
16143 struct sk_buff *skb;
16144
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016145 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016146
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016147 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016148 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016149
16150 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016151 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152 return;
16153 }
16154
16155 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
16156 wiphy, sizeof(tSirLPHBInd),
16157 GFP_ATOMIC);
16158 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016159 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 return;
16161 }
16162
16163 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016164 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016165 goto nla_put_failure;
16166 }
16167 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016168 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016169 goto nla_put_failure;
16170 }
16171 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016172 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016173 goto nla_put_failure;
16174 }
16175 cfg80211_testmode_event(skb, GFP_ATOMIC);
16176 return;
16177
16178nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016179 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180 kfree_skb(skb);
16181
16182 return;
16183}
16184#endif /* FEATURE_WLAN_LPHB */
16185
16186/**
16187 * __wlan_hdd_cfg80211_testmode() - test mode
16188 * @wiphy: Pointer to wiphy
16189 * @data: Data pointer
16190 * @len: Data length
16191 *
16192 * Return: 0 for success, non-zero for failure
16193 */
16194static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16195 void *data, int len)
16196{
16197 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16198 int err;
16199 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16200
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016201 ENTER();
16202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 err = wlan_hdd_validate_context(pHddCtx);
16204 if (err)
16205 return err;
16206
16207 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16208 len, wlan_hdd_tm_policy);
16209 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016210 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016211 return err;
16212 }
16213
16214 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016215 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016216 return -EINVAL;
16217 }
16218
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016219 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016220 TRACE_CODE_HDD_CFG80211_TESTMODE,
16221 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016222 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16223#ifdef FEATURE_WLAN_LPHB
16224 /* Low Power Heartbeat configuration request */
16225 case WLAN_HDD_TM_CMD_WLAN_HB:
16226 {
16227 int buf_len;
16228 void *buf;
16229 tSirLPHBReq *hb_params = NULL;
16230 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016231 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016232
16233 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016234 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235 return -EINVAL;
16236 }
16237
16238 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16239 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16240
16241 hb_params_temp = (tSirLPHBReq *) buf;
16242 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16243 && (hb_params_temp->params.lphbTcpParamReq.
16244 timePeriodSec == 0))
16245 return -EINVAL;
16246
16247 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016248 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016250 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016251 return -ENOMEM;
16252 }
16253
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016254 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016255 smeStatus =
16256 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16257 hb_params,
16258 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016259 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016260 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016261 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 }
16263 return 0;
16264 }
16265#endif /* FEATURE_WLAN_LPHB */
16266
16267#if defined(QCA_WIFI_FTM)
16268 case WLAN_HDD_TM_CMD_WLAN_FTM:
16269 {
16270 int buf_len;
16271 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016272 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016274 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275 return -EINVAL;
16276 }
16277
16278 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16279 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16280
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016281 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016282
16283 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16284
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016285 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016286 err = -EBUSY;
16287 break;
16288 }
16289#endif
16290
16291 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016292 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016293 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16294 return -EOPNOTSUPP;
16295 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016296 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016297 return err;
16298}
16299
16300/**
16301 * wlan_hdd_cfg80211_testmode() - test mode
16302 * @wiphy: Pointer to wiphy
16303 * @dev: Pointer to network device
16304 * @data: Data pointer
16305 * @len: Data length
16306 *
16307 * Return: 0 for success, non-zero for failure
16308 */
16309static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16310#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16311 struct wireless_dev *wdev,
16312#endif
16313 void *data, int len)
16314{
16315 int ret;
16316
16317 cds_ssr_protect(__func__);
16318 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16319 cds_ssr_unprotect(__func__);
16320
16321 return ret;
16322}
16323
16324#if defined(QCA_WIFI_FTM)
16325/**
16326 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16327 * @buf: Pointer to buffer
16328 * @buf_len: Buffer length
16329 *
16330 * Return: none
16331 */
16332void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16333{
16334 struct sk_buff *skb;
16335 hdd_context_t *hdd_ctx;
16336
16337 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016338 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016339 return;
16340 }
16341
Anurag Chouhan6d760662016-02-20 16:05:43 +053016342 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016344 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016345 return;
16346 }
16347
16348 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16349 buf_len, GFP_KERNEL);
16350 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016351 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016352 return;
16353 }
16354
16355 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16356 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16357 goto nla_put_failure;
16358
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016359 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016360
16361 cfg80211_testmode_event(skb, GFP_KERNEL);
16362 return;
16363
16364nla_put_failure:
16365 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016366 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016367}
16368#endif
16369#endif /* CONFIG_NL80211_TESTMODE */
16370
16371#ifdef QCA_HT_2040_COEX
16372/**
16373 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16374 * @wiphy: Pointer to wiphy
16375 * @dev: Pointer to network device
16376 * @chandef: Pointer to channel definition parameter
16377 *
16378 * Return: 0 for success, non-zero for failure
16379 */
16380static int
16381__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16382 struct net_device *dev,
16383 struct cfg80211_chan_def *chandef)
16384{
16385 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16386 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016387 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016388 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016389 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016390
Anurag Chouhan6d760662016-02-20 16:05:43 +053016391 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016392 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393 return -EINVAL;
16394 }
16395
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016396 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16397 hdd_err("invalid session id: %d", pAdapter->sessionId);
16398 return -EINVAL;
16399 }
16400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016401 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16402 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016403 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016404 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016406 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016407 sme_get_config_param(pHddCtx->hHal, &sme_config);
16408 switch (chandef->width) {
16409 case NL80211_CHAN_WIDTH_20:
16410 if (sme_config.csrConfig.channelBondingMode24GHz !=
16411 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16412 sme_config.csrConfig.channelBondingMode24GHz =
16413 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16414 sme_update_config(pHddCtx->hHal, &sme_config);
16415 cbModeChange = true;
16416 }
16417 break;
16418
16419 case NL80211_CHAN_WIDTH_40:
16420 if (sme_config.csrConfig.channelBondingMode24GHz ==
16421 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16422 if (NL80211_CHAN_HT40MINUS ==
16423 cfg80211_get_chandef_type(chandef))
16424 sme_config.csrConfig.channelBondingMode24GHz =
16425 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16426 else
16427 sme_config.csrConfig.channelBondingMode24GHz =
16428 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16429 sme_update_config(pHddCtx->hHal, &sme_config);
16430 cbModeChange = true;
16431 }
16432 break;
16433
16434 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016435 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016436 return -EINVAL;
16437 }
16438
16439 if (!cbModeChange)
16440 return 0;
16441
Krunal Sonib4326f22016-03-10 13:05:51 -080016442 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016443 return 0;
16444
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016445 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016446 sme_config.csrConfig.channelBondingMode24GHz);
16447
16448 /* Change SAP ht2040 mode */
16449 status = hdd_set_sap_ht2040_mode(pAdapter,
16450 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016451 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016452 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016453 return -EINVAL;
16454 }
16455
16456 return 0;
16457}
16458
16459/**
16460 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16461 * @wiphy: Pointer to wiphy
16462 * @dev: Pointer to network device
16463 * @chandef: Pointer to channel definition parameter
16464 *
16465 * Return: 0 for success, non-zero for failure
16466 */
16467static int
16468wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16469 struct net_device *dev,
16470 struct cfg80211_chan_def *chandef)
16471{
16472 int ret;
16473
16474 cds_ssr_protect(__func__);
16475 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16476 cds_ssr_unprotect(__func__);
16477
16478 return ret;
16479}
16480#endif
16481
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016482#ifdef CHANNEL_SWITCH_SUPPORTED
16483/**
16484 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16485 * channel in SAP/GO
16486 * @wiphy: wiphy pointer
16487 * @dev: dev pointer.
16488 * @csa_params: Change channel params
16489 *
16490 * This function is called to switch channel in SAP/GO
16491 *
16492 * Return: 0 if success else return non zero
16493 */
16494static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16495 struct net_device *dev,
16496 struct cfg80211_csa_settings *csa_params)
16497{
16498 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16499 hdd_context_t *hdd_ctx;
16500 uint8_t channel;
16501 uint16_t freq;
16502 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016503 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016504
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016505 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016506 csa_params->chandef.chan->center_freq);
16507
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016508 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16509 hdd_err("invalid session id: %d", adapter->sessionId);
16510 return -EINVAL;
16511 }
16512
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016513 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16514 ret = wlan_hdd_validate_context(hdd_ctx);
16515
16516 if (0 != ret)
16517 return ret;
16518
Krunal Sonib4326f22016-03-10 13:05:51 -080016519 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16520 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016521 return -ENOTSUPP;
16522
16523 freq = csa_params->chandef.chan->center_freq;
16524 channel = cds_freq_to_chan(freq);
16525
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016526 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16527
16528 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016529 return ret;
16530}
16531
16532/**
16533 * wlan_hdd_cfg80211_channel_switch()- function to switch
16534 * channel in SAP/GO
16535 * @wiphy: wiphy pointer
16536 * @dev: dev pointer.
16537 * @csa_params: Change channel params
16538 *
16539 * This function is called to switch channel in SAP/GO
16540 *
16541 * Return: 0 if success else return non zero
16542 */
16543static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16544 struct net_device *dev,
16545 struct cfg80211_csa_settings *csa_params)
16546{
16547 int ret;
16548
16549 cds_ssr_protect(__func__);
16550 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16551 cds_ssr_unprotect(__func__);
16552 return ret;
16553}
16554#endif
16555
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016556/**
16557 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16558 * translation from NL to policy manager type
16559 * @type: Generic connection mode type defined in NL
16560 *
16561 *
16562 * This function provides the type translation
16563 *
16564 * Return: cds_con_mode enum
16565 */
16566enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16567 enum nl80211_iftype type)
16568{
16569 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16570 switch (type) {
16571 case NL80211_IFTYPE_STATION:
16572 mode = CDS_STA_MODE;
16573 break;
16574 case NL80211_IFTYPE_P2P_CLIENT:
16575 mode = CDS_P2P_CLIENT_MODE;
16576 break;
16577 case NL80211_IFTYPE_P2P_GO:
16578 mode = CDS_P2P_GO_MODE;
16579 break;
16580 case NL80211_IFTYPE_AP:
16581 mode = CDS_SAP_MODE;
16582 break;
16583 case NL80211_IFTYPE_ADHOC:
16584 mode = CDS_IBSS_MODE;
16585 break;
16586 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016587 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016588 type);
16589 }
16590 return mode;
16591}
16592
16593/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016594 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16595 * @wiphy: Handle to struct wiphy to get handle to module context.
16596 * @chandef: Contains information about the capture channel to be set.
16597 *
16598 * This interface is called if and only if monitor mode interface alone is
16599 * active.
16600 *
16601 * Return: 0 success or error code on failure.
16602 */
16603static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16604 struct cfg80211_chan_def *chandef)
16605{
16606 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16607 hdd_adapter_t *adapter;
16608 hdd_station_ctx_t *sta_ctx;
16609 struct hdd_mon_set_ch_info *ch_info;
16610 QDF_STATUS status;
16611 tHalHandle hal_hdl;
16612 struct qdf_mac_addr bssid;
16613 tCsrRoamProfile roam_profile;
16614 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016615 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016616 int ret;
16617 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16618
16619 ENTER();
16620
16621 ret = wlan_hdd_validate_context(hdd_ctx);
16622 if (ret)
16623 return ret;
16624
16625 hal_hdl = hdd_ctx->hHal;
16626
16627 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16628 if (!adapter)
16629 return -EIO;
16630
16631 hdd_info("%s: set monitor mode Channel %d and freq %d",
16632 adapter->dev->name, chan_num, chandef->chan->center_freq);
16633
16634 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16635 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016636 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16637 roam_profile.ChannelInfo.numOfChannels = 1;
16638 roam_profile.phyMode = ch_info->phy_mode;
16639 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016640 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016641
16642 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16643 QDF_MAC_ADDR_SIZE);
16644
16645 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016646 /*
16647 * CDS api expects secondary channel for calculating
16648 * the channel params
16649 */
16650 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16651 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16652 if (chan_num >= 1 && chan_num <= 5)
16653 sec_ch = chan_num + 4;
16654 else if (chan_num >= 6 && chan_num <= 13)
16655 sec_ch = chan_num - 4;
16656 }
16657 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016658 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16659 &roam_profile);
16660 if (status) {
16661 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16662 status);
16663 ret = qdf_status_to_os_return(status);
16664 return ret;
16665 }
16666 EXIT();
16667 return 0;
16668}
16669
16670/**
16671 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16672 * @wiphy: Handle to struct wiphy to get handle to module context.
16673 * @chandef: Contains information about the capture channel to be set.
16674 *
16675 * This interface is called if and only if monitor mode interface alone is
16676 * active.
16677 *
16678 * Return: 0 success or error code on failure.
16679 */
16680static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16681 struct cfg80211_chan_def *chandef)
16682{
16683 int ret;
16684
16685 cds_ssr_protect(__func__);
16686 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16687 cds_ssr_unprotect(__func__);
16688 return ret;
16689}
16690
16691/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016692 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16693 * @adapter: pointer to adapter
16694 *
16695 * Wrapper function to clear link layer stats.
16696 * return - void
16697 */
16698void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16699{
16700 tSirLLStatsClearReq link_layer_stats_clear_req;
16701 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16702
Mukul Sharma491021c2016-09-29 21:39:19 +053016703 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16704 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016705 link_layer_stats_clear_req.stopReq = 0;
16706 link_layer_stats_clear_req.reqId = 1;
16707 link_layer_stats_clear_req.staId = adapter->sessionId;
16708 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16709
16710 return;
16711}
16712
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016713/**
16714 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16715 * @adapter: HDD Adapter
16716 *
16717 * If roaming is in progress and there is a request to
16718 * disconnect the session, then it is deferred. Once
16719 * roaming is complete/aborted, then this routine is
16720 * used to resume the disconnect that was deferred
16721 *
16722 * Return: None
16723 */
16724void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16725{
16726 switch (adapter->defer_disconnect) {
16727 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16728 adapter->defer_disconnect = 0;
16729 wlan_hdd_disconnect(adapter,
16730 adapter->cfg80211_disconnect_reason);
16731 break;
16732 case DEFER_DISCONNECT_TRY_DISCONNECT:
16733 wlan_hdd_try_disconnect(adapter);
16734 adapter->defer_disconnect = 0;
16735 break;
16736 default:
16737 hdd_info("Invalid source to defer:%d. Hence not handling it",
16738 adapter->defer_disconnect);
16739 break;
16740 }
16741}
16742
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016743#define CNT_DIFF(cur, prev) \
16744 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16745#define MAX_COUNT 0xffffffff
16746static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16747 struct scan_chan_info *chan,
16748 struct scan_chan_info *info, uint32_t cmd_flag)
16749{
16750 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16751 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16752 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16753
16754 mutex_lock(&hdd_ctx->chan_info_lock);
16755
16756 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16757 qdf_mem_zero(chan, sizeof(*chan));
16758
16759 chan->freq = info->freq;
16760 chan->noise_floor = info->noise_floor;
16761 chan->clock_freq = info->clock_freq;
16762 chan->cmd_flag = info->cmd_flag;
16763 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16764
16765 chan->rx_clear_count =
16766 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16767
16768 chan->tx_frame_count =
16769 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16770
16771 mutex_unlock(&hdd_ctx->chan_info_lock);
16772
16773}
16774#undef CNT_DIFF
16775#undef MAX_COUNT
16776
16777/**
16778 * wlan_hdd_chan_info_cb() - channel info callback
16779 * @chan_info: struct scan_chan_info
16780 *
16781 * Store channel info into HDD context
16782 *
16783 * Return: None.
16784 */
16785static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16786{
16787 hdd_context_t *hdd_ctx;
16788 struct scan_chan_info *chan;
16789 uint8_t idx;
16790
16791 ENTER();
16792
16793 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16794 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16795 hdd_err("hdd_ctx is invalid");
16796 return;
16797 }
16798
16799 if (!hdd_ctx->chan_info) {
16800 hdd_err("chan_info is NULL");
16801 return;
16802 }
16803
16804 chan = hdd_ctx->chan_info;
16805 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16806 if (chan[idx].freq == info->freq) {
16807 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16808 info->cmd_flag);
16809 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16810 chan[idx].cmd_flag, chan[idx].freq,
16811 chan[idx].noise_floor,
16812 chan[idx].cycle_count, chan[idx].rx_clear_count,
16813 chan[idx].clock_freq, chan[idx].cmd_flag,
16814 chan[idx].tx_frame_count, idx);
16815 if (chan[idx].freq == 0)
16816 break;
16817
16818 }
16819 }
16820
16821 EXIT();
16822}
16823
16824/**
16825 * wlan_hdd_init_chan_info() - init chan info in hdd context
16826 * @hdd_ctx: HDD context pointer
16827 *
16828 * Return: none
16829 */
16830void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16831{
16832 uint8_t num_2g, num_5g, index = 0;
16833
16834 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16835 hdd_info("SNR monitoring is disabled");
16836 return;
16837 }
16838
16839 hdd_ctx->chan_info =
16840 qdf_mem_malloc(sizeof(struct scan_chan_info)
16841 * QDF_MAX_NUM_CHAN);
16842 if (hdd_ctx->chan_info == NULL) {
16843 hdd_err("Failed to malloc for chan info");
16844 return;
16845 }
16846 mutex_init(&hdd_ctx->chan_info_lock);
16847
16848 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16849 for (; index < num_2g; index++) {
16850 hdd_ctx->chan_info[index].freq =
16851 hdd_channels_2_4_ghz[index].center_freq;
16852 }
16853
16854 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16855 for (; (index - num_2g) < num_5g; index++) {
16856 if (cds_is_dsrc_channel(
16857 hdd_channels_5_ghz[index - num_2g].center_freq))
16858 continue;
16859 hdd_ctx->chan_info[index].freq =
16860 hdd_channels_5_ghz[index - num_2g].center_freq;
16861 }
16862 sme_set_chan_info_callback(hdd_ctx->hHal,
16863 &wlan_hdd_chan_info_cb);
16864}
16865
16866/**
16867 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16868 * @hdd_ctx: hdd context pointer
16869 *
16870 * Return: none
16871 */
16872void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16873{
16874 struct scan_chan_info *chan;
16875
16876 chan = hdd_ctx->chan_info;
16877 hdd_ctx->chan_info = NULL;
16878 if (chan)
16879 qdf_mem_free(chan);
16880}
16881
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016882/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016883 * struct cfg80211_ops - cfg80211_ops
16884 *
16885 * @add_virtual_intf: Add virtual interface
16886 * @del_virtual_intf: Delete virtual interface
16887 * @change_virtual_intf: Change virtual interface
16888 * @change_station: Change station
16889 * @add_beacon: Add beacon in sap mode
16890 * @del_beacon: Delete beacon in sap mode
16891 * @set_beacon: Set beacon in sap mode
16892 * @start_ap: Start ap
16893 * @change_beacon: Change beacon
16894 * @stop_ap: Stop ap
16895 * @change_bss: Change bss
16896 * @add_key: Add key
16897 * @get_key: Get key
16898 * @del_key: Delete key
16899 * @set_default_key: Set default key
16900 * @set_channel: Set channel
16901 * @scan: Scan
16902 * @connect: Connect
16903 * @disconnect: Disconnect
16904 * @join_ibss = Join ibss
16905 * @leave_ibss = Leave ibss
16906 * @set_wiphy_params = Set wiphy params
16907 * @set_tx_power = Set tx power
16908 * @get_tx_power = get tx power
16909 * @remain_on_channel = Remain on channel
16910 * @cancel_remain_on_channel = Cancel remain on channel
16911 * @mgmt_tx = Tx management frame
16912 * @mgmt_tx_cancel_wait = Cancel management tx wait
16913 * @set_default_mgmt_key = Set default management key
16914 * @set_txq_params = Set tx queue parameters
16915 * @get_station = Get station
16916 * @set_power_mgmt = Set power management
16917 * @del_station = Delete station
16918 * @add_station = Add station
16919 * @set_pmksa = Set pmksa
16920 * @del_pmksa = Delete pmksa
16921 * @flush_pmksa = Flush pmksa
16922 * @update_ft_ies = Update FT IEs
16923 * @tdls_mgmt = Tdls management
16924 * @tdls_oper = Tdls operation
16925 * @set_rekey_data = Set rekey data
16926 * @sched_scan_start = Scheduled scan start
16927 * @sched_scan_stop = Scheduled scan stop
16928 * @resume = Resume wlan
16929 * @suspend = Suspend wlan
16930 * @set_mac_acl = Set mac acl
16931 * @testmode_cmd = Test mode command
16932 * @set_ap_chanwidth = Set AP channel bandwidth
16933 * @dump_survey = Dump survey
16934 * @key_mgmt_set_pmk = Set pmk key management
16935 */
16936static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16937 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16938 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16939 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16940 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016941 .start_ap = wlan_hdd_cfg80211_start_ap,
16942 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16943 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016944 .change_bss = wlan_hdd_cfg80211_change_bss,
16945 .add_key = wlan_hdd_cfg80211_add_key,
16946 .get_key = wlan_hdd_cfg80211_get_key,
16947 .del_key = wlan_hdd_cfg80211_del_key,
16948 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16949 .scan = wlan_hdd_cfg80211_scan,
16950 .connect = wlan_hdd_cfg80211_connect,
16951 .disconnect = wlan_hdd_cfg80211_disconnect,
16952 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16953 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16954 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16955 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16956 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16957 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16958 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16959 .mgmt_tx = wlan_hdd_mgmt_tx,
16960 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16961 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16962 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016963 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016964 .get_station = wlan_hdd_cfg80211_get_station,
16965 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16966 .del_station = wlan_hdd_cfg80211_del_station,
16967 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016968 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16969 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16970 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016971#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016972 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16973#endif
16974#ifdef FEATURE_WLAN_TDLS
16975 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16976 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16977#endif
16978#ifdef WLAN_FEATURE_GTK_OFFLOAD
16979 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16980#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16981#ifdef FEATURE_WLAN_SCAN_PNO
16982 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16983 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16984#endif /*FEATURE_WLAN_SCAN_PNO */
16985 .resume = wlan_hdd_cfg80211_resume_wlan,
16986 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16987 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16988#ifdef WLAN_NL80211_TESTMODE
16989 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16990#endif
16991#ifdef QCA_HT_2040_COEX
16992 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16993#endif
16994 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016995#ifdef CHANNEL_SWITCH_SUPPORTED
16996 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16997#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016998 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016999#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17000 defined(CFG80211_ABORT_SCAN)
17001 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17002#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017003};