blob: c5e11a27ec3cff745cc41912e4cdc24e44da6e0a [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 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
Jeff Johnson9c50e782016-06-29 15:28:56 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038#include <linux/version.h>
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/etherdevice.h>
43#include <linux/wireless.h>
44#include <wlan_hdd_includes.h>
45#include <net/arp.h>
46#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053047#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include <wlan_hdd_wowl.h>
49#include <ani_global.h>
50#include "sir_params.h"
51#include "dot11f.h"
52#include "wlan_hdd_assoc.h"
53#include "wlan_hdd_wext.h"
54#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070055#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#include "wlan_hdd_p2p.h"
57#include "wlan_hdd_cfg80211.h"
58#include "wlan_hdd_hostapd.h"
59#include "wlan_hdd_softap_tx_rx.h"
60#include "wlan_hdd_main.h"
61#include "wlan_hdd_power.h"
62#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "cds_utils.h"
66#include "cds_sched.h"
67#include "wlan_hdd_scan.h"
68#include <qc_sap_ioctl.h>
69#include "wlan_hdd_tdls.h"
70#include "wlan_hdd_wmm.h"
71#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053072#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073#include "wlan_hdd_misc.h"
74#include "wlan_hdd_nan.h"
75#include <wlan_hdd_ipa.h>
76#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053078#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053079#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Manikandan Mohanb6315dd2016-05-10 16:16:36 -070095#include "ol_txrx.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"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#define g_mode_rates_size (12)
104#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
106 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
107
108/*
109 * Android CTS verifier needs atleast this much wait time (in msec)
110 */
111#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
112
113/*
114 * Refer @tCfgProtection structure for definition of the bit map.
115 * below value is obtained by setting the following bit-fields.
116 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
117 */
118#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
119
120#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700121 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800122 .center_freq = (freq), \
123 .hw_value = (chan), \
124 .flags = (flag), \
125 .max_antenna_gain = 0, \
126 .max_power = 30, \
127}
128
129#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700130 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
139 { \
140 .bitrate = rate, \
141 .hw_value = rate_id, \
142 .flags = flag, \
143 }
144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
146#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147
148#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
Agrawal Ashish65634612016-08-18 13:24:32 +0530150#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
151 mode <= DFS_MODE_DEPRIORITIZE))
152#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
153 || (channel >= 36 && channel <= 184))
154
Peng Xu4d67c8f2015-10-16 16:02:26 -0700155#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530156#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158static const u32 hdd_cipher_suites[] = {
159 WLAN_CIPHER_SUITE_WEP40,
160 WLAN_CIPHER_SUITE_WEP104,
161 WLAN_CIPHER_SUITE_TKIP,
162#ifdef FEATURE_WLAN_ESE
163#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
164#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
165 WLAN_CIPHER_SUITE_BTK,
166 WLAN_CIPHER_SUITE_KRK,
167 WLAN_CIPHER_SUITE_CCMP,
168#else
169 WLAN_CIPHER_SUITE_CCMP,
170#endif
171#ifdef FEATURE_WLAN_WAPI
172 WLAN_CIPHER_SUITE_SMS4,
173#endif
174#ifdef WLAN_FEATURE_11W
175 WLAN_CIPHER_SUITE_AES_CMAC,
176#endif
177};
178
Abhishek Singhf512bf32016-05-04 16:47:46 +0530179static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 HDD2GHZCHAN(2412, 1, 0),
181 HDD2GHZCHAN(2417, 2, 0),
182 HDD2GHZCHAN(2422, 3, 0),
183 HDD2GHZCHAN(2427, 4, 0),
184 HDD2GHZCHAN(2432, 5, 0),
185 HDD2GHZCHAN(2437, 6, 0),
186 HDD2GHZCHAN(2442, 7, 0),
187 HDD2GHZCHAN(2447, 8, 0),
188 HDD2GHZCHAN(2452, 9, 0),
189 HDD2GHZCHAN(2457, 10, 0),
190 HDD2GHZCHAN(2462, 11, 0),
191 HDD2GHZCHAN(2467, 12, 0),
192 HDD2GHZCHAN(2472, 13, 0),
193 HDD2GHZCHAN(2484, 14, 0),
194};
195
Abhishek Singhf512bf32016-05-04 16:47:46 +0530196static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 HDD5GHZCHAN(5180, 36, 0),
198 HDD5GHZCHAN(5200, 40, 0),
199 HDD5GHZCHAN(5220, 44, 0),
200 HDD5GHZCHAN(5240, 48, 0),
201 HDD5GHZCHAN(5260, 52, 0),
202 HDD5GHZCHAN(5280, 56, 0),
203 HDD5GHZCHAN(5300, 60, 0),
204 HDD5GHZCHAN(5320, 64, 0),
205 HDD5GHZCHAN(5500, 100, 0),
206 HDD5GHZCHAN(5520, 104, 0),
207 HDD5GHZCHAN(5540, 108, 0),
208 HDD5GHZCHAN(5560, 112, 0),
209 HDD5GHZCHAN(5580, 116, 0),
210 HDD5GHZCHAN(5600, 120, 0),
211 HDD5GHZCHAN(5620, 124, 0),
212 HDD5GHZCHAN(5640, 128, 0),
213 HDD5GHZCHAN(5660, 132, 0),
214 HDD5GHZCHAN(5680, 136, 0),
215 HDD5GHZCHAN(5700, 140, 0),
216 HDD5GHZCHAN(5720, 144, 0),
217 HDD5GHZCHAN(5745, 149, 0),
218 HDD5GHZCHAN(5765, 153, 0),
219 HDD5GHZCHAN(5785, 157, 0),
220 HDD5GHZCHAN(5805, 161, 0),
221 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 HDD5GHZCHAN(5852, 170, 0),
223 HDD5GHZCHAN(5855, 171, 0),
224 HDD5GHZCHAN(5860, 172, 0),
225 HDD5GHZCHAN(5865, 173, 0),
226 HDD5GHZCHAN(5870, 174, 0),
227 HDD5GHZCHAN(5875, 175, 0),
228 HDD5GHZCHAN(5880, 176, 0),
229 HDD5GHZCHAN(5885, 177, 0),
230 HDD5GHZCHAN(5890, 178, 0),
231 HDD5GHZCHAN(5895, 179, 0),
232 HDD5GHZCHAN(5900, 180, 0),
233 HDD5GHZCHAN(5905, 181, 0),
234 HDD5GHZCHAN(5910, 182, 0),
235 HDD5GHZCHAN(5915, 183, 0),
236 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237};
238
239static struct ieee80211_rate g_mode_rates[] = {
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] = {
255 HDD_G_MODE_RATETAB(60, 0x10, 0),
256 HDD_G_MODE_RATETAB(90, 0x20, 0),
257 HDD_G_MODE_RATETAB(120, 0x40, 0),
258 HDD_G_MODE_RATETAB(180, 0x80, 0),
259 HDD_G_MODE_RATETAB(240, 0x100, 0),
260 HDD_G_MODE_RATETAB(360, 0x200, 0),
261 HDD_G_MODE_RATETAB(480, 0x400, 0),
262 HDD_G_MODE_RATETAB(540, 0x800, 0),
263};
264
265static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530266 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700268 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .bitrates = g_mode_rates,
270 .n_bitrates = g_mode_rates_size,
271 .ht_cap.ht_supported = 1,
272 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
273 | IEEE80211_HT_CAP_GRN_FLD
274 | IEEE80211_HT_CAP_DSSSCCK40
275 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
276 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
277 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
278 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
279 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
280 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
281 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
282};
283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530285 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700287 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .bitrates = a_mode_rates,
289 .n_bitrates = a_mode_rates_size,
290 .ht_cap.ht_supported = 1,
291 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
292 | IEEE80211_HT_CAP_GRN_FLD
293 | IEEE80211_HT_CAP_DSSSCCK40
294 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
295 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
296 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
297 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
298 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
299 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
300 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
301 .vht_cap.vht_supported = 1,
302};
303
304/* This structure contain information what kind of frame are expected in
305 TX/RX direction for each kind of interface */
306static const struct ieee80211_txrx_stypes
307 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
308 [NL80211_IFTYPE_STATION] = {
309 .tx = 0xffff,
310 .rx = BIT(SIR_MAC_MGMT_ACTION) |
311 BIT(SIR_MAC_MGMT_PROBE_REQ),
312 },
313 [NL80211_IFTYPE_AP] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
316 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
317 BIT(SIR_MAC_MGMT_PROBE_REQ) |
318 BIT(SIR_MAC_MGMT_DISASSOC) |
319 BIT(SIR_MAC_MGMT_AUTH) |
320 BIT(SIR_MAC_MGMT_DEAUTH) |
321 BIT(SIR_MAC_MGMT_ACTION),
322 },
323 [NL80211_IFTYPE_ADHOC] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_P2P_CLIENT] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ACTION) |
336 BIT(SIR_MAC_MGMT_PROBE_REQ),
337 },
338 [NL80211_IFTYPE_P2P_GO] = {
339 /* This is also same as for SoftAP */
340 .tx = 0xffff,
341 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
342 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
343 BIT(SIR_MAC_MGMT_PROBE_REQ) |
344 BIT(SIR_MAC_MGMT_DISASSOC) |
345 BIT(SIR_MAC_MGMT_AUTH) |
346 BIT(SIR_MAC_MGMT_DEAUTH) |
347 BIT(SIR_MAC_MGMT_ACTION),
348 },
349};
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351/* Interface limits and combinations registered by the driver */
352
353/* STA ( + STA ) combination */
354static const struct ieee80211_iface_limit
355 wlan_hdd_sta_iface_limit[] = {
356 {
357 .max = 3, /* p2p0 is a STA as well */
358 .types = BIT(NL80211_IFTYPE_STATION),
359 },
360};
361
362/* ADHOC (IBSS) limit */
363static const struct ieee80211_iface_limit
364 wlan_hdd_adhoc_iface_limit[] = {
365 {
366 .max = 1,
367 .types = BIT(NL80211_IFTYPE_STATION),
368 },
369 {
370 .max = 1,
371 .types = BIT(NL80211_IFTYPE_ADHOC),
372 },
373};
374
375/* AP ( + AP ) combination */
376static const struct ieee80211_iface_limit
377 wlan_hdd_ap_iface_limit[] = {
378 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530379 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 .types = BIT(NL80211_IFTYPE_AP),
381 },
382};
383
384/* P2P limit */
385static const struct ieee80211_iface_limit
386 wlan_hdd_p2p_iface_limit[] = {
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO),
394 },
395};
396
397static const struct ieee80211_iface_limit
398 wlan_hdd_sta_ap_iface_limit[] = {
399 {
400 /* We need 1 extra STA interface for OBSS scan when SAP starts
401 * with HT40 in STA+SAP concurrency mode
402 */
403 .max = (1 + SAP_MAX_OBSS_STA_CNT),
404 .types = BIT(NL80211_IFTYPE_STATION),
405 },
406 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530407 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 .types = BIT(NL80211_IFTYPE_AP),
409 },
410};
411
412/* STA + P2P combination */
413static const struct ieee80211_iface_limit
414 wlan_hdd_sta_p2p_iface_limit[] = {
415 {
416 /* One reserved for dedicated P2PDEV usage */
417 .max = 2,
418 .types = BIT(NL80211_IFTYPE_STATION)
419 },
420 {
421 /* Support for two identical (GO + GO or CLI + CLI)
422 * or dissimilar (GO + CLI) P2P interfaces
423 */
424 .max = 2,
425 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
426 },
427};
428
429/* STA + AP + P2PGO combination */
430static const struct ieee80211_iface_limit
431wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
432 /* Support for AP+P2PGO interfaces */
433 {
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_STATION)
436 },
437 {
438 .max = 1,
439 .types = BIT(NL80211_IFTYPE_P2P_GO)
440 },
441 {
442 .max = 1,
443 .types = BIT(NL80211_IFTYPE_AP)
444 }
445};
446
447/* SAP + P2P combination */
448static const struct ieee80211_iface_limit
449wlan_hdd_sap_p2p_iface_limit[] = {
450 {
451 /* 1 dedicated for p2p0 which is a STA type */
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_STATION)
454 },
455 {
456 /* The p2p interface in SAP+P2P can be GO/CLI.
457 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
458 */
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
461 },
462 {
463 /* SAP+GO to support only one SAP interface */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_AP)
466 }
467};
468
469/* P2P + P2P combination */
470static const struct ieee80211_iface_limit
471wlan_hdd_p2p_p2p_iface_limit[] = {
472 {
473 /* 1 dedicated for p2p0 which is a STA type */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_STATION)
476 },
477 {
478 /* The p2p interface in P2P+P2P can be GO/CLI.
479 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
480 */
481 .max = 2,
482 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
483 },
484};
485
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700486static const struct ieee80211_iface_limit
487 wlan_hdd_mon_iface_limit[] = {
488 {
489 .max = 3, /* Monitor interface */
490 .types = BIT(NL80211_IFTYPE_MONITOR),
491 },
492};
493
494static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 wlan_hdd_iface_combination[] = {
496 /* STA */
497 {
498 .limits = wlan_hdd_sta_iface_limit,
499 .num_different_channels = 2,
500 .max_interfaces = 3,
501 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
502 },
503 /* ADHOC */
504 {
505 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700506 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 .max_interfaces = 2,
508 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
509 },
510 /* AP */
511 {
512 .limits = wlan_hdd_ap_iface_limit,
513 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530514 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
516 },
517 /* P2P */
518 {
519 .limits = wlan_hdd_p2p_iface_limit,
520 .num_different_channels = 2,
521 .max_interfaces = 2,
522 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
523 },
524 /* STA + AP */
525 {
526 .limits = wlan_hdd_sta_ap_iface_limit,
527 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530528 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
530 .beacon_int_infra_match = true,
531 },
532 /* STA + P2P */
533 {
534 .limits = wlan_hdd_sta_p2p_iface_limit,
535 .num_different_channels = 2,
536 /* one interface reserved for P2PDEV dedicated usage */
537 .max_interfaces = 4,
538 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
539 .beacon_int_infra_match = true,
540 },
541 /* STA + P2P GO + SAP */
542 {
543 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
544 /* we can allow 3 channels for three different persona
545 * but due to firmware limitation, allow max 2 concrnt channels.
546 */
547 .num_different_channels = 2,
548 /* one interface reserved for P2PDEV dedicated usage */
549 .max_interfaces = 4,
550 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
551 .beacon_int_infra_match = true,
552 },
553 /* SAP + P2P */
554 {
555 .limits = wlan_hdd_sap_p2p_iface_limit,
556 .num_different_channels = 2,
557 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
558 .max_interfaces = 3,
559 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
560 .beacon_int_infra_match = true,
561 },
562 /* P2P + P2P */
563 {
564 .limits = wlan_hdd_p2p_p2p_iface_limit,
565 .num_different_channels = 2,
566 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
567 .max_interfaces = 3,
568 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
569 .beacon_int_infra_match = true,
570 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530571 /* Monitor */
572 {
573 .limits = wlan_hdd_mon_iface_limit,
574 .max_interfaces = 3,
575 .num_different_channels = 2,
576 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
577 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579
580static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530581struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583#ifdef WLAN_NL80211_TESTMODE
584enum wlan_hdd_tm_attr {
585 WLAN_HDD_TM_ATTR_INVALID = 0,
586 WLAN_HDD_TM_ATTR_CMD = 1,
587 WLAN_HDD_TM_ATTR_DATA = 2,
588 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
589 WLAN_HDD_TM_ATTR_TYPE = 4,
590 /* keep last */
591 WLAN_HDD_TM_ATTR_AFTER_LAST,
592 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
593};
594
595enum wlan_hdd_tm_cmd {
596 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
597 WLAN_HDD_TM_CMD_WLAN_HB = 1,
598};
599
600#define WLAN_HDD_TM_DATA_MAX_LEN 5000
601
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530602enum wlan_hdd_vendor_ie_access_policy {
603 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
604 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
605};
606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
608 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
609 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
610 .len = WLAN_HDD_TM_DATA_MAX_LEN},
611};
612#endif /* WLAN_NL80211_TESTMODE */
613
614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
615static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
616 .flags = WIPHY_WOWLAN_MAGIC_PKT,
617 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
618 .pattern_min_len = 1,
619 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
620};
621#endif
622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530624 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
625 * @flags: Pointer to the flags to Add channel switch flag.
626 *
627 * This Function adds Channel Switch support flag, if channel switch is
628 * supported by kernel.
629 * Return: void.
630 */
631#ifdef CHANNEL_SWITCH_SUPPORTED
632static inline void hdd_add_channel_switch_support(uint32_t *flags)
633{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800634 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530635 return;
636}
637#else
638static inline void hdd_add_channel_switch_support(uint32_t *flags)
639{
640 return;
641}
642#endif
643
Manikandan Mohan22b83722015-12-15 15:03:23 -0800644#ifdef FEATURE_WLAN_TDLS
645
646/* TDLS capabilities params */
647#define PARAM_MAX_TDLS_SESSION \
648 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
649#define PARAM_TDLS_FEATURE_SUPPORT \
650 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
651
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530652/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
654 * @wiphy: WIPHY structure pointer
655 * @wdev: Wireless device structure pointer
656 * @data: Pointer to the data received
657 * @data_len: Length of the data received
658 *
659 * This function provides TDLS capabilities
660 *
661 * Return: 0 on success and errno on failure
662 */
663static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
664 struct wireless_dev *wdev,
665 const void *data,
666 int data_len)
667{
668 int status;
669 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
670 struct sk_buff *skb;
671 uint32_t set = 0;
672
Jeff Johnson1f61b612016-02-12 16:28:33 -0800673 ENTER_DEV(wdev->netdev);
674
Anurag Chouhan6d760662016-02-20 16:05:43 +0530675 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 hdd_err("Command not allowed in FTM mode");
677 return -EPERM;
678 }
679
680 status = wlan_hdd_validate_context(hdd_ctx);
681 if (status)
682 return status;
683
684 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
685 NLMSG_HDRLEN);
686 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700687 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 goto fail;
689 }
690
691 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700692 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
694 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 goto fail;
697 }
698 } else {
699 set = set | WIFI_TDLS_SUPPORT;
700 set = set | (hdd_ctx->config->fTDLSExternalControl ?
701 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
702 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
703 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
706 hdd_ctx->max_num_tdls_sta) ||
707 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
708 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700709 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 goto fail;
711 }
712 }
713 return cfg80211_vendor_cmd_reply(skb);
714fail:
715 if (skb)
716 kfree_skb(skb);
717 return -EINVAL;
718}
719
720/**
721 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
722 * @wiphy: WIPHY structure pointer
723 * @wdev: Wireless device structure pointer
724 * @data: Pointer to the data received
725 * @data_len: Length of the data received
726 *
727 * This function provides TDLS capabilities
728 *
729 * Return: 0 on success and errno on failure
730 */
731static int
732wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
733 struct wireless_dev *wdev,
734 const void *data,
735 int data_len)
736{
737 int ret;
738
739 cds_ssr_protect(__func__);
740 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
741 data, data_len);
742 cds_ssr_unprotect(__func__);
743
744 return ret;
745}
746#endif
747
748#ifdef QCA_HT_2040_COEX
749static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
750#endif
751
752#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
753/*
754 * FUNCTION: wlan_hdd_send_avoid_freq_event
755 * This is called when wlan driver needs to send vendor specific
756 * avoid frequency range event to userspace
757 */
758int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
759 tHddAvoidFreqList *pAvoidFreqList)
760{
761 struct sk_buff *vendor_event;
762
763 ENTER();
764
765 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700766 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 return -EINVAL;
768 }
769
770 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 return -EINVAL;
773 }
774
775 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
776 NULL,
777 sizeof(tHddAvoidFreqList),
778 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
779 GFP_KERNEL);
780 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700781 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 return -EINVAL;
783 }
784
785 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
786 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
787
788 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
789
790 EXIT();
791 return 0;
792}
793#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
794
795/* vendor specific events */
796static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
797#ifdef FEATURE_WLAN_CH_AVOID
798 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
799 .vendor_id =
800 QCA_NL80211_VENDOR_ID,
801 .subcmd =
802 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
803 },
804#endif /* FEATURE_WLAN_CH_AVOID */
805
806#ifdef WLAN_FEATURE_NAN
807 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_NAN
812 },
813#endif
814
815#ifdef WLAN_FEATURE_STATS_EXT
816 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
821 },
822#endif /* WLAN_FEATURE_STATS_EXT */
823#ifdef FEATURE_WLAN_EXTSCAN
824 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
829 },
830 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
831 .vendor_id =
832 QCA_NL80211_VENDOR_ID,
833 .subcmd =
834 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
835 },
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
837 .
838 vendor_id
839 =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .
850 subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd
860 =
861 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
862 },
863 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
864 .
865 vendor_id
866 =
867 QCA_NL80211_VENDOR_ID,
868 .subcmd =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
872 .vendor_id =
873 QCA_NL80211_VENDOR_ID,
874 .subcmd =
875 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
876 },
877 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
878 .
879 vendor_id
880 =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .
899 subcmd
900 =
901 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
902 },
903 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
904 .
905 vendor_id
906 =
907 QCA_NL80211_VENDOR_ID,
908 .
909 subcmd =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd
919 =
920 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
921 },
922 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
923 .
924 vendor_id
925 =
926 QCA_NL80211_VENDOR_ID,
927 .
928 subcmd
929 =
930 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
931 },
932 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
933 .vendor_id = QCA_NL80211_VENDOR_ID,
934 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
935 },
936 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
937 .vendor_id = QCA_NL80211_VENDOR_ID,
938 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
939 },
940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
979#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
980 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
981 .vendor_id =
982 QCA_NL80211_VENDOR_ID,
983 .subcmd =
984 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
985 },
986 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
987 .vendor_id = QCA_NL80211_VENDOR_ID,
988 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
989 },
990#ifdef WLAN_FEATURE_ROAM_OFFLOAD
991 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
992 .vendor_id =
993 QCA_NL80211_VENDOR_ID,
994 .subcmd =
995 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
996 },
997#endif
998 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
999 .vendor_id =
1000 QCA_NL80211_VENDOR_ID,
1001 .subcmd =
1002 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1003 },
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1027 },
1028#ifdef FEATURE_WLAN_EXTSCAN
1029 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1030 .vendor_id = QCA_NL80211_VENDOR_ID,
1031 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1032 },
1033 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1034 .vendor_id = QCA_NL80211_VENDOR_ID,
1035 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1036 },
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1044 },
1045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1048 },
1049#endif /* FEATURE_WLAN_EXTSCAN */
1050 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1053 },
1054#ifdef WLAN_FEATURE_MEMDUMP
1055 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1058 },
1059#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001060#ifdef WLAN_FEATURE_TSF
1061 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1064 },
1065#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1069 },
1070 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1073 },
1074 /* OCB events */
1075 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1078 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001079#ifdef FEATURE_LFR_SUBNET_DETECTION
1080 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1083 },
1084#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001085
1086#ifdef WLAN_FEATURE_NAN_DATAPATH
1087 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1090 },
1091#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001092
1093 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1096 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301097 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1098 .vendor_id = QCA_NL80211_VENDOR_ID,
1099 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1100 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101};
1102
1103/**
1104 * __is_driver_dfs_capable() - get driver DFS capability
1105 * @wiphy: pointer to wireless wiphy structure.
1106 * @wdev: pointer to wireless_dev structure.
1107 * @data: Pointer to the data to be passed via vendor interface
1108 * @data_len:Length of the data to be passed
1109 *
1110 * This function is called by userspace to indicate whether or not
1111 * the driver supports DFS offload.
1112 *
1113 * Return: 0 on success, negative errno on failure
1114 */
1115static int __is_driver_dfs_capable(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 const void *data,
1118 int data_len)
1119{
1120 u32 dfs_capability = 0;
1121 struct sk_buff *temp_skbuff;
1122 int ret_val;
1123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1124
Jeff Johnson1f61b612016-02-12 16:28:33 -08001125 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126
1127 ret_val = wlan_hdd_validate_context(hdd_ctx);
1128 if (ret_val)
1129 return ret_val;
1130
Anurag Chouhan6d760662016-02-20 16:05:43 +05301131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 hdd_err("Command not allowed in FTM mode");
1133 return -EPERM;
1134 }
1135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1139 NLMSG_HDRLEN);
1140
1141 if (temp_skbuff != NULL) {
1142 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1143 dfs_capability);
1144 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001145 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 kfree_skb(temp_skbuff);
1147
1148 return ret_val;
1149 }
1150
1151 return cfg80211_vendor_cmd_reply(temp_skbuff);
1152 }
1153
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 return -ENOMEM;
1156}
1157
1158/**
1159 * is_driver_dfs_capable() - get driver DFS capability
1160 * @wiphy: pointer to wireless wiphy structure.
1161 * @wdev: pointer to wireless_dev structure.
1162 * @data: Pointer to the data to be passed via vendor interface
1163 * @data_len:Length of the data to be passed
1164 *
1165 * This function is called by userspace to indicate whether or not
1166 * the driver supports DFS offload. This is an SSR-protected
1167 * wrapper function.
1168 *
1169 * Return: 0 on success, negative errno on failure
1170 */
1171static int is_driver_dfs_capable(struct wiphy *wiphy,
1172 struct wireless_dev *wdev,
1173 const void *data,
1174 int data_len)
1175{
1176 int ret;
1177
1178 cds_ssr_protect(__func__);
1179 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1180 cds_ssr_unprotect(__func__);
1181
1182 return ret;
1183}
1184
1185/**
1186 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1187 *
1188 * @adapter: SAP adapter pointer
1189 *
1190 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1191 * radio. So in case of DFS MCC scenario override current SAP given config
1192 * to follow concurrent SAP DFS config
1193 *
1194 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1197{
1198 hdd_adapter_t *con_sap_adapter;
1199 tsap_Config_t *sap_config, *con_sap_config;
1200 int con_ch;
1201
1202 /*
1203 * Check if AP+AP case, once primary AP chooses a DFS
1204 * channel secondary AP should always follow primary APs channel
1205 */
1206 if (!cds_concurrent_beaconing_sessions_running())
1207 return 0;
1208
1209 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1210 if (!con_sap_adapter)
1211 return 0;
1212
1213 sap_config = &adapter->sessionCtx.ap.sapConfig;
1214 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1215 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1216
1217 if (!CDS_IS_DFS_CH(con_ch))
1218 return 0;
1219
Jeff Johnson020db452016-06-29 14:37:26 -07001220 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001222 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel = con_ch;
1224
1225 if (con_sap_config->acs_cfg.acs_mode == true) {
1226 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1227 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_err("Primary AP channel config error");
1229 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 con_ch, con_sap_config->acs_cfg.pri_ch,
1231 con_sap_config->acs_cfg.ht_sec_ch);
1232 return -EINVAL;
1233 }
1234 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1235 * MCC restriction. So free ch list allocated in do_acs
1236 * func for Sec AP and realloc for Pri AP ch list size
1237 */
1238 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301239 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 &con_sap_config->acs_cfg,
1243 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 sizeof(uint8_t) *
1246 con_sap_config->acs_cfg.ch_list_count);
1247 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001248 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 return -ENOMEM;
1250 }
1251
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 con_sap_config->acs_cfg.ch_list,
1254 con_sap_config->acs_cfg.ch_list_count);
1255
1256 } else {
1257 sap_config->acs_cfg.pri_ch = con_ch;
1258 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1259 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1260 }
1261
1262 return con_ch;
1263}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264
1265/**
1266 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1267 * @sap_cfg: pointer to SAP config struct
1268 *
1269 * This function sets the default ACS start and end channel for the given band
1270 * and also parses the given ACS channel list.
1271 *
1272 * Return: None
1273 */
1274
1275static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1276 bool vht_enabled)
1277{
1278 int i;
1279 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1280 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001281 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1282 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1284 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001285 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1286 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001289 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1290 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001293 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 }
1296
1297 if (ht_enabled)
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1299
1300 if (vht_enabled)
1301 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1302
1303
1304 /* Parse ACS Chan list from hostapd */
1305 if (!sap_cfg->acs_cfg.ch_list)
1306 return;
1307
1308 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1309 sap_cfg->acs_cfg.end_ch =
1310 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1311 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301312 /* avoid channel as start channel */
1313 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1314 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1316 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1317 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1318 }
1319}
1320
1321
1322static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1323
1324/**
1325 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1326 * @adapter: pointer to SAP adapter struct
1327 *
1328 * This function starts the ACS procedure if there are no
1329 * constraints like MBSSID DFS restrictions.
1330 *
1331 * Return: Status of ACS Start procedure
1332 */
1333
1334static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1335{
1336
1337 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1338 tsap_Config_t *sap_config;
1339 tpWLAN_SAPEventCB acs_event_callback;
1340 int status;
1341
1342 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301343 if (hdd_ctx->acs_policy.acs_channel)
1344 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1345 else
1346 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347
1348 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1349 if (status < 0) {
1350 return status;
1351 } else {
1352 if (status > 0) {
1353 /*notify hostapd about channel override */
1354 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1355 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1356 return 0;
1357 }
1358 }
1359 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1360 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001361 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 return -EINVAL;
1363 }
1364
1365 acs_event_callback = hdd_hostapd_sap_event_cb;
1366
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301367 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301368 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001369 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 acs_event_callback, sap_config, adapter->dev);
1373
1374
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379 sap_config->acs_cfg.acs_mode = true;
1380 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1381
1382 return 0;
1383}
1384
1385/**
1386 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1387 * @wiphy: Linux wiphy struct pointer
1388 * @wdev: Linux wireless device struct pointer
1389 * @data: ACS information from hostapd
1390 * @data_len: ACS information length
1391 *
1392 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1393 * and starts ACS procedure.
1394 *
1395 * Return: ACS procedure start status
1396 */
1397
1398static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1399 struct wireless_dev *wdev,
1400 const void *data, int data_len)
1401{
1402 struct net_device *ndev = wdev->netdev;
1403 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1405 tsap_Config_t *sap_config;
1406 struct sk_buff *temp_skbuff;
1407 int status = -EINVAL, i = 0;
1408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1409 bool ht_enabled, ht40_enabled, vht_enabled;
1410 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301411 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412
1413 /* ***Note*** Donot set SME config related to ACS operation here because
1414 * ACS operation is not synchronouse and ACS for Second AP may come when
1415 * ACS operation for first AP is going on. So only do_acs is split to
1416 * seperate start_acs routine. Also SME-PMAC struct that is used to
1417 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1418 * config shall be set only from start_acs.
1419 */
1420
1421 /* nla_policy Policy template. Policy not applied as some attributes are
1422 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1423 *
1424 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1425 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1426 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1427 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1428 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1429 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1430 */
1431
Jeff Johnson1f61b612016-02-12 16:28:33 -08001432 ENTER_DEV(ndev);
1433
Anurag Chouhan6d760662016-02-20 16:05:43 +05301434 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 hdd_err("Command not allowed in FTM mode");
1436 return -EPERM;
1437 }
1438
1439 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001440 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 return -EPERM;
1442 }
1443
1444 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301445 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301447
Naveen Rawat64e477e2016-05-20 10:34:56 -07001448 if (cds_is_sub_20_mhz_enabled()) {
1449 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1450 status = -EINVAL;
1451 goto out;
1452 }
1453
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301455 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456
1457 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1458 NULL);
1459 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 goto out;
1462 }
1463
1464 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001465 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 goto out;
1467 }
1468 sap_config->acs_cfg.hw_mode = nla_get_u8(
1469 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1470
1471 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1472 ht_enabled =
1473 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1474 else
1475 ht_enabled = 0;
1476
1477 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1478 ht40_enabled =
1479 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1480 else
1481 ht40_enabled = 0;
1482
1483 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1484 vht_enabled =
1485 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1486 else
1487 vht_enabled = 0;
1488
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301489 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1490 vht_enabled = 0;
1491 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1492 }
1493
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1495 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1496 } else {
1497 if (ht_enabled && ht40_enabled)
1498 ch_width = 40;
1499 else
1500 ch_width = 20;
1501 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301502
1503 /* this may be possible, when sap_force_11n_for_11ac is set */
1504 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1505 if (ht_enabled && ht40_enabled)
1506 ch_width = 40;
1507 else
1508 ch_width = 20;
1509 }
1510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511 if (ch_width == 80)
1512 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1513 else if (ch_width == 40)
1514 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1515 else
1516 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1517
1518 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1519 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1520 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1521 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1522 * since it contains the frequency values of the channels in
1523 * the channel list.
1524 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1525 * is present
1526 */
1527 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1528 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1529 sap_config->acs_cfg.ch_list_count = nla_len(
1530 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1531 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301532 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 sizeof(uint8_t) *
1534 sap_config->acs_cfg.ch_list_count);
1535 if (sap_config->acs_cfg.ch_list == NULL)
1536 goto out;
1537
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301538 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 sap_config->acs_cfg.ch_list_count);
1540 }
1541 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1542 uint32_t *freq =
1543 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1544 sap_config->acs_cfg.ch_list_count = nla_len(
1545 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1546 sizeof(uint32_t);
1547 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301548 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549 sap_config->acs_cfg.ch_list_count);
1550 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001551 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001552 status = -ENOMEM;
1553 goto out;
1554 }
1555
1556 /* convert frequency to channel */
1557 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1558 sap_config->acs_cfg.ch_list[i] =
1559 ieee80211_frequency_to_channel(freq[i]);
1560 }
1561 }
1562
1563 hdd_debug("get pcl for DO_ACS vendor command");
1564
1565 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001566 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301567 sap_config->acs_cfg.pcl_channels,
1568 &sap_config->acs_cfg.pcl_ch_count,
1569 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301570 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001571 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301574 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1575 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001576 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577 vht_enabled = 1;
1578 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1579 sap_config->acs_cfg.ch_width =
1580 hdd_ctx->config->vhtChannelWidth;
1581 /* No VHT80 in 2.4G so perform ACS accordingly */
1582 if (sap_config->acs_cfg.end_ch <= 14 &&
1583 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1584 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1585 }
1586
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301587 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1588
Jeff Johnson020db452016-06-29 14:37:26 -07001589 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 -08001590 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1591 ch_width, ht_enabled, vht_enabled,
1592 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1593
1594 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001595 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 sap_config->acs_cfg.ch_list_count);
1597 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001598 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599 }
1600 sap_config->acs_cfg.acs_mode = true;
1601 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001602 /* ***Note*** Completion variable usage is not allowed
1603 * here since ACS scan operation may take max 2.2 sec
1604 * for 5G band:
1605 * 9 Active channel X 40 ms active scan time +
1606 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1608 * for this long. So we split up the scanning part.
1609 */
1610 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001611 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612 status = 0;
1613 } else {
1614 status = wlan_hdd_cfg80211_start_acs(adapter);
1615 }
1616
1617out:
1618 if (0 == status) {
1619 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1620 NLMSG_HDRLEN);
1621 if (temp_skbuff != NULL)
1622 return cfg80211_vendor_cmd_reply(temp_skbuff);
1623 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001624 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1626
1627 return status;
1628}
1629
1630 /**
1631 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1632 * @wiphy: Linux wiphy struct pointer
1633 * @wdev: Linux wireless device struct pointer
1634 * @data: ACS information from hostapd
1635 * @data_len: ACS information len
1636 *
1637 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1638 * and starts ACS procedure.
1639 *
1640 * Return: ACS procedure start status
1641 */
1642
1643static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1644 struct wireless_dev *wdev,
1645 const void *data, int data_len)
1646{
1647 int ret;
1648
1649 cds_ssr_protect(__func__);
1650 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1651 cds_ssr_unprotect(__func__);
1652
1653 return ret;
1654}
1655
1656/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001657 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1658 * @adapter: Pointer to adapter struct
1659 *
1660 * This function handle cleanup of what was done in DO_ACS, including free
1661 * memory.
1662 *
1663 * Return: void
1664 */
1665
1666void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1667{
1668 if (adapter == NULL)
1669 return;
1670 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1671 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1672 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1673 }
1674}
1675
1676/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1678 * @work: Linux workqueue struct pointer for ACS work
1679 *
1680 * This function starts the ACS procedure which was marked pending when an ACS
1681 * procedure was in progress for a concurrent SAP interface.
1682 *
1683 * Return: None
1684 */
1685
1686static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1687{
1688 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1689 acs_pending_work.work);
1690 wlan_hdd_cfg80211_start_acs(adapter);
1691}
1692
1693/**
1694 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1695 * @adapter: Pointer to SAP adapter struct
1696 * @pri_channel: SAP ACS procedure selected Primary channel
1697 * @sec_channel: SAP ACS procedure selected secondary channel
1698 *
1699 * This is a callback function from SAP module on ACS procedure is completed.
1700 * This function send the ACS selected channel information to hostapd
1701 *
1702 * Return: None
1703 */
1704
1705void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1706{
1707 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1708 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1709 struct sk_buff *vendor_event;
1710 int ret_val;
1711 hdd_adapter_t *con_sap_adapter;
1712 uint16_t ch_width;
1713
1714 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001715 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1717 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1718 GFP_KERNEL);
1719
1720 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001721 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 return;
1723 }
1724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725 ret_val = nla_put_u8(vendor_event,
1726 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1727 sap_cfg->acs_cfg.pri_ch);
1728 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001729 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 kfree_skb(vendor_event);
1731 return;
1732 }
1733
1734 ret_val = nla_put_u8(vendor_event,
1735 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1736 sap_cfg->acs_cfg.ht_sec_ch);
1737 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001738 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001739 kfree_skb(vendor_event);
1740 return;
1741 }
1742
1743 ret_val = nla_put_u8(vendor_event,
1744 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1745 sap_cfg->acs_cfg.vht_seg0_center_ch);
1746 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001747 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748 kfree_skb(vendor_event);
1749 return;
1750 }
1751
1752 ret_val = nla_put_u8(vendor_event,
1753 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1754 sap_cfg->acs_cfg.vht_seg1_center_ch);
1755 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001756 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001757 kfree_skb(vendor_event);
1758 return;
1759 }
1760
1761 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1762 ch_width = 80;
1763 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1764 ch_width = 40;
1765 else
1766 ch_width = 20;
1767
1768 ret_val = nla_put_u16(vendor_event,
1769 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1770 ch_width);
1771 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001772 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001773 kfree_skb(vendor_event);
1774 return;
1775 }
1776 if (sap_cfg->acs_cfg.pri_ch > 14)
1777 ret_val = nla_put_u8(vendor_event,
1778 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1779 QCA_ACS_MODE_IEEE80211A);
1780 else
1781 ret_val = nla_put_u8(vendor_event,
1782 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1783 QCA_ACS_MODE_IEEE80211G);
1784
1785 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001786 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001787 kfree_skb(vendor_event);
1788 return;
1789 }
1790
Jeff Johnson46b40792016-06-29 14:03:14 -07001791 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 -08001792 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1793 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1794 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1795
1796 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1797 /* ***Note*** As already mentioned Completion variable usage is not
1798 * allowed here since ACS scan operation may take max 2.2 sec.
1799 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1800 * operation.
1801 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1802 * when Primary AP ACS is complete and secondary AP ACS is started here
1803 * immediately, Primary AP start_bss may come inbetween ACS operation
1804 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1805 * delay. This path and below constraint will be removed on sessionizing
1806 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1807 * As per design constraint user space control application must take
1808 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1809 * this code path. Sec AP hostapd should be started after Primary AP
1810 * start beaconing which can be confirmed by getchannel iwpriv command
1811 */
1812
1813 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1814 if (con_sap_adapter &&
1815 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1817 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 /* Lets give 500ms for OBSS + START_BSS to complete */
1819 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1820 msecs_to_jiffies(500));
1821 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1822 }
1823
1824 return;
1825}
1826
1827static int
1828__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1829 struct wireless_dev *wdev,
1830 const void *data,
1831 int data_len)
1832{
1833 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1834 struct sk_buff *skb = NULL;
1835 uint32_t fset = 0;
1836 int ret;
1837
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001838 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301839
Anurag Chouhan6d760662016-02-20 16:05:43 +05301840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001841 hdd_err("Command not allowed in FTM mode");
1842 return -EPERM;
1843 }
1844
1845 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301846 if (ret)
1847 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848
1849 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001850 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851 fset |= WIFI_FEATURE_INFRA;
1852 }
1853 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001854 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001855 fset |= WIFI_FEATURE_INFRA_5G;
1856 }
1857#ifdef WLAN_FEATURE_P2P
1858 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1859 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001860 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 fset |= WIFI_FEATURE_P2P;
1862 }
1863#endif
1864 fset |= WIFI_FEATURE_SOFT_AP;
1865
1866 /* HOTSPOT is a supplicant feature, enable it by default */
1867 fset |= WIFI_FEATURE_HOTSPOT;
1868
1869#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301870 if (pHddCtx->config->extscan_enabled &&
1871 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001872 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1874 }
1875#endif
1876 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001877 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 fset |= WIFI_FEATURE_NAN;
1879 }
1880 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001881 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 fset |= WIFI_FEATURE_D2D_RTT;
1883 fset |= WIFI_FEATURE_D2AP_RTT;
1884 }
1885#ifdef FEATURE_WLAN_SCAN_PNO
1886 if (pHddCtx->config->configPNOScanSupport &&
1887 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001888 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889 fset |= WIFI_FEATURE_PNO;
1890 }
1891#endif
1892 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1893#ifdef FEATURE_WLAN_TDLS
1894 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1895 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001896 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 fset |= WIFI_FEATURE_TDLS;
1898 }
1899 if (sme_is_feature_supported_by_fw(TDLS) &&
1900 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1901 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1904 }
1905#endif
1906#ifdef WLAN_AP_STA_CONCURRENCY
1907 fset |= WIFI_FEATURE_AP_STA;
1908#endif
1909 fset |= WIFI_FEATURE_RSSI_MONITOR;
1910
1911 if (hdd_link_layer_stats_supported())
1912 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1913
1914 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1915 NLMSG_HDRLEN);
1916 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001917 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 return -EINVAL;
1919 }
Jeff Johnson020db452016-06-29 14:37:26 -07001920 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001922 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 goto nla_put_failure;
1924 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301925 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301926 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927nla_put_failure:
1928 kfree_skb(skb);
1929 return -EINVAL;
1930}
1931
1932/**
1933 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1934 * @wiphy: pointer to wireless wiphy structure.
1935 * @wdev: pointer to wireless_dev structure.
1936 * @data: Pointer to the data to be passed via vendor interface
1937 * @data_len:Length of the data to be passed
1938 *
1939 * Return: Return the Success or Failure code.
1940 */
1941static int
1942wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1943 struct wireless_dev *wdev,
1944 const void *data, int data_len)
1945{
1946 int ret = 0;
1947
1948 cds_ssr_protect(__func__);
1949 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1950 data, data_len);
1951 cds_ssr_unprotect(__func__);
1952
1953 return ret;
1954}
1955
1956/**
1957 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1958 * @wiphy: pointer to wireless wiphy structure.
1959 * @wdev: pointer to wireless_dev structure.
1960 * @data: Pointer to the data to be passed via vendor interface
1961 * @data_len:Length of the data to be passed
1962 *
1963 * Set the MAC address that is to be used for scanning.
1964 *
1965 * Return: Return the Success or Failure code.
1966 */
1967static int
1968__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1969 struct wireless_dev *wdev,
1970 const void *data,
1971 int data_len)
1972{
1973 tpSirScanMacOui pReqMsg = NULL;
1974 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1975 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301976 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977 int ret;
1978
Jeff Johnson1f61b612016-02-12 16:28:33 -08001979 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980
Anurag Chouhan6d760662016-02-20 16:05:43 +05301981 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 hdd_err("Command not allowed in FTM mode");
1983 return -EPERM;
1984 }
1985
1986 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301987 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989
1990 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001991 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 return -ENOTSUPP;
1993 }
1994
1995 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1996 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001997 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998 return -EINVAL;
1999 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302000 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002002 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003 return -ENOMEM;
2004 }
2005 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002006 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 goto fail;
2008 }
2009 nla_memcpy(&pReqMsg->oui[0],
2010 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2011 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002012 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013 pReqMsg->oui[1], pReqMsg->oui[2]);
2014 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302015 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002016 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 goto fail;
2018 }
2019 return 0;
2020fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302021 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022 return -EINVAL;
2023}
2024
2025/**
2026 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2027 * @wiphy: pointer to wireless wiphy structure.
2028 * @wdev: pointer to wireless_dev structure.
2029 * @data: Pointer to the data to be passed via vendor interface
2030 * @data_len:Length of the data to be passed
2031 *
2032 * Set the MAC address that is to be used for scanning. This is an
2033 * SSR-protecting wrapper function.
2034 *
2035 * Return: Return the Success or Failure code.
2036 */
2037static int
2038wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2039 struct wireless_dev *wdev,
2040 const void *data,
2041 int data_len)
2042{
2043 int ret;
2044
2045 cds_ssr_protect(__func__);
2046 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2047 data, data_len);
2048 cds_ssr_unprotect(__func__);
2049
2050 return ret;
2051}
2052
2053/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302054 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2055 * @wiphy: pointer phy adapter
2056 * @wdev: pointer to wireless device structure
2057 * @data: pointer to data buffer
2058 * @data_len: length of data
2059 *
2060 * This routine will give concurrency matrix
2061 *
2062 * Return: int status code
2063 */
2064static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2065 struct wireless_dev *wdev,
2066 const void *data,
2067 int data_len)
2068{
2069 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2070 uint8_t i, feature_sets, max_feature_sets;
2071 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2072 struct sk_buff *reply_skb;
2073 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2074 int ret;
2075
2076 ENTER_DEV(wdev->netdev);
2077
2078 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2079 hdd_err("Command not allowed in FTM mode");
2080 return -EPERM;
2081 }
2082
2083 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302084 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302085 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302086
2087 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2088 data, data_len, NULL)) {
2089 hdd_err("Invalid ATTR");
2090 return -EINVAL;
2091 }
2092
2093 /* Parse and fetch max feature set */
2094 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2095 hdd_err("Attr max feature set size failed");
2096 return -EINVAL;
2097 }
2098 max_feature_sets = nla_get_u32(tb[
2099 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2100 hdd_info("Max feature set size: %d", max_feature_sets);
2101
2102 /* Fill feature combination matrix */
2103 feature_sets = 0;
2104 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002105 WIFI_FEATURE_P2P;
2106 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2107 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302108 /* Add more feature combinations here */
2109
2110 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002111 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302112 hdd_info("Feature set matrix");
2113 for (i = 0; i < feature_sets; i++)
2114 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2115
2116 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2117 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2118 if (!reply_skb) {
2119 hdd_err("Feature set matrix: buffer alloc fail");
2120 return -ENOMEM;
2121 }
2122
2123 if (nla_put_u32(reply_skb,
2124 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2125 feature_sets) ||
2126 nla_put(reply_skb,
2127 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2128 sizeof(u32) * feature_sets,
2129 feature_set_matrix)) {
2130 hdd_err("nla put fail");
2131 kfree_skb(reply_skb);
2132 return -EINVAL;
2133 }
2134 return cfg80211_vendor_cmd_reply(reply_skb);
2135}
2136
2137/**
2138 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2139 * @wiphy: pointer to wireless wiphy structure.
2140 * @wdev: pointer to wireless_dev structure.
2141 * @data: Pointer to the data to be passed via vendor interface
2142 * @data_len:Length of the data to be passed
2143 *
2144 * Retrieves the concurrency feature set matrix
2145 *
2146 * Return: 0 on success, negative errno on failure
2147 */
2148static int
2149wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2150 struct wireless_dev *wdev,
2151 const void *data,
2152 int data_len)
2153{
2154 int ret;
2155
2156 cds_ssr_protect(__func__);
2157 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2158 data, data_len);
2159 cds_ssr_unprotect(__func__);
2160
2161 return ret;
2162}
2163
2164/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2166 * @feature_flags: pointer to the byte array of features.
2167 * @feature: Feature to be turned ON in the byte array.
2168 *
2169 * Return: None
2170 *
2171 * This is called to turn ON or SET the feature flag for the requested feature.
2172 **/
2173#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002174static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2175 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176{
2177 uint32_t index;
2178 uint8_t bit_mask;
2179
2180 index = feature / NUM_BITS_IN_BYTE;
2181 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2182 feature_flags[index] |= bit_mask;
2183}
2184
2185/**
2186 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2187 * @wiphy: pointer to wireless wiphy structure.
2188 * @wdev: pointer to wireless_dev structure.
2189 * @data: Pointer to the data to be passed via vendor interface
2190 * @data_len:Length of the data to be passed
2191 *
2192 * This is called when wlan driver needs to send supported feature set to
2193 * supplicant upon a request/query from the supplicant.
2194 *
2195 * Return: Return the Success or Failure code.
2196 **/
2197#define MAX_CONCURRENT_CHAN_ON_24G 2
2198#define MAX_CONCURRENT_CHAN_ON_5G 2
2199static int
2200__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2201 struct wireless_dev *wdev,
2202 const void *data, int data_len)
2203{
2204 struct sk_buff *skb = NULL;
2205 uint32_t dbs_capability = 0;
2206 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302207 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 int ret_val;
2209
2210 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2211 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2212
Jeff Johnson1f61b612016-02-12 16:28:33 -08002213 ENTER_DEV(wdev->netdev);
2214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2216 if (ret_val)
2217 return ret_val;
2218
Anurag Chouhan6d760662016-02-20 16:05:43 +05302219 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220 hdd_err("Command not allowed in FTM mode");
2221 return -EPERM;
2222 }
2223
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002224 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002225 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002226 wlan_hdd_cfg80211_set_feature(feature_flags,
2227 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2228 }
2229
2230 wlan_hdd_cfg80211_set_feature(feature_flags,
2231 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2232 if (wma_is_scan_simultaneous_capable())
2233 wlan_hdd_cfg80211_set_feature(feature_flags,
2234 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002235
2236 if (wma_is_p2p_lo_capable())
2237 wlan_hdd_cfg80211_set_feature(feature_flags,
2238 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2239
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2241 NLMSG_HDRLEN);
2242
2243 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002244 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002245 return -ENOMEM;
2246 }
2247
2248 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2249 sizeof(feature_flags), feature_flags))
2250 goto nla_put_failure;
2251
2252 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302253 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 if (one_by_one_dbs)
2255 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2256
2257 if (two_by_two_dbs)
2258 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2259
2260 if (!one_by_one_dbs && !two_by_two_dbs)
2261 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2262 } else {
2263 hdd_err("wma_get_dbs_hw_mode failed");
2264 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2265 }
2266
2267 hdd_info("dbs_capability is %d", dbs_capability);
2268
2269 if (nla_put_u32(skb,
2270 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2271 MAX_CONCURRENT_CHAN_ON_24G))
2272 goto nla_put_failure;
2273
2274 if (nla_put_u32(skb,
2275 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2276 MAX_CONCURRENT_CHAN_ON_5G))
2277 goto nla_put_failure;
2278
2279 return cfg80211_vendor_cmd_reply(skb);
2280
2281nla_put_failure:
2282 kfree_skb(skb);
2283 return -EINVAL;
2284}
2285
2286/**
2287 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2288 * @wiphy: pointer to wireless wiphy structure.
2289 * @wdev: pointer to wireless_dev structure.
2290 * @data: Pointer to the data to be passed via vendor interface
2291 * @data_len:Length of the data to be passed
2292 *
2293 * This is called when wlan driver needs to send supported feature set to
2294 * supplicant upon a request/query from the supplicant.
2295 *
2296 * Return: Return the Success or Failure code.
2297 */
2298static int
2299wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2300 struct wireless_dev *wdev,
2301 const void *data, int data_len)
2302{
2303 int ret;
2304
2305 cds_ssr_protect(__func__);
2306 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2307 data, data_len);
2308 cds_ssr_unprotect(__func__);
2309
2310 return ret;
2311}
2312
2313
2314/**
2315 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2316 * @wiphy: The wiphy structure
2317 * @wdev: The wireless device
2318 * @data: Data passed by framework
2319 * @data_len: Parameters to be configured passed as data
2320 *
2321 * The roaming related parameters are configured by the framework
2322 * using this interface.
2323 *
2324 * Return: Return either success or failure code.
2325 */
2326static int
2327__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2328 struct wireless_dev *wdev, const void *data, int data_len)
2329{
2330 struct net_device *dev = wdev->netdev;
2331 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2332 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2333 uint8_t session_id;
2334 struct roam_ext_params roam_params;
2335 uint32_t cmd_type, req_id;
2336 struct nlattr *curr_attr;
2337 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2338 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2339 int rem, i;
2340 uint32_t buf_len = 0;
2341 int ret;
2342
Jeff Johnson1f61b612016-02-12 16:28:33 -08002343 ENTER_DEV(dev);
2344
Anurag Chouhan6d760662016-02-20 16:05:43 +05302345 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002346 hdd_err("Command not allowed in FTM mode");
2347 return -EPERM;
2348 }
2349
2350 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302351 if (ret)
2352 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002353
2354 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2355 data, data_len,
2356 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002357 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002358 return -EINVAL;
2359 }
2360 /* Parse and fetch Command Type*/
2361 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002362 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002363 goto fail;
2364 }
2365 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302366 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2368 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002369 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 goto fail;
2371 }
2372 req_id = nla_get_u32(
2373 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002374 hdd_debug("Req Id (%d)", req_id);
2375 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 switch (cmd_type) {
2377 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2378 i = 0;
2379 nla_for_each_nested(curr_attr,
2380 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2381 rem) {
2382 if (nla_parse(tb2,
2383 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2384 nla_data(curr_attr), nla_len(curr_attr),
2385 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002386 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387 goto fail;
2388 }
2389 /* Parse and Fetch allowed SSID list*/
2390 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002391 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 goto fail;
2393 }
2394 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2395 /*
2396 * Upper Layers include a null termination character.
2397 * Check for the actual permissible length of SSID and
2398 * also ensure not to copy the NULL termination
2399 * character to the driver buffer.
2400 */
2401 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2402 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2403 nla_memcpy(
2404 roam_params.ssid_allowed_list[i].ssId,
2405 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2406 buf_len - 1);
2407 roam_params.ssid_allowed_list[i].length =
2408 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002409 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410 roam_params.ssid_allowed_list[i].length,
2411 roam_params.ssid_allowed_list[i].ssId,
2412 roam_params.ssid_allowed_list[i].length);
2413 i++;
2414 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002415 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416 }
2417 }
2418 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002419 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 roam_params.num_ssid_allowed_list);
2421 sme_update_roam_params(pHddCtx->hHal, session_id,
2422 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2423 break;
2424 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2425 /* Parse and fetch 5G Boost Threshold */
2426 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002427 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 goto fail;
2429 }
2430 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2431 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002432 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 roam_params.raise_rssi_thresh_5g);
2434 /* Parse and fetch 5G Penalty Threshold */
2435 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002436 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 goto fail;
2438 }
2439 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2440 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002441 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 roam_params.drop_rssi_thresh_5g);
2443 /* Parse and fetch 5G Boost Factor */
2444 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002445 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 goto fail;
2447 }
2448 roam_params.raise_factor_5g = nla_get_u32(
2449 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002450 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 roam_params.raise_factor_5g);
2452 /* Parse and fetch 5G Penalty factor */
2453 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 goto fail;
2456 }
2457 roam_params.drop_factor_5g = nla_get_u32(
2458 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002459 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 roam_params.drop_factor_5g);
2461 /* Parse and fetch 5G Max Boost */
2462 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 goto fail;
2465 }
2466 roam_params.max_raise_rssi_5g = nla_get_u32(
2467 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002468 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 roam_params.max_raise_rssi_5g);
2470 /* Parse and fetch Rssi Diff */
2471 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002472 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 goto fail;
2474 }
2475 roam_params.rssi_diff = nla_get_s32(
2476 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002477 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 roam_params.rssi_diff);
2479 /* Parse and fetch Alert Rssi Threshold */
2480 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002481 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 goto fail;
2483 }
2484 roam_params.alert_rssi_threshold = nla_get_u32(
2485 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002486 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 roam_params.alert_rssi_threshold);
2488 sme_update_roam_params(pHddCtx->hHal, session_id,
2489 roam_params,
2490 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2491 break;
2492 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2493 /* Parse and fetch Activate Good Rssi Roam */
2494 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002495 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 goto fail;
2497 }
2498 roam_params.good_rssi_roam = nla_get_s32(
2499 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002500 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501 roam_params.good_rssi_roam);
2502 sme_update_roam_params(pHddCtx->hHal, session_id,
2503 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2504 break;
2505 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2506 /* Parse and fetch number of preferred BSSID */
2507 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002508 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 goto fail;
2510 }
2511 roam_params.num_bssid_favored = nla_get_u32(
2512 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002513 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 roam_params.num_bssid_favored);
2515 i = 0;
2516 nla_for_each_nested(curr_attr,
2517 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2518 rem) {
2519 if (nla_parse(tb2,
2520 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2521 nla_data(curr_attr), nla_len(curr_attr),
2522 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002523 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 goto fail;
2525 }
2526 /* Parse and fetch MAC address */
2527 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002528 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529 goto fail;
2530 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002531 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302533 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002534 hdd_debug(MAC_ADDRESS_STR,
2535 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 /* Parse and fetch preference factor*/
2537 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002538 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 goto fail;
2540 }
2541 roam_params.bssid_favored_factor[i] = nla_get_u32(
2542 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002543 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 roam_params.bssid_favored_factor[i]);
2545 i++;
2546 }
2547 sme_update_roam_params(pHddCtx->hHal, session_id,
2548 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2549 break;
2550 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2551 /* Parse and fetch number of blacklist BSSID */
2552 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002553 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 goto fail;
2555 }
2556 roam_params.num_bssid_avoid_list = nla_get_u32(
2557 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002558 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 roam_params.num_bssid_avoid_list);
2560 i = 0;
2561 nla_for_each_nested(curr_attr,
2562 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2563 rem) {
2564 if (nla_parse(tb2,
2565 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2566 nla_data(curr_attr), nla_len(curr_attr),
2567 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002568 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 goto fail;
2570 }
2571 /* Parse and fetch MAC address */
2572 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002573 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 goto fail;
2575 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002576 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302578 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002579 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002581 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 i++;
2583 }
2584 sme_update_roam_params(pHddCtx->hHal, session_id,
2585 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2586 break;
2587 }
2588 return 0;
2589fail:
2590 return -EINVAL;
2591}
2592
2593/**
2594 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2595 * @wiphy: pointer to wireless wiphy structure.
2596 * @wdev: pointer to wireless_dev structure.
2597 * @data: Pointer to the data to be passed via vendor interface
2598 * @data_len:Length of the data to be passed
2599 *
2600 * Return: Return the Success or Failure code.
2601 */
2602static int
2603wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2604 struct wireless_dev *wdev,
2605 const void *data,
2606 int data_len)
2607{
2608 int ret;
2609
2610 cds_ssr_protect(__func__);
2611 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2612 data, data_len);
2613 cds_ssr_unprotect(__func__);
2614
2615 return ret;
2616}
2617
2618static const struct nla_policy
2619wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2620 +1] = {
2621 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2622};
2623
2624/**
2625 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2626 * @hdd_ctx: HDD context
2627 * @device_mode: device mode
2628 * Return: bool
2629 */
2630static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002631 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002632{
2633 hdd_adapter_t *adapter;
2634 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2635 hdd_ap_ctx_t *ap_ctx;
2636 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302637 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302639 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002640 &adapter_node);
2641
2642 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302643 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644 adapter = adapter_node->pAdapter;
2645
2646 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002647 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002648 ap_ctx =
2649 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2650
2651 /*
2652 * if there is SAP already running on DFS channel,
2653 * do not disable scan on dfs channels. Note that
2654 * with SAP on DFS, there cannot be conurrency on
2655 * single radio. But then we can have multiple
2656 * radios !!
2657 */
2658 if (CHANNEL_STATE_DFS ==
2659 cds_get_channel_state(
2660 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002661 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002662 return true;
2663 }
2664 }
2665
2666 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002667 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 sta_ctx =
2669 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2670
2671 /*
2672 * if STA is already connected on DFS channel,
2673 * do not disable scan on dfs channels
2674 */
2675 if (hdd_conn_is_connected(sta_ctx) &&
2676 (CHANNEL_STATE_DFS ==
2677 cds_get_channel_state(
2678 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002679 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 return true;
2681 }
2682 }
2683
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302684 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 adapter_node,
2686 &next);
2687 adapter_node = next;
2688 }
2689
2690 return false;
2691}
2692
2693/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002694 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2695 * @hdd_ctx: HDD context within host driver
2696 * @adapter: Adapter pointer
2697 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2698 *
2699 * Loops through devices to see who is operating on DFS channels
2700 * and then disables/enables DFS channels by calling SME API.
2701 * Fails the disable request if any device is active on a DFS channel.
2702 *
2703 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002705
2706int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2707 hdd_adapter_t *adapter,
2708 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302711 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002712 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713
2714 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2715 if (no_dfs_flag) {
2716 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002717 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718
2719 if (true == status)
2720 return -EOPNOTSUPP;
2721
2722 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002723 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724
2725 if (true == status)
2726 return -EOPNOTSUPP;
2727 }
2728
2729 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2730
2731 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2732
2733 /*
2734 * call the SME API to tunnel down the new channel list
2735 * to the firmware
2736 */
2737 status = sme_handle_dfs_chan_scan(
2738 h_hal, hdd_ctx->config->enableDFSChnlScan);
2739
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302740 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002741 ret_val = 0;
2742
2743 /*
2744 * Clear the SME scan cache also. Note that the
2745 * clearing of scan results is independent of session;
2746 * so no need to iterate over
2747 * all sessions
2748 */
2749 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302750 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002751 ret_val = -EPERM;
2752 }
2753
2754 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002755 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 ret_val = 0;
2757 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002758 return ret_val;
2759}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002761/**
2762 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2763 * @wiphy: corestack handler
2764 * @wdev: wireless device
2765 * @data: data
2766 * @data_len: data length
2767 * Return: success(0) or reason code for failure
2768 */
2769static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2770 struct wireless_dev *wdev,
2771 const void *data,
2772 int data_len)
2773{
2774 struct net_device *dev = wdev->netdev;
2775 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2776 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2777 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2778 int ret_val;
2779 uint32_t no_dfs_flag = 0;
2780
Jeff Johnson1f61b612016-02-12 16:28:33 -08002781 ENTER_DEV(dev);
2782
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002783 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302784 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002785 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002786
2787 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2788 data, data_len,
2789 wlan_hdd_set_no_dfs_flag_config_policy)) {
2790 hdd_err("invalid attr");
2791 return -EINVAL;
2792 }
2793
2794 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2795 hdd_err("attr dfs flag failed");
2796 return -EINVAL;
2797 }
2798
2799 no_dfs_flag = nla_get_u32(
2800 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2801
Jeff Johnson020db452016-06-29 14:37:26 -07002802 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002803
2804 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002805 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002806 return -EINVAL;
2807 }
2808
2809 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2810 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 return ret_val;
2812}
2813
2814/**
2815 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2816 *
2817 * @wiphy: wiphy device pointer
2818 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002819 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 * @data_len: Buffer length
2821 *
2822 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2823 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2824 *
2825 * Return: EOK or other error codes.
2826 */
2827
2828static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2829 struct wireless_dev *wdev,
2830 const void *data,
2831 int data_len)
2832{
2833 int ret;
2834
2835 cds_ssr_protect(__func__);
2836 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2837 data, data_len);
2838 cds_ssr_unprotect(__func__);
2839
2840 return ret;
2841}
2842
Manikandan Mohan80dea792016-04-28 16:36:48 -07002843static const struct nla_policy
2844wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2845 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2846};
2847
2848/**
2849 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2850 * @wiphy: wiphy device pointer
2851 * @wdev: wireless device pointer
2852 * @data: Vendor command data buffer
2853 * @data_len: Buffer length
2854 *
2855 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2856 * setup WISA Mode features.
2857 *
2858 * Return: Success(0) or reason code for failure
2859 */
2860static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2861 struct wireless_dev *wdev, const void *data, int data_len)
2862{
2863 struct net_device *dev = wdev->netdev;
2864 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2865 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2866 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2867 struct sir_wisa_params wisa;
2868 int ret_val;
2869 QDF_STATUS status;
2870 bool wisa_mode;
2871
2872 ENTER_DEV(dev);
2873 ret_val = wlan_hdd_validate_context(hdd_ctx);
2874 if (ret_val)
2875 goto err;
2876
2877 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2878 hdd_err("Command not allowed in FTM mode");
2879 return -EPERM;
2880 }
2881
2882 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2883 wlan_hdd_wisa_cmd_policy)) {
2884 hdd_err("Invalid WISA cmd attributes");
2885 ret_val = -EINVAL;
2886 goto err;
2887 }
2888 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2889 hdd_err("Invalid WISA mode");
2890 ret_val = -EINVAL;
2891 goto err;
2892 }
2893
2894 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2895 hdd_info("WISA Mode: %d", wisa_mode);
2896 wisa.mode = wisa_mode;
2897 wisa.vdev_id = adapter->sessionId;
2898 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002899 if (!QDF_IS_STATUS_SUCCESS(status)) {
2900 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002901 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002902 }
2903 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2904 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2905 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002906err:
2907 EXIT();
2908 return ret_val;
2909}
2910
2911/**
2912 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2913 * @wiphy: corestack handler
2914 * @wdev: wireless device
2915 * @data: data
2916 * @data_len: data length
2917 *
2918 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2919 * setup WISA mode features.
2920 *
2921 * Return: Success(0) or reason code for failure
2922 */
2923static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2924 struct wireless_dev *wdev,
2925 const void *data,
2926 int data_len)
2927{
2928 int ret;
2929
2930 cds_ssr_protect(__func__);
2931 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2932 cds_ssr_unprotect(__func__);
2933
2934 return ret;
2935}
2936
Anurag Chouhan96919482016-07-13 16:36:57 +05302937/*
2938 * define short names for the global vendor params
2939 * used by __wlan_hdd_cfg80211_get_station_cmd()
2940 */
2941#define STATION_INVALID \
2942 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2943#define STATION_INFO \
2944 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2945#define STATION_ASSOC_FAIL_REASON \
2946 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2947#define STATION_MAX \
2948 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2949
2950static const struct nla_policy
2951hdd_get_station_policy[STATION_MAX + 1] = {
2952 [STATION_INFO] = {.type = NLA_FLAG},
2953 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2954};
2955
2956/**
2957 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2958 * @hdd_ctx: HDD context within host driver
2959 * @wdev: wireless device
2960 *
2961 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2962 * Validate cmd attributes and send the station info to upper layers.
2963 *
2964 * Return: Success(0) or reason code for failure
2965 */
2966static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2967 hdd_adapter_t *adapter)
2968{
2969 struct sk_buff *skb = NULL;
2970 uint32_t nl_buf_len;
2971 hdd_station_ctx_t *hdd_sta_ctx;
2972
2973 nl_buf_len = NLMSG_HDRLEN;
2974 nl_buf_len += sizeof(uint32_t);
2975 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2976
2977 if (!skb) {
2978 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2979 return -ENOMEM;
2980 }
2981
2982 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2983
2984 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2985 hdd_sta_ctx->conn_info.assoc_status_code)) {
2986 hdd_err("put fail");
2987 goto fail;
2988 }
2989 return cfg80211_vendor_cmd_reply(skb);
2990fail:
2991 if (skb)
2992 kfree_skb(skb);
2993 return -EINVAL;
2994}
2995
2996/**
2997 * hdd_map_auth_type() - transform auth type specific to
2998 * vendor command
2999 * @auth_type: csr auth type
3000 *
3001 * Return: Success(0) or reason code for failure
3002 */
3003static int hdd_convert_auth_type(uint32_t auth_type)
3004{
3005 uint32_t ret_val;
3006
3007 switch (auth_type) {
3008 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3009 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3010 break;
3011 case eCSR_AUTH_TYPE_SHARED_KEY:
3012 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3013 break;
3014 case eCSR_AUTH_TYPE_WPA:
3015 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3016 break;
3017 case eCSR_AUTH_TYPE_WPA_PSK:
3018 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3019 break;
3020 case eCSR_AUTH_TYPE_AUTOSWITCH:
3021 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3022 break;
3023 case eCSR_AUTH_TYPE_WPA_NONE:
3024 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3025 break;
3026 case eCSR_AUTH_TYPE_RSN:
3027 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3028 break;
3029 case eCSR_AUTH_TYPE_RSN_PSK:
3030 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3031 break;
3032 case eCSR_AUTH_TYPE_FT_RSN:
3033 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3034 break;
3035 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3036 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3037 break;
3038 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3039 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3040 break;
3041 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3042 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3043 break;
3044 case eCSR_AUTH_TYPE_CCKM_WPA:
3045 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3046 break;
3047 case eCSR_AUTH_TYPE_CCKM_RSN:
3048 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3049 break;
3050 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3051 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3052 break;
3053 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3054 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3055 break;
3056 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3057 case eCSR_AUTH_TYPE_FAILED:
3058 case eCSR_AUTH_TYPE_NONE:
3059 default:
3060 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3061 break;
3062 }
3063 return ret_val;
3064}
3065
3066/**
3067 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3068 * vendor command
3069 * @dot11mode: dot11mode
3070 *
3071 * Return: Success(0) or reason code for failure
3072 */
3073static int hdd_convert_dot11mode(uint32_t dot11mode)
3074{
3075 uint32_t ret_val;
3076
3077 switch (dot11mode) {
3078 case eCSR_CFG_DOT11_MODE_11A:
3079 ret_val = QCA_WLAN_802_11_MODE_11A;
3080 break;
3081 case eCSR_CFG_DOT11_MODE_11B:
3082 ret_val = QCA_WLAN_802_11_MODE_11B;
3083 break;
3084 case eCSR_CFG_DOT11_MODE_11G:
3085 ret_val = QCA_WLAN_802_11_MODE_11G;
3086 break;
3087 case eCSR_CFG_DOT11_MODE_11N:
3088 ret_val = QCA_WLAN_802_11_MODE_11N;
3089 break;
3090 case eCSR_CFG_DOT11_MODE_11AC:
3091 ret_val = QCA_WLAN_802_11_MODE_11AC;
3092 break;
3093 case eCSR_CFG_DOT11_MODE_AUTO:
3094 case eCSR_CFG_DOT11_MODE_ABG:
3095 default:
3096 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3097 }
3098 return ret_val;
3099}
3100
3101/**
3102 * hdd_add_tx_bitrate() - add tx bitrate attribute
3103 * @skb: pointer to sk buff
3104 * @hdd_sta_ctx: pointer to hdd station context
3105 * @idx: attribute index
3106 *
3107 * Return: Success(0) or reason code for failure
3108 */
3109static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3110 hdd_station_ctx_t *hdd_sta_ctx,
3111 int idx)
3112{
3113 struct nlattr *nla_attr;
3114 uint32_t bitrate, bitrate_compat;
3115
3116 nla_attr = nla_nest_start(skb, idx);
3117 if (!nla_attr)
3118 goto fail;
3119 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3120 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3121
3122 /* report 16-bit bitrate only if we can */
3123 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3124 if (bitrate > 0 &&
3125 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3126 hdd_err("put fail");
3127 goto fail;
3128 }
3129 if (bitrate_compat > 0 &&
3130 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3131 hdd_err("put fail");
3132 goto fail;
3133 }
3134 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3135 hdd_sta_ctx->conn_info.txrate.nss)) {
3136 hdd_err("put fail");
3137 goto fail;
3138 }
3139 nla_nest_end(skb, nla_attr);
3140 return 0;
3141fail:
3142 return -EINVAL;
3143}
3144
3145/**
3146 * hdd_add_sta_info() - add station info attribute
3147 * @skb: pointer to sk buff
3148 * @hdd_sta_ctx: pointer to hdd station context
3149 * @idx: attribute index
3150 *
3151 * Return: Success(0) or reason code for failure
3152 */
3153static int32_t hdd_add_sta_info(struct sk_buff *skb,
3154 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3155{
3156 struct nlattr *nla_attr;
3157
3158 nla_attr = nla_nest_start(skb, idx);
3159 if (!nla_attr)
3160 goto fail;
3161 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3162 (hdd_sta_ctx->conn_info.signal + 100))) {
3163 hdd_err("put fail");
3164 goto fail;
3165 }
3166 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3167 goto fail;
3168 nla_nest_end(skb, nla_attr);
3169 return 0;
3170fail:
3171 return -EINVAL;
3172}
3173
3174/**
3175 * hdd_add_survey_info() - add survey info attribute
3176 * @skb: pointer to sk buff
3177 * @hdd_sta_ctx: pointer to hdd station context
3178 * @idx: attribute index
3179 *
3180 * Return: Success(0) or reason code for failure
3181 */
3182static int32_t hdd_add_survey_info(struct sk_buff *skb,
3183 hdd_station_ctx_t *hdd_sta_ctx,
3184 int idx)
3185{
3186 struct nlattr *nla_attr;
3187
3188 nla_attr = nla_nest_start(skb, idx);
3189 if (!nla_attr)
3190 goto fail;
3191 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3192 hdd_sta_ctx->conn_info.freq) ||
3193 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3194 (hdd_sta_ctx->conn_info.noise + 100))) {
3195 hdd_err("put fail");
3196 goto fail;
3197 }
3198 nla_nest_end(skb, nla_attr);
3199 return 0;
3200fail:
3201 return -EINVAL;
3202}
3203
3204/**
3205 * hdd_add_link_standard_info() - add link info attribute
3206 * @skb: pointer to sk buff
3207 * @hdd_sta_ctx: pointer to hdd station context
3208 * @idx: attribute index
3209 *
3210 * Return: Success(0) or reason code for failure
3211 */
3212static int32_t
3213hdd_add_link_standard_info(struct sk_buff *skb,
3214 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3215{
3216 struct nlattr *nla_attr;
3217
3218 nla_attr = nla_nest_start(skb, idx);
3219 if (!nla_attr)
3220 goto fail;
3221 if (nla_put(skb,
3222 NL80211_ATTR_SSID,
3223 hdd_sta_ctx->conn_info.SSID.SSID.length,
3224 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3225 hdd_err("put fail");
3226 goto fail;
3227 }
3228 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3229 goto fail;
3230 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3231 goto fail;
3232 nla_nest_end(skb, nla_attr);
3233 return 0;
3234fail:
3235 return -EINVAL;
3236}
3237
3238/**
3239 * hdd_add_ap_standard_info() - add ap info attribute
3240 * @skb: pointer to sk buff
3241 * @hdd_sta_ctx: pointer to hdd station context
3242 * @idx: attribute index
3243 *
3244 * Return: Success(0) or reason code for failure
3245 */
3246static int32_t
3247hdd_add_ap_standard_info(struct sk_buff *skb,
3248 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3249{
3250 struct nlattr *nla_attr;
3251
3252 nla_attr = nla_nest_start(skb, idx);
3253 if (!nla_attr)
3254 goto fail;
3255 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3256 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3257 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3258 &hdd_sta_ctx->conn_info.vht_caps)) {
3259 hdd_err("put fail");
3260 goto fail;
3261 }
3262 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3263 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3264 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3265 &hdd_sta_ctx->conn_info.ht_caps)) {
3266 hdd_err("put fail");
3267 goto fail;
3268 }
3269 nla_nest_end(skb, nla_attr);
3270 return 0;
3271fail:
3272 return -EINVAL;
3273}
3274
3275/**
3276 * hdd_get_station_info() - send BSS information to supplicant
3277 * @hdd_ctx: pointer to hdd context
3278 * @adapter: pointer to adapter
3279 *
3280 * Return: 0 if success else error status
3281 */
3282static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3283 hdd_adapter_t *adapter)
3284{
3285 struct sk_buff *skb = NULL;
3286 uint8_t *tmp_hs20 = NULL;
3287 uint32_t nl_buf_len;
3288 hdd_station_ctx_t *hdd_sta_ctx;
3289
3290 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3291
3292 nl_buf_len = NLMSG_HDRLEN;
3293 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3294 sizeof(hdd_sta_ctx->conn_info.freq) +
3295 sizeof(hdd_sta_ctx->conn_info.noise) +
3296 sizeof(hdd_sta_ctx->conn_info.signal) +
3297 (sizeof(uint32_t) * 2) +
3298 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3299 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3300 sizeof(hdd_sta_ctx->conn_info.authType) +
3301 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3302 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3303 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3304 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3305 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3306 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3307 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3308 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3309 1);
3310 }
3311 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3312 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3313 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3314 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3315
3316
3317 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3318 if (!skb) {
3319 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3320 return -ENOMEM;
3321 }
3322
3323 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3324 LINK_INFO_STANDARD_NL80211_ATTR)) {
3325 hdd_err("put fail");
3326 goto fail;
3327 }
3328 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3329 AP_INFO_STANDARD_NL80211_ATTR)) {
3330 hdd_err("put fail");
3331 goto fail;
3332 }
3333 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3334 hdd_sta_ctx->conn_info.roam_count) ||
3335 nla_put_u32(skb, INFO_AKM,
3336 hdd_convert_auth_type(
3337 hdd_sta_ctx->conn_info.authType)) ||
3338 nla_put_u32(skb, WLAN802_11_MODE,
3339 hdd_convert_dot11mode(
3340 hdd_sta_ctx->conn_info.dot11Mode))) {
3341 hdd_err("put fail");
3342 goto fail;
3343 }
3344 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3345 if (nla_put(skb, HT_OPERATION,
3346 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3347 &hdd_sta_ctx->conn_info.ht_operation)) {
3348 hdd_err("put fail");
3349 goto fail;
3350 }
3351 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3352 if (nla_put(skb, VHT_OPERATION,
3353 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3354 &hdd_sta_ctx->conn_info.vht_operation)) {
3355 hdd_err("put fail");
3356 goto fail;
3357 }
3358 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3359 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3360 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3361 tmp_hs20 + 1)) {
3362 hdd_err("put fail");
3363 goto fail;
3364 }
3365
3366 return cfg80211_vendor_cmd_reply(skb);
3367fail:
3368 if (skb)
3369 kfree_skb(skb);
3370 return -EINVAL;
3371}
3372
3373/**
3374 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3375 * @wiphy: corestack handler
3376 * @wdev: wireless device
3377 * @data: data
3378 * @data_len: data length
3379 *
3380 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3381 * Validate cmd attributes and send the station info to upper layers.
3382 *
3383 * Return: Success(0) or reason code for failure
3384 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303385static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303386__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3387 struct wireless_dev *wdev,
3388 const void *data,
3389 int data_len)
3390{
3391 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3392 struct net_device *dev = wdev->netdev;
3393 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3394 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3395 int32_t status;
3396
3397 ENTER_DEV(dev);
3398 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3399 hdd_err("Command not allowed in FTM mode");
3400 status = -EPERM;
3401 goto out;
3402 }
3403
3404 status = wlan_hdd_validate_context(hdd_ctx);
3405 if (0 != status)
3406 goto out;
3407
3408
3409 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3410 data, data_len, NULL);
3411 if (status) {
3412 hdd_err("Invalid ATTR");
3413 goto out;
3414 }
3415
3416 /* Parse and fetch Command Type*/
3417 if (tb[STATION_INFO]) {
3418 status = hdd_get_station_info(hdd_ctx, adapter);
3419 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3420 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3421 } else {
3422 hdd_err("get station info cmd type failed");
3423 status = -EINVAL;
3424 goto out;
3425 }
3426 EXIT();
3427out:
3428 return status;
3429}
3430
3431/**
3432 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3433 * @wiphy: corestack handler
3434 * @wdev: wireless device
3435 * @data: data
3436 * @data_len: data length
3437 *
3438 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3439 * Validate cmd attributes and send the station info to upper layers.
3440 *
3441 * Return: Success(0) or reason code for failure
3442 */
3443static int32_t
3444hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3445 struct wireless_dev *wdev,
3446 const void *data,
3447 int data_len)
3448{
3449 int ret;
3450
3451 cds_ssr_protect(__func__);
3452 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3453 cds_ssr_unprotect(__func__);
3454
3455 return ret;
3456}
3457
3458/*
3459 * undef short names defined for get station command
3460 * used by __wlan_hdd_cfg80211_get_station_cmd()
3461 */
3462#undef STATION_INVALID
3463#undef STATION_INFO
3464#undef STATION_ASSOC_FAIL_REASON
3465#undef STATION_MAX
3466
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003467#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3468/**
3469 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3470 * @wiphy: pointer to wireless wiphy structure.
3471 * @wdev: pointer to wireless_dev structure.
3472 * @data: Pointer to the Key data
3473 * @data_len:Length of the data passed
3474 *
3475 * This is called when wlan driver needs to save the keys received via
3476 * vendor specific command.
3477 *
3478 * Return: Return the Success or Failure code.
3479 */
3480static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3481 struct wireless_dev *wdev,
3482 const void *data, int data_len)
3483{
3484 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3485 struct net_device *dev = wdev->netdev;
3486 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3487 hdd_context_t *hdd_ctx_ptr;
3488 int status;
3489
Jeff Johnson1f61b612016-02-12 16:28:33 -08003490 ENTER_DEV(dev);
3491
Anurag Chouhan6d760662016-02-20 16:05:43 +05303492 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493 hdd_err("Command not allowed in FTM mode");
3494 return -EPERM;
3495 }
3496
3497 if ((data == NULL) || (data_len == 0) ||
3498 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003499 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 return -EINVAL;
3501 }
3502
3503 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3504 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003505 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506 return -EINVAL;
3507 }
3508
3509 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303510 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3513 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003514 true,
3515 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303516 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3517 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3519 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3520 return 0;
3521}
3522
3523/**
3524 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3525 * @wiphy: pointer to wireless wiphy structure.
3526 * @wdev: pointer to wireless_dev structure.
3527 * @data: Pointer to the Key data
3528 * @data_len:Length of the data passed
3529 *
3530 * This is called when wlan driver needs to save the keys received via
3531 * vendor specific command.
3532 *
3533 * Return: Return the Success or Failure code.
3534 */
3535static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3536 struct wireless_dev *wdev,
3537 const void *data, int data_len)
3538{
3539 int ret;
3540
3541 cds_ssr_protect(__func__);
3542 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3543 cds_ssr_unprotect(__func__);
3544
3545 return ret;
3546}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003547#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548
3549static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3550 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3551 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3552 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003553 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554};
3555
3556/**
3557 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3558 * @wiphy: pointer to wireless wiphy structure.
3559 * @wdev: pointer to wireless_dev structure.
3560 * @data: Pointer to the data to be passed via vendor interface
3561 * @data_len:Length of the data to be passed
3562 *
3563 * This is called when wlan driver needs to send wifi driver related info
3564 * (driver/fw version) to the user space application upon request.
3565 *
3566 * Return: Return the Success or Failure code.
3567 */
3568static int
3569__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3570 struct wireless_dev *wdev,
3571 const void *data, int data_len)
3572{
3573 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3574 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003575 tSirVersionString driver_version;
3576 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003579 struct sk_buff *reply_skb;
3580 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581
Jeff Johnson1f61b612016-02-12 16:28:33 -08003582 ENTER_DEV(wdev->netdev);
3583
Anurag Chouhan6d760662016-02-20 16:05:43 +05303584 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 hdd_err("Command not allowed in FTM mode");
3586 return -EPERM;
3587 }
3588
3589 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303590 if (status)
3591 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592
3593 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3594 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003595 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003596 return -EINVAL;
3597 }
3598
3599 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003600 hdd_err("Rcvd req for Driver version");
3601 strlcpy(driver_version, QWLAN_VERSIONSTR,
3602 sizeof(driver_version));
3603 skb_len += strlen(driver_version) + 1;
3604 count++;
3605 }
3606
3607 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3608 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3610 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003611 snprintf(firmware_version, sizeof(firmware_version),
3612 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3613 skb_len += strlen(firmware_version) + 1;
3614 count++;
3615 }
3616
3617 if (count == 0) {
3618 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003619 return -EINVAL;
3620 }
3621
Ryan Hsu7ac88852016-04-28 10:20:34 -07003622 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3623 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003626 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 return -ENOMEM;
3628 }
3629
Ryan Hsu7ac88852016-04-28 10:20:34 -07003630 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3631 if (nla_put_string(reply_skb,
3632 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3633 driver_version))
3634 goto error_nla_fail;
3635 }
3636
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303637 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003638 if (nla_put_string(reply_skb,
3639 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3640 firmware_version))
3641 goto error_nla_fail;
3642 }
3643
3644 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3645 if (nla_put_u32(reply_skb,
3646 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3647 hdd_ctx->radio_index))
3648 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649 }
3650
3651 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003652
3653error_nla_fail:
3654 hdd_err("nla put fail");
3655 kfree_skb(reply_skb);
3656 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003657}
3658
3659/**
3660 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3661 * @wiphy: pointer to wireless wiphy structure.
3662 * @wdev: pointer to wireless_dev structure.
3663 * @data: Pointer to the data to be passed via vendor interface
3664 * @data_len:Length of the data to be passed
3665 *
3666 * This is called when wlan driver needs to send wifi driver related info
3667 * (driver/fw version) to the user space application upon request.
3668 *
3669 * Return: Return the Success or Failure code.
3670 */
3671static int
3672wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3673 struct wireless_dev *wdev,
3674 const void *data, int data_len)
3675{
3676 int ret;
3677
3678 cds_ssr_protect(__func__);
3679 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3680 cds_ssr_unprotect(__func__);
3681
3682 return ret;
3683}
3684
3685/**
3686 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3687 * @wiphy: pointer to wireless wiphy structure.
3688 * @wdev: pointer to wireless_dev structure.
3689 * @data: Pointer to the data to be passed via vendor interface
3690 * @data_len:Length of the data to be passed
3691 *
3692 * This is called by userspace to know the supported logger features
3693 *
3694 * Return: Return the Success or Failure code.
3695 */
3696static int
3697__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3698 struct wireless_dev *wdev,
3699 const void *data, int data_len)
3700{
3701 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3702 int status;
3703 uint32_t features;
3704 struct sk_buff *reply_skb = NULL;
3705
Jeff Johnson1f61b612016-02-12 16:28:33 -08003706 ENTER_DEV(wdev->netdev);
3707
Anurag Chouhan6d760662016-02-20 16:05:43 +05303708 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 hdd_err("Command not allowed in FTM mode");
3710 return -EPERM;
3711 }
3712
3713 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303714 if (status)
3715 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003716
3717 features = 0;
3718
3719 if (hdd_is_memdump_supported())
3720 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3721 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3722 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3723 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3724
3725 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3726 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3727 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003728 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 return -ENOMEM;
3730 }
3731
Jeff Johnson020db452016-06-29 14:37:26 -07003732 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3734 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003735 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736 kfree_skb(reply_skb);
3737 return -EINVAL;
3738 }
3739
3740 return cfg80211_vendor_cmd_reply(reply_skb);
3741}
3742
3743/**
3744 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3745 * @wiphy: pointer to wireless wiphy structure.
3746 * @wdev: pointer to wireless_dev structure.
3747 * @data: Pointer to the data to be passed via vendor interface
3748 * @data_len:Length of the data to be passed
3749 *
3750 * This is called by userspace to know the supported logger features
3751 *
3752 * Return: Return the Success or Failure code.
3753 */
3754static int
3755wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3756 struct wireless_dev *wdev,
3757 const void *data, int data_len)
3758{
3759 int ret;
3760
3761 cds_ssr_protect(__func__);
3762 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3763 data, data_len);
3764 cds_ssr_unprotect(__func__);
3765
3766 return ret;
3767}
3768
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003769#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770/**
3771 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3772 * @hdd_ctx_ptr: pointer to HDD Context.
3773 * @bssid: pointer to bssid of roamed AP.
3774 * @req_rsn_ie: Pointer to request RSN IE
3775 * @req_rsn_len: Length of the request RSN IE
3776 * @rsp_rsn_ie: Pointer to response RSN IE
3777 * @rsp_rsn_len: Length of the response RSN IE
3778 * @roam_info_ptr: Pointer to the roaming related information
3779 *
3780 * This is called when wlan driver needs to send the roaming and
3781 * authorization information after roaming.
3782 *
3783 * The information that would be sent is the request RSN IE, response
3784 * RSN IE and BSSID of the newly roamed AP.
3785 *
3786 * If the Authorized status is authenticated, then additional parameters
3787 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3788 * supplicant.
3789 *
3790 * The supplicant upon receiving this event would ignore the legacy
3791 * cfg80211_roamed call and use the entire information from this event.
3792 * The cfg80211_roamed should still co-exist since the kernel will
3793 * make use of the parameters even if the supplicant ignores it.
3794 *
3795 * Return: Return the Success or Failure code.
3796 */
3797int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3798 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3799 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3800{
3801 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003802 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803 ENTER();
3804
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303805 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003808 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003809 !roam_info_ptr->roamSynchInProgress)
3810 return 0;
3811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3813 NULL,
3814 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3815 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3816 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003817 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3819 GFP_KERNEL);
3820
3821 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003822 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003823 return -EINVAL;
3824 }
3825
3826 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3827 ETH_ALEN, bssid) ||
3828 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3829 req_rsn_len, req_rsn_ie) ||
3830 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3831 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003832 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003833 goto nla_put_failure;
3834 }
Jeff Johnson020db452016-06-29 14:37:26 -07003835 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836 if (roam_info_ptr->synchAuthStatus ==
3837 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003838 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003839 if (nla_put_u8(skb,
3840 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3841 hdd_err("nla put fail");
3842 goto nla_put_failure;
3843 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003844 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3845 /* if FT or CCKM connection: dont send replay counter */
3846 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3847 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3848 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3849 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3850 nla_put(skb,
3851 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3852 SIR_REPLAY_CTR_LEN,
3853 roam_info_ptr->replay_ctr)) {
3854 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003855 hdd_err("failed to send replay counter.");
3856 goto nla_put_failure;
3857 }
3858 if (nla_put(skb,
3859 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3860 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3861 nla_put(skb,
3862 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3863 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3864 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865 goto nla_put_failure;
3866 }
3867 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003868 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3870 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003871 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 goto nla_put_failure;
3873 }
3874 }
3875
Jeff Johnson020db452016-06-29 14:37:26 -07003876 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003877 roam_info_ptr->subnet_change_status);
3878
3879 /*
3880 * Add subnet change status if subnet has changed
3881 * 0 = unchanged
3882 * 1 = changed
3883 * 2 = unknown
3884 */
3885 if (roam_info_ptr->subnet_change_status) {
3886 if (nla_put_u8(skb,
3887 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3888 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003889 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003890 goto nla_put_failure;
3891 }
3892 }
3893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 cfg80211_vendor_event(skb, GFP_KERNEL);
3895 return 0;
3896
3897nla_put_failure:
3898 kfree_skb(skb);
3899 return -EINVAL;
3900}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003901#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902
3903static const struct nla_policy
3904wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3905
3906 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3907 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3908 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303909 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303910 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3911 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003912 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3913 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3914 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3915 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3916 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917};
3918
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003919/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303920 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3921 *
3922 * @adapter: Pointer to HDD adapter
3923 * @ie_data: Pointer to Scan IEs buffer
3924 * @ie_len: Length of Scan IEs
3925 *
3926 * Return: 0 on success; error number otherwise
3927 */
3928static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3929 uint8_t *ie_data, uint8_t ie_len)
3930{
3931 hdd_scaninfo_t *scan_info = NULL;
3932 scan_info = &adapter->scan_info;
3933
3934 if (scan_info->default_scan_ies) {
3935 qdf_mem_free(scan_info->default_scan_ies);
3936 scan_info->default_scan_ies = NULL;
3937 }
3938
3939 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3940 if (!scan_info->default_scan_ies)
3941 return -ENOMEM;
3942
3943 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3944 scan_info->default_scan_ies_len = ie_len;
3945 return 0;
3946}
3947
3948/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3950 * vendor command
3951 *
3952 * @wiphy: wiphy device pointer
3953 * @wdev: wireless device pointer
3954 * @data: Vendor command data buffer
3955 * @data_len: Buffer length
3956 *
3957 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3958 *
3959 * Return: Error code.
3960 */
3961static int
3962__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3963 struct wireless_dev *wdev,
3964 const void *data,
3965 int data_len)
3966{
3967 struct net_device *dev = wdev->netdev;
3968 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3969 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3970 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3971 int ret_val = 0;
3972 u32 modulated_dtim;
3973 u16 stats_avg_factor;
3974 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303975 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003976 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003977 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303978 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303979 int attr_len;
3980 int access_policy = 0;
3981 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3982 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303983 uint16_t scan_ie_len = 0;
3984 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303985 struct sir_set_tx_rx_aggregation_size request;
3986 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003987 uint8_t retry, delay;
3988 int param_id;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303989
Jeff Johnson1f61b612016-02-12 16:28:33 -08003990 ENTER_DEV(dev);
3991
Anurag Chouhan6d760662016-02-20 16:05:43 +05303992 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993 hdd_err("Command not allowed in FTM mode");
3994 return -EPERM;
3995 }
3996
3997 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303998 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000
4001 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4002 data, data_len,
4003 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004004 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005 return -EINVAL;
4006 }
4007
Krunal Sonie3531942016-04-12 17:43:53 -07004008 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4009 ftm_capab = nla_get_u32(tb[
4010 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4011 hdd_ctx->config->fine_time_meas_cap =
4012 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4013 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304014 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004015 hdd_ctx->config->fine_time_meas_cap);
4016 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4017 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4018 hdd_ctx->config->fine_time_meas_cap);
4019 }
4020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4022 modulated_dtim = nla_get_u32(
4023 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4024
4025 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4026 adapter->sessionId,
4027 modulated_dtim);
4028
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304029 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 ret_val = -EPERM;
4031 }
4032
Kapil Gupta6213c012016-09-02 19:39:09 +05304033 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4034 qpower = nla_get_u8(
4035 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4036 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4037 ret_val = -EINVAL;
4038 }
4039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4041 stats_avg_factor = nla_get_u16(
4042 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4043 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4044 adapter->sessionId,
4045 stats_avg_factor);
4046
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304047 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 ret_val = -EPERM;
4049 }
4050
4051
4052 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4053 guard_time = nla_get_u32(
4054 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4055 status = sme_configure_guard_time(hdd_ctx->hHal,
4056 adapter->sessionId,
4057 guard_time);
4058
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304059 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004060 ret_val = -EPERM;
4061 }
4062
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304063 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4064 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4065 attr_len = nla_len(
4066 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4067 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4068 hdd_info("Invalid value. attr_len %d",
4069 attr_len);
4070 return -EINVAL;
4071 }
4072
4073 nla_memcpy(&vendor_ie,
4074 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4075 attr_len);
4076 vendor_ie_present = true;
4077 hdd_info("Access policy vendor ie present.attr_len %d",
4078 attr_len);
4079 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4080 &vendor_ie[0], attr_len);
4081 }
4082
4083 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4084 access_policy = (int) nla_get_u32(
4085 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4086 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4087 (access_policy >
4088 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4089 hdd_info("Invalid value. access_policy %d",
4090 access_policy);
4091 return -EINVAL;
4092 }
4093 access_policy_present = true;
4094 hdd_info("Access policy present. access_policy %d",
4095 access_policy);
4096 }
4097
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004098 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4099 retry = nla_get_u8(tb[
4100 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4101 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4102 CFG_NON_AGG_RETRY_MAX : retry;
4103 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4104 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4105 retry, PDEV_CMD);
4106 }
4107
4108 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4109 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4110 retry = retry > CFG_AGG_RETRY_MAX ?
4111 CFG_AGG_RETRY_MAX : retry;
4112
4113 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4114 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4115 CFG_AGG_RETRY_MIN : retry;
4116 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4117 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4118 retry, PDEV_CMD);
4119 }
4120
4121 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4122 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4123 retry = retry > CFG_MGMT_RETRY_MAX ?
4124 CFG_MGMT_RETRY_MAX : retry;
4125 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4126 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4127 retry, PDEV_CMD);
4128 }
4129
4130 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4131 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4132 retry = retry > CFG_CTRL_RETRY_MAX ?
4133 CFG_CTRL_RETRY_MAX : retry;
4134 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4135 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4136 retry, PDEV_CMD);
4137 }
4138
4139 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4140 delay = nla_get_u8(tb[
4141 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4142 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4143 CFG_PROPAGATION_DELAY_MAX : delay;
4144 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4145 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4146 delay, PDEV_CMD);
4147 }
4148
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304149 if (vendor_ie_present && access_policy_present) {
4150 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4151 access_policy =
4152 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304153 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304154 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304155 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304156
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304157 hdd_info("calling sme_update_access_policy_vendor_ie");
4158 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4159 adapter->sessionId, &vendor_ie[0],
4160 access_policy);
4161 if (QDF_STATUS_SUCCESS != status) {
4162 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304163 return -EINVAL;
4164 }
4165 }
4166
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304167 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4168 set_value = nla_get_u8(
4169 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4170 hdd_info("set_value: %d", set_value);
4171 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4172 }
4173
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304174 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4175 scan_ie_len = nla_len(
4176 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4177 hdd_info("Received default scan IE of len %d session %d device mode %d",
4178 scan_ie_len, adapter->sessionId,
4179 adapter->device_mode);
4180 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4181 scan_ie = (uint8_t *) nla_data(tb
4182 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304183
4184 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4185 scan_ie_len))
4186 hdd_err("Failed to save default scan IEs");
4187
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304188 if (adapter->device_mode == QDF_STA_MODE) {
4189 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4190 adapter->sessionId, scan_ie,
4191 scan_ie_len);
4192 if (QDF_STATUS_SUCCESS != status)
4193 ret_val = -EPERM;
4194 }
4195 } else
4196 ret_val = -EPERM;
4197 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304198
4199 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4200 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4201 /* if one is specified, both must be specified */
4202 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4203 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4204 hdd_err("Both TX and RX MPDU Aggregation required");
4205 return -EINVAL;
4206 }
4207
4208 request.tx_aggregation_size = nla_get_u8(
4209 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4210 request.rx_aggregation_size = nla_get_u8(
4211 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4212 request.vdev_id = adapter->sessionId;
4213
4214 if (request.tx_aggregation_size >=
4215 CFG_TX_AGGREGATION_SIZE_MIN &&
4216 request.tx_aggregation_size <=
4217 CFG_TX_AGGREGATION_SIZE_MAX &&
4218 request.rx_aggregation_size >=
4219 CFG_RX_AGGREGATION_SIZE_MIN &&
4220 request.rx_aggregation_size <=
4221 CFG_RX_AGGREGATION_SIZE_MAX) {
4222 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4223 if (qdf_status != QDF_STATUS_SUCCESS) {
4224 hdd_err("failed to set aggr sizes err %d",
4225 qdf_status);
4226 ret_val = -EPERM;
4227 }
4228 } else {
4229 hdd_err("TX %d RX %d MPDU aggr size not in range",
4230 request.tx_aggregation_size,
4231 request.rx_aggregation_size);
4232 ret_val = -EINVAL;
4233 }
4234 }
4235
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304236 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4237 uint8_t ignore_assoc_disallowed;
4238
4239 ignore_assoc_disallowed
4240 = nla_get_u8(tb[
4241 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4242 hdd_info("Set ignore_assoc_disallowed value - %d",
4243 ignore_assoc_disallowed);
4244 if ((ignore_assoc_disallowed <
4245 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4246 (ignore_assoc_disallowed >
4247 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4248 return -EPERM;
4249
4250 sme_update_session_param(hdd_ctx->hHal,
4251 adapter->sessionId,
4252 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4253 ignore_assoc_disallowed);
4254 }
4255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256 return ret_val;
4257}
4258
4259/**
4260 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4261 * vendor command
4262 *
4263 * @wiphy: wiphy device pointer
4264 * @wdev: wireless device pointer
4265 * @data: Vendor command data buffer
4266 * @data_len: Buffer length
4267 *
4268 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4269 *
4270 * Return: EOK or other error codes.
4271 */
4272static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4273 struct wireless_dev *wdev,
4274 const void *data,
4275 int data_len)
4276{
4277 int ret;
4278
4279 cds_ssr_protect(__func__);
4280 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4281 data, data_len);
4282 cds_ssr_unprotect(__func__);
4283
4284 return ret;
4285}
4286
4287static const struct
4288nla_policy
4289qca_wlan_vendor_wifi_logger_start_policy
4290[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4291 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4292 = {.type = NLA_U32 },
4293 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4294 = {.type = NLA_U32 },
4295 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4296 = {.type = NLA_U32 },
4297};
4298
4299/**
4300 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4301 * or disable the collection of packet statistics from the firmware
4302 * @wiphy: WIPHY structure pointer
4303 * @wdev: Wireless device structure pointer
4304 * @data: Pointer to the data received
4305 * @data_len: Length of the data received
4306 *
4307 * This function enables or disables the collection of packet statistics from
4308 * the firmware
4309 *
4310 * Return: 0 on success and errno on failure
4311 */
4312static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4313 struct wireless_dev *wdev,
4314 const void *data,
4315 int data_len)
4316{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304317 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4319 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4320 struct sir_wifi_start_log start_log;
4321
Jeff Johnson1f61b612016-02-12 16:28:33 -08004322 ENTER_DEV(wdev->netdev);
4323
Anurag Chouhan6d760662016-02-20 16:05:43 +05304324 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 hdd_err("Command not allowed in FTM mode");
4326 return -EPERM;
4327 }
4328
4329 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304330 if (status)
4331 return status;
4332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333
4334 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4335 data, data_len,
4336 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004337 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 return -EINVAL;
4339 }
4340
4341 /* Parse and fetch ring id */
4342 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004343 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344 return -EINVAL;
4345 }
4346 start_log.ring_id = nla_get_u32(
4347 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004348 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349
4350 /* Parse and fetch verbose level */
4351 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004352 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 return -EINVAL;
4354 }
4355 start_log.verbose_level = nla_get_u32(
4356 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004357 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358
4359 /* Parse and fetch flag */
4360 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004361 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 return -EINVAL;
4363 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304364 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304366 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304368 /* size is buff size which can be set using iwpriv command*/
4369 start_log.size = 0;
4370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004371 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4372
4373 if (start_log.ring_id == RING_ID_WAKELOCK) {
4374 /* Start/stop wakelock events */
4375 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4376 cds_set_wakelock_logging(true);
4377 else
4378 cds_set_wakelock_logging(false);
4379 return 0;
4380 }
4381
4382 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304383 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004384 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385 status);
4386 return -EINVAL;
4387 }
4388 return 0;
4389}
4390
4391/**
4392 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4393 * or disable the collection of packet statistics from the firmware
4394 * @wiphy: WIPHY structure pointer
4395 * @wdev: Wireless device structure pointer
4396 * @data: Pointer to the data received
4397 * @data_len: Length of the data received
4398 *
4399 * This function is used to enable or disable the collection of packet
4400 * statistics from the firmware
4401 *
4402 * Return: 0 on success and errno on failure
4403 */
4404static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4405 struct wireless_dev *wdev,
4406 const void *data,
4407 int data_len)
4408{
4409 int ret = 0;
4410
4411 cds_ssr_protect(__func__);
4412 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4413 wdev, data, data_len);
4414 cds_ssr_unprotect(__func__);
4415
4416 return ret;
4417}
4418
4419static const struct
4420nla_policy
4421qca_wlan_vendor_wifi_logger_get_ring_data_policy
4422[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4423 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4424 = {.type = NLA_U32 },
4425};
4426
4427/**
4428 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4429 * @wiphy: WIPHY structure pointer
4430 * @wdev: Wireless device structure pointer
4431 * @data: Pointer to the data received
4432 * @data_len: Length of the data received
4433 *
4434 * This function is used to flush or retrieve the per packet statistics from
4435 * the driver
4436 *
4437 * Return: 0 on success and errno on failure
4438 */
4439static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4440 struct wireless_dev *wdev,
4441 const void *data,
4442 int data_len)
4443{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304444 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004445 uint32_t ring_id;
4446 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4447 struct nlattr *tb
4448 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4449
Jeff Johnson1f61b612016-02-12 16:28:33 -08004450 ENTER_DEV(wdev->netdev);
4451
Anurag Chouhan6d760662016-02-20 16:05:43 +05304452 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004453 hdd_err("Command not allowed in FTM mode");
4454 return -EPERM;
4455 }
4456
4457 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304458 if (status)
4459 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460
4461 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4462 data, data_len,
4463 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004464 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004465 return -EINVAL;
4466 }
4467
4468 /* Parse and fetch ring id */
4469 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004470 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004471 return -EINVAL;
4472 }
4473
4474 ring_id = nla_get_u32(
4475 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4476
4477 if (ring_id == RING_ID_PER_PACKET_STATS) {
4478 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004479 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304480 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4481 /*
4482 * As part of DRIVER ring ID, flush both driver and fw logs.
4483 * For other Ring ID's driver doesn't have any rings to flush
4484 */
4485 hdd_notice("Bug report triggered by framework");
4486
4487 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4488 WLAN_LOG_INDICATOR_FRAMEWORK,
4489 WLAN_LOG_REASON_CODE_UNUSED,
4490 true, false);
4491 if (QDF_STATUS_SUCCESS != status) {
4492 hdd_err("Failed to trigger bug report");
4493 return -EINVAL;
4494 }
4495 } else {
4496 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4497 WLAN_LOG_INDICATOR_FRAMEWORK,
4498 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 return 0;
4501}
4502
4503/**
4504 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4505 * @wiphy: WIPHY structure pointer
4506 * @wdev: Wireless device structure pointer
4507 * @data: Pointer to the data received
4508 * @data_len: Length of the data received
4509 *
4510 * This function is used to flush or retrieve the per packet statistics from
4511 * the driver
4512 *
4513 * Return: 0 on success and errno on failure
4514 */
4515static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4516 struct wireless_dev *wdev,
4517 const void *data,
4518 int data_len)
4519{
4520 int ret = 0;
4521
4522 cds_ssr_protect(__func__);
4523 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4524 wdev, data, data_len);
4525 cds_ssr_unprotect(__func__);
4526
4527 return ret;
4528}
4529
4530#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4531/**
4532 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4533 * @hdd_ctx: HDD context
4534 * @request_id: [input] request id
4535 * @pattern_id: [output] pattern id
4536 *
4537 * This function loops through request id to pattern id array
4538 * if the slot is available, store the request id and return pattern id
4539 * if entry exists, return the pattern id
4540 *
4541 * Return: 0 on success and errno on failure
4542 */
4543static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4544 uint32_t request_id,
4545 uint8_t *pattern_id)
4546{
4547 uint32_t i;
4548
4549 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4550 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4551 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4552 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4553 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4554 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4555 return 0;
4556 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4557 request_id) {
4558 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4559 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4560 return 0;
4561 }
4562 }
4563 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4564 return -EINVAL;
4565}
4566
4567/**
4568 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4569 * @hdd_ctx: HDD context
4570 * @request_id: [input] request id
4571 * @pattern_id: [output] pattern id
4572 *
4573 * This function loops through request id to pattern id array
4574 * reset request id to 0 (slot available again) and
4575 * return pattern id
4576 *
4577 * Return: 0 on success and errno on failure
4578 */
4579static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4580 uint32_t request_id,
4581 uint8_t *pattern_id)
4582{
4583 uint32_t i;
4584
4585 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4586 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4587 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4588 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4589 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4590 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4591 return 0;
4592 }
4593 }
4594 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4595 return -EINVAL;
4596}
4597
4598
4599/*
4600 * define short names for the global vendor params
4601 * used by __wlan_hdd_cfg80211_offloaded_packets()
4602 */
4603#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4604#define PARAM_REQUEST_ID \
4605 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4606#define PARAM_CONTROL \
4607 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4608#define PARAM_IP_PACKET \
4609 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4610#define PARAM_SRC_MAC_ADDR \
4611 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4612#define PARAM_DST_MAC_ADDR \
4613 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4614#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4615
4616/**
4617 * wlan_hdd_add_tx_ptrn() - add tx pattern
4618 * @adapter: adapter pointer
4619 * @hdd_ctx: hdd context
4620 * @tb: nl attributes
4621 *
4622 * This function reads the NL attributes and forms a AddTxPtrn message
4623 * posts it to SME.
4624 *
4625 */
4626static int
4627wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4628 struct nlattr **tb)
4629{
4630 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304631 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004632 uint32_t request_id, ret, len;
4633 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304634 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004635 uint16_t eth_type = htons(ETH_P_IP);
4636
4637 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004638 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 return -ENOTSUPP;
4640 }
4641
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304642 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004643 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004644 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004645 return -ENOMEM;
4646 }
4647
4648 /* Parse and fetch request Id */
4649 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004650 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 goto fail;
4652 }
4653
4654 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4655 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004656 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004657 return -EINVAL;
4658 }
Jeff Johnson77848112016-06-29 14:52:06 -07004659 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660
4661 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004662 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 goto fail;
4664 }
4665 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004666 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004668 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 goto fail;
4670 }
4671
4672 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004673 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 goto fail;
4675 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004676 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304677 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004678 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004679 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680
Anurag Chouhanc5548422016-02-24 18:33:27 +05304681 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004682 &adapter->macAddressCurrent)) {
4683 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 goto fail;
4685 }
4686
4687 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004688 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689 goto fail;
4690 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304691 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004692 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 MAC_ADDR_ARRAY(dst_addr.bytes));
4694
4695 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004696 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 goto fail;
4698 }
4699 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004700 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701
4702 if (add_req->ucPtrnSize < 0 ||
4703 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4704 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004705 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 add_req->ucPtrnSize);
4707 goto fail;
4708 }
4709
4710 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304711 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304712 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304713 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304714 QDF_MAC_ADDR_SIZE);
4715 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304716 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 len += 2;
4718
4719 /*
4720 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4721 * ------------------------------------------------------------
4722 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4723 * ------------------------------------------------------------
4724 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304725 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 nla_data(tb[PARAM_IP_PACKET]),
4727 add_req->ucPtrnSize);
4728 add_req->ucPtrnSize += len;
4729
4730 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4731 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004732 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004733 goto fail;
4734 }
4735 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004736 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004737
4738 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304739 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004740 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741 goto fail;
4742 }
4743
4744 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304745 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 return 0;
4747
4748fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304749 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750 return -EINVAL;
4751}
4752
4753/**
4754 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4755 * @adapter: adapter pointer
4756 * @hdd_ctx: hdd context
4757 * @tb: nl attributes
4758 *
4759 * This function reads the NL attributes and forms a DelTxPtrn message
4760 * posts it to SME.
4761 *
4762 */
4763static int
4764wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4765 struct nlattr **tb)
4766{
4767 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304768 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004769 uint32_t request_id, ret;
4770 uint8_t pattern_id = 0;
4771
4772 /* Parse and fetch request Id */
4773 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004774 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775 return -EINVAL;
4776 }
4777 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4778 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004779 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004780 return -EINVAL;
4781 }
4782
4783 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4784 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004785 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 return -EINVAL;
4787 }
4788
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304789 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004790 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004791 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792 return -ENOMEM;
4793 }
4794
Anurag Chouhanc5548422016-02-24 18:33:27 +05304795 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004796 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004798 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004799 request_id, del_req->ucPtrnId);
4800
4801 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304802 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004803 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 goto fail;
4805 }
4806
4807 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304808 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004809 return 0;
4810
4811fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304812 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004813 return -EINVAL;
4814}
4815
4816
4817/**
4818 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4819 * @wiphy: Pointer to wireless phy
4820 * @wdev: Pointer to wireless device
4821 * @data: Pointer to data
4822 * @data_len: Data length
4823 *
4824 * Return: 0 on success, negative errno on failure
4825 */
4826static int
4827__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4828 struct wireless_dev *wdev,
4829 const void *data,
4830 int data_len)
4831{
4832 struct net_device *dev = wdev->netdev;
4833 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4834 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4835 struct nlattr *tb[PARAM_MAX + 1];
4836 uint8_t control;
4837 int ret;
4838 static const struct nla_policy policy[PARAM_MAX + 1] = {
4839 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4840 [PARAM_CONTROL] = { .type = NLA_U32 },
4841 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304842 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304844 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004845 [PARAM_PERIOD] = { .type = NLA_U32 },
4846 };
4847
Jeff Johnson1f61b612016-02-12 16:28:33 -08004848 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849
Anurag Chouhan6d760662016-02-20 16:05:43 +05304850 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851 hdd_err("Command not allowed in FTM mode");
4852 return -EPERM;
4853 }
4854
4855 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304856 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004857 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858
4859 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004860 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861 return -ENOTSUPP;
4862 }
4863
4864 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004865 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 return -EINVAL;
4867 }
4868
4869 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004870 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871 return -EINVAL;
4872 }
4873 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004874 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875
4876 if (control == WLAN_START_OFFLOADED_PACKETS)
4877 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4878 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4879 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4880 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004881 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004882 return -EINVAL;
4883 }
4884}
4885
4886/*
4887 * done with short names for the global vendor params
4888 * used by __wlan_hdd_cfg80211_offloaded_packets()
4889 */
4890#undef PARAM_MAX
4891#undef PARAM_REQUEST_ID
4892#undef PARAM_CONTROL
4893#undef PARAM_IP_PACKET
4894#undef PARAM_SRC_MAC_ADDR
4895#undef PARAM_DST_MAC_ADDR
4896#undef PARAM_PERIOD
4897
4898/**
4899 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4900 * @wiphy: wiphy structure pointer
4901 * @wdev: Wireless device structure pointer
4902 * @data: Pointer to the data received
4903 * @data_len: Length of @data
4904 *
4905 * Return: 0 on success; errno on failure
4906 */
4907static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4908 struct wireless_dev *wdev,
4909 const void *data,
4910 int data_len)
4911{
4912 int ret = 0;
4913
4914 cds_ssr_protect(__func__);
4915 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4916 wdev, data, data_len);
4917 cds_ssr_unprotect(__func__);
4918
4919 return ret;
4920}
4921#endif
4922
4923/*
4924 * define short names for the global vendor params
4925 * used by __wlan_hdd_cfg80211_monitor_rssi()
4926 */
4927#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4928#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4929#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4930#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4931#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4932
4933/**
4934 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4935 * @wiphy: Pointer to wireless phy
4936 * @wdev: Pointer to wireless device
4937 * @data: Pointer to data
4938 * @data_len: Data length
4939 *
4940 * Return: 0 on success, negative errno on failure
4941 */
4942static int
4943__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4944 struct wireless_dev *wdev,
4945 const void *data,
4946 int data_len)
4947{
4948 struct net_device *dev = wdev->netdev;
4949 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4950 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4951 struct nlattr *tb[PARAM_MAX + 1];
4952 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304953 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004954 int ret;
4955 uint32_t control;
4956 static const struct nla_policy policy[PARAM_MAX + 1] = {
4957 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4958 [PARAM_CONTROL] = { .type = NLA_U32 },
4959 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4960 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4961 };
4962
Jeff Johnson1f61b612016-02-12 16:28:33 -08004963 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004964
4965 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304966 if (ret)
4967 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004968
4969 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004970 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 return -ENOTSUPP;
4972 }
4973
4974 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004975 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 return -EINVAL;
4977 }
4978
4979 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004980 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981 return -EINVAL;
4982 }
4983
4984 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004985 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004986 return -EINVAL;
4987 }
4988
4989 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4990 req.session_id = adapter->sessionId;
4991 control = nla_get_u32(tb[PARAM_CONTROL]);
4992
4993 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4994 req.control = true;
4995 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004996 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997 return -EINVAL;
4998 }
4999
5000 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005001 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002 return -EINVAL;
5003 }
5004
5005 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5006 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5007
5008 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005009 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010 req.min_rssi, req.max_rssi);
5011 return -EINVAL;
5012 }
Jeff Johnson77848112016-06-29 14:52:06 -07005013 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014 req.min_rssi, req.max_rssi);
5015
5016 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5017 req.control = false;
5018 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005019 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020 return -EINVAL;
5021 }
Jeff Johnson77848112016-06-29 14:52:06 -07005022 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023 req.request_id, req.session_id, req.control);
5024
5025 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305026 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005027 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028 return -EINVAL;
5029 }
5030
5031 return 0;
5032}
5033
5034/*
5035 * done with short names for the global vendor params
5036 * used by __wlan_hdd_cfg80211_monitor_rssi()
5037 */
5038#undef PARAM_MAX
5039#undef PARAM_CONTROL
5040#undef PARAM_REQUEST_ID
5041#undef PARAM_MAX_RSSI
5042#undef PARAM_MIN_RSSI
5043
5044/**
5045 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5046 * @wiphy: wiphy structure pointer
5047 * @wdev: Wireless device structure pointer
5048 * @data: Pointer to the data received
5049 * @data_len: Length of @data
5050 *
5051 * Return: 0 on success; errno on failure
5052 */
5053static int
5054wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5055 const void *data, int data_len)
5056{
5057 int ret;
5058
5059 cds_ssr_protect(__func__);
5060 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5061 cds_ssr_unprotect(__func__);
5062
5063 return ret;
5064}
5065
5066/**
5067 * hdd_rssi_threshold_breached() - rssi breached NL event
5068 * @hddctx: HDD context
5069 * @data: rssi breached event data
5070 *
5071 * This function reads the rssi breached event %data and fill in the skb with
5072 * NL attributes and send up the NL event.
5073 *
5074 * Return: none
5075 */
5076void hdd_rssi_threshold_breached(void *hddctx,
5077 struct rssi_breach_event *data)
5078{
5079 hdd_context_t *hdd_ctx = hddctx;
5080 struct sk_buff *skb;
5081
5082 ENTER();
5083
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305084 if (wlan_hdd_validate_context(hdd_ctx))
5085 return;
5086 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005087 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005088 return;
5089 }
5090
5091 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5092 NULL,
5093 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5094 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5095 GFP_KERNEL);
5096
5097 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005098 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099 return;
5100 }
5101
Jeff Johnson77848112016-06-29 14:52:06 -07005102 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005103 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005104 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005105 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5106
5107 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5108 data->request_id) ||
5109 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5110 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5111 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5112 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005113 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005114 goto fail;
5115 }
5116
5117 cfg80211_vendor_event(skb, GFP_KERNEL);
5118 return;
5119
5120fail:
5121 kfree_skb(skb);
5122 return;
5123}
5124
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305125static const struct nla_policy
5126ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5127 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5128};
5129
5130/**
5131 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5132 * @wiphy: Pointer to wireless phy
5133 * @wdev: Pointer to wireless device
5134 * @data: Pointer to data
5135 * @data_len: Length of @data
5136 *
5137 * Return: 0 on success, negative errno on failure
5138 */
5139static int
5140__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5141 struct wireless_dev *wdev,
5142 const void *data, int data_len)
5143{
5144 int status;
5145 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5146 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005147 struct net_device *dev = wdev->netdev;
5148 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305149
5150 ENTER_DEV(wdev->netdev);
5151
5152 status = wlan_hdd_validate_context(pHddCtx);
5153 if (0 != status)
5154 return status;
5155 if (!pHddCtx->config->fhostNSOffload) {
5156 hdd_err("ND Offload not supported");
5157 return -EINVAL;
5158 }
5159
5160 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5161 (struct nlattr *)data,
5162 data_len, ns_offload_set_policy)) {
5163 hdd_err("nla_parse failed");
5164 return -EINVAL;
5165 }
5166
5167 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5168 hdd_err("ND Offload flag attribute not present");
5169 return -EINVAL;
5170 }
5171
5172 pHddCtx->ns_offload_enable =
5173 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5174
Dustin Brownd8279d22016-09-07 14:52:57 -07005175 /* update ns offload in case it is already enabled/disabled */
5176 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5177
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305178 return 0;
5179}
5180
5181/**
5182 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5183 * @wiphy: pointer to wireless wiphy structure.
5184 * @wdev: pointer to wireless_dev structure.
5185 * @data: Pointer to the data to be passed via vendor interface
5186 * @data_len:Length of the data to be passed
5187 *
5188 * Return: Return the Success or Failure code.
5189 */
5190static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5191 struct wireless_dev *wdev,
5192 const void *data, int data_len)
5193{
5194 int ret;
5195
5196 cds_ssr_protect(__func__);
5197 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5198 cds_ssr_unprotect(__func__);
5199
5200 return ret;
5201}
5202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5204 * @wiphy: Pointer to wireless phy
5205 * @wdev: Pointer to wireless device
5206 * @data: Pointer to data
5207 * @data_len: Data length
5208 *
5209 * This function return the preferred frequency list generated by the policy
5210 * manager.
5211 *
5212 * Return: success or failure code
5213 */
5214static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5215 struct wireless_dev
5216 *wdev, const void *data,
5217 int data_len)
5218{
5219 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5220 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305221 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305222 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305224 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225 enum cds_con_mode intf_mode;
5226 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5227 struct sk_buff *reply_skb;
5228
Jeff Johnson1f61b612016-02-12 16:28:33 -08005229 ENTER_DEV(wdev->netdev);
5230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 ret = wlan_hdd_validate_context(hdd_ctx);
5232 if (ret)
5233 return -EINVAL;
5234
5235 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5236 data, data_len, NULL)) {
5237 hdd_err("Invalid ATTR");
5238 return -EINVAL;
5239 }
5240
5241 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5242 hdd_err("attr interface type failed");
5243 return -EINVAL;
5244 }
5245
5246 intf_mode = nla_get_u32(tb
5247 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5248
5249 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5250 hdd_err("Invalid interface type");
5251 return -EINVAL;
5252 }
5253
5254 hdd_debug("Userspace requested pref freq list");
5255
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305256 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5257 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305258 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 hdd_err("Get pcl failed");
5260 return -EINVAL;
5261 }
5262
5263 /* convert channel number to frequency */
5264 for (i = 0; i < pcl_len; i++) {
5265 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5266 freq_list[i] =
5267 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005268 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005269 else
5270 freq_list[i] =
5271 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005272 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005273 }
5274
5275 /* send the freq_list back to supplicant */
5276 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5277 sizeof(u32) *
5278 pcl_len +
5279 NLMSG_HDRLEN);
5280
5281 if (!reply_skb) {
5282 hdd_err("Allocate reply_skb failed");
5283 return -EINVAL;
5284 }
5285
5286 if (nla_put_u32(reply_skb,
5287 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5288 intf_mode) ||
5289 nla_put(reply_skb,
5290 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5291 sizeof(uint32_t) * pcl_len,
5292 freq_list)) {
5293 hdd_err("nla put fail");
5294 kfree_skb(reply_skb);
5295 return -EINVAL;
5296 }
5297
5298 return cfg80211_vendor_cmd_reply(reply_skb);
5299}
5300
5301/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5302 * @wiphy: Pointer to wireless phy
5303 * @wdev: Pointer to wireless device
5304 * @data: Pointer to data
5305 * @data_len: Data length
5306 *
5307 * This function return the preferred frequency list generated by the policy
5308 * manager.
5309 *
5310 * Return: success or failure code
5311 */
5312static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5313 struct wireless_dev
5314 *wdev, const void *data,
5315 int data_len)
5316{
5317 int ret = 0;
5318
5319 cds_ssr_protect(__func__);
5320 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5321 data, data_len);
5322 cds_ssr_unprotect(__func__);
5323
5324 return ret;
5325}
5326
5327/**
5328 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5329 * @wiphy: Pointer to wireless phy
5330 * @wdev: Pointer to wireless device
5331 * @data: Pointer to data
5332 * @data_len: Data length
5333 *
5334 * Return: 0 on success, negative errno on failure
5335 */
5336static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5337 struct wireless_dev *wdev,
5338 const void *data,
5339 int data_len)
5340{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305341 struct net_device *ndev = wdev->netdev;
5342 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5344 int ret = 0;
5345 enum cds_con_mode intf_mode;
5346 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5347 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348
Jeff Johnson1f61b612016-02-12 16:28:33 -08005349 ENTER_DEV(ndev);
5350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 ret = wlan_hdd_validate_context(hdd_ctx);
5352 if (ret)
5353 return ret;
5354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5356 data, data_len, NULL)) {
5357 hdd_err("Invalid ATTR");
5358 return -EINVAL;
5359 }
5360
5361 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5362 hdd_err("attr interface type failed");
5363 return -EINVAL;
5364 }
5365
5366 intf_mode = nla_get_u32(tb
5367 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5368
5369 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5370 hdd_err("Invalid interface type");
5371 return -EINVAL;
5372 }
5373
5374 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5375 hdd_err("attr probable freq failed");
5376 return -EINVAL;
5377 }
5378
5379 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5380 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5381
5382 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005383 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005384 channel_hint, HW_MODE_20_MHZ)) {
5385 hdd_err("Set channel hint failed due to concurrency check");
5386 return -EINVAL;
5387 }
5388
Krunal Soni09e55032016-06-07 10:06:55 -07005389 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5390 hdd_warn("Remain On Channel Pending");
5391
Krunal Soni3091bcc2016-06-23 12:28:21 -07005392 ret = qdf_reset_connection_update();
5393 if (!QDF_IS_STATUS_SUCCESS(ret))
5394 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395
Krunal Soni3091bcc2016-06-23 12:28:21 -07005396 ret = cds_current_connections_update(adapter->sessionId,
5397 channel_hint,
5398 SIR_UPDATE_REASON_SET_OPER_CHAN);
5399 if (QDF_STATUS_E_FAILURE == ret) {
5400 /* return in the failure case */
5401 hdd_err("ERROR: connections update failed!!");
5402 return -EINVAL;
5403 }
5404
5405 if (QDF_STATUS_SUCCESS == ret) {
5406 /*
5407 * Success is the only case for which we expect hw mode
5408 * change to take place, hence we need to wait.
5409 * For any other return value it should be a pass
5410 * through
5411 */
5412 ret = qdf_wait_for_connection_update();
5413 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5414 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 return -EINVAL;
5416 }
5417
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 }
5419
5420 return 0;
5421}
5422
5423/**
5424 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5425 * @wiphy: Pointer to wireless phy
5426 * @wdev: Pointer to wireless device
5427 * @data: Pointer to data
5428 * @data_len: Data length
5429 *
5430 * Return: 0 on success, negative errno on failure
5431 */
5432static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5433 struct wireless_dev *wdev,
5434 const void *data,
5435 int data_len)
5436{
5437 int ret = 0;
5438
5439 cds_ssr_protect(__func__);
5440 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5441 data, data_len);
5442 cds_ssr_unprotect(__func__);
5443
5444 return ret;
5445}
5446
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305447static const struct
5448nla_policy
5449qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5450 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5451};
5452
5453/**
5454 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5455 * @wiphy: WIPHY structure pointer
5456 * @wdev: Wireless device structure pointer
5457 * @data: Pointer to the data received
5458 * @data_len: Length of the data received
5459 *
5460 * This function is used to get link properties like nss, rate flags and
5461 * operating frequency for the active connection with the given peer.
5462 *
5463 * Return: 0 on success and errno on failure
5464 */
5465static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5466 struct wireless_dev *wdev,
5467 const void *data,
5468 int data_len)
5469{
5470 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5471 struct net_device *dev = wdev->netdev;
5472 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5473 hdd_station_ctx_t *hdd_sta_ctx;
5474 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305475 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305476 uint32_t sta_id;
5477 struct sk_buff *reply_skb;
5478 uint32_t rate_flags = 0;
5479 uint8_t nss;
5480 uint8_t final_rate_flags = 0;
5481 uint32_t freq;
5482
Jeff Johnson1f61b612016-02-12 16:28:33 -08005483 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305484
Anurag Chouhan6d760662016-02-20 16:05:43 +05305485 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305486 hdd_err("Command not allowed in FTM mode");
5487 return -EPERM;
5488 }
5489
5490 if (0 != wlan_hdd_validate_context(hdd_ctx))
5491 return -EINVAL;
5492
5493 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5494 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005495 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305496 return -EINVAL;
5497 }
5498
5499 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005500 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305501 adapter->device_mode);
5502 return -EINVAL;
5503 }
5504
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305505 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305506 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005507 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305508 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5509
Krunal Sonib4326f22016-03-10 13:05:51 -08005510 if (adapter->device_mode == QDF_STA_MODE ||
5511 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305512 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5513 if ((hdd_sta_ctx->conn_info.connState !=
5514 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305515 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305516 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005517 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305518 MAC_ADDR_ARRAY(peer_mac));
5519 return -EINVAL;
5520 }
5521
5522 nss = hdd_sta_ctx->conn_info.nss;
5523 freq = cds_chan_to_freq(
5524 hdd_sta_ctx->conn_info.operationChannel);
5525 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005526 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5527 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305528
5529 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5530 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305531 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305532 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305533 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305534 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305535 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305536 break;
5537 }
5538
5539 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005540 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305541 MAC_ADDR_ARRAY(peer_mac));
5542 return -EINVAL;
5543 }
5544
5545 nss = adapter->aStaInfo[sta_id].nss;
5546 freq = cds_chan_to_freq(
5547 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5548 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5549 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005550 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305551 MAC_ADDR_ARRAY(peer_mac));
5552 return -EINVAL;
5553 }
5554
5555 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5556 if (rate_flags & eHAL_TX_RATE_VHT80) {
5557 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005558#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305559 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005560#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305561 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5562 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005563#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305564 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005565#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305566 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5567 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5568 } else if (rate_flags &
5569 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5570 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005571#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305572 if (rate_flags & eHAL_TX_RATE_HT40)
5573 final_rate_flags |=
5574 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005575#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305576 }
5577
5578 if (rate_flags & eHAL_TX_RATE_SGI) {
5579 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5580 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5581 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5582 }
5583 }
5584
5585 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5586 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5587
5588 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005589 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305590 return -EINVAL;
5591 }
5592
5593 if (nla_put_u8(reply_skb,
5594 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5595 nss) ||
5596 nla_put_u8(reply_skb,
5597 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5598 final_rate_flags) ||
5599 nla_put_u32(reply_skb,
5600 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5601 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005602 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305603 kfree_skb(reply_skb);
5604 return -EINVAL;
5605 }
5606
5607 return cfg80211_vendor_cmd_reply(reply_skb);
5608}
5609
5610/**
5611 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5612 * properties.
5613 * @wiphy: WIPHY structure pointer
5614 * @wdev: Wireless device structure pointer
5615 * @data: Pointer to the data received
5616 * @data_len: Length of the data received
5617 *
5618 * This function is used to get link properties like nss, rate flags and
5619 * operating frequency for the active connection with the given peer.
5620 *
5621 * Return: 0 on success and errno on failure
5622 */
5623static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5624 struct wireless_dev *wdev,
5625 const void *data,
5626 int data_len)
5627{
5628 int ret = 0;
5629
5630 cds_ssr_protect(__func__);
5631 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5632 wdev, data, data_len);
5633 cds_ssr_unprotect(__func__);
5634
5635 return ret;
5636}
5637
Peng Xu278d0122015-09-24 16:34:17 -07005638static const struct
5639nla_policy
5640qca_wlan_vendor_ota_test_policy
5641[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5642 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5643};
5644
5645/**
5646 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5647 * @wiphy: Pointer to wireless phy
5648 * @wdev: Pointer to wireless device
5649 * @data: Pointer to data
5650 * @data_len: Data length
5651 *
5652 * Return: 0 on success, negative errno on failure
5653 */
5654static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5655 struct wireless_dev *wdev,
5656 const void *data,
5657 int data_len)
5658{
5659 struct net_device *dev = wdev->netdev;
5660 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5661 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5662 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5663 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5664 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305665 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005666 uint32_t current_roam_state;
5667
Jeff Johnson1f61b612016-02-12 16:28:33 -08005668 ENTER_DEV(dev);
5669
Anurag Chouhan6d760662016-02-20 16:05:43 +05305670 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005671 hdd_err("Command not allowed in FTM mode");
5672 return -EPERM;
5673 }
5674
5675 if (0 != wlan_hdd_validate_context(hdd_ctx))
5676 return -EINVAL;
5677
5678 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5679 data, data_len,
5680 qca_wlan_vendor_ota_test_policy)) {
5681 hdd_err("invalid attr");
5682 return -EINVAL;
5683 }
5684
5685 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5686 hdd_err("attr ota test failed");
5687 return -EINVAL;
5688 }
5689
5690 ota_enable = nla_get_u8(
5691 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5692
5693 hdd_info(" OTA test enable = %d", ota_enable);
5694 if (ota_enable != 1) {
5695 hdd_err("Invalid value, only enable test mode is supported!");
5696 return -EINVAL;
5697 }
5698
5699 current_roam_state =
5700 sme_get_current_roam_state(hal, adapter->sessionId);
5701 status = sme_stop_roaming(hal, adapter->sessionId,
5702 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305703 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005704 hdd_err("Enable/Disable roaming failed");
5705 return -EINVAL;
5706 }
5707
5708 status = sme_ps_enable_disable(hal, adapter->sessionId,
5709 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305710 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005711 hdd_err("Enable/Disable power save failed");
5712 /* restore previous roaming setting */
5713 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5714 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5715 status = sme_start_roaming(hal, adapter->sessionId,
5716 eCsrHddIssued);
5717 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5718 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5719 status = sme_stop_roaming(hal, adapter->sessionId,
5720 eCsrHddIssued);
5721
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305722 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005723 hdd_err("Restoring roaming state failed");
5724
5725 return -EINVAL;
5726 }
5727
5728
5729 return 0;
5730}
5731
5732/**
5733 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5734 * @wiphy: Pointer to wireless phy
5735 * @wdev: Pointer to wireless device
5736 * @data: Pointer to data
5737 * @data_len: Data length
5738 *
5739 * Return: 0 on success, negative errno on failure
5740 */
5741static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5742 struct wireless_dev *wdev,
5743 const void *data,
5744 int data_len)
5745{
5746 int ret = 0;
5747
5748 cds_ssr_protect(__func__);
5749 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5750 cds_ssr_unprotect(__func__);
5751
5752 return ret;
5753}
5754
Peng Xu4d67c8f2015-10-16 16:02:26 -07005755/**
5756 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5757 * @wiphy: Pointer to wireless phy
5758 * @wdev: Pointer to wireless device
5759 * @data: Pointer to data
5760 * @data_len: Data length
5761 *
5762 * Return: 0 on success, negative errno on failure
5763 */
5764static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5765 struct wireless_dev *wdev,
5766 const void *data,
5767 int data_len)
5768{
5769 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5770 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005771 hdd_adapter_t *adapter;
5772 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005773 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5774 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005775 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005776
Jeff Johnson1f61b612016-02-12 16:28:33 -08005777 ENTER_DEV(dev);
5778
Peng Xu4d67c8f2015-10-16 16:02:26 -07005779 ret = wlan_hdd_validate_context(hdd_ctx);
5780 if (ret)
5781 return ret;
5782
5783 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5784
5785 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5786 data, data_len, NULL)) {
5787 hdd_err("Invalid ATTR");
5788 return -EINVAL;
5789 }
5790
5791 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5792 hdd_err("attr tx power scale failed");
5793 return -EINVAL;
5794 }
5795
5796 scale_value = nla_get_u8(tb
5797 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5798
5799 if (scale_value > MAX_TXPOWER_SCALE) {
5800 hdd_err("Invalid tx power scale level");
5801 return -EINVAL;
5802 }
5803
Peng Xu62c8c432016-05-09 15:23:02 -07005804 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005805
Peng Xu62c8c432016-05-09 15:23:02 -07005806 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005807 hdd_err("Set tx power scale failed");
5808 return -EINVAL;
5809 }
5810
5811 return 0;
5812}
5813
5814/**
5815 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5816 * @wiphy: Pointer to wireless phy
5817 * @wdev: Pointer to wireless device
5818 * @data: Pointer to data
5819 * @data_len: Data length
5820 *
5821 * Return: 0 on success, negative errno on failure
5822 */
5823static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5824 struct wireless_dev *wdev,
5825 const void *data,
5826 int data_len)
5827{
Peng Xu62c8c432016-05-09 15:23:02 -07005828 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005829
5830 cds_ssr_protect(__func__);
5831 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5832 data, data_len);
5833 cds_ssr_unprotect(__func__);
5834
5835 return ret;
5836}
5837
5838/**
5839 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5840 * @wiphy: Pointer to wireless phy
5841 * @wdev: Pointer to wireless device
5842 * @data: Pointer to data
5843 * @data_len: Data length
5844 *
5845 * Return: 0 on success, negative errno on failure
5846 */
5847static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5848 struct wireless_dev *wdev,
5849 const void *data,
5850 int data_len)
5851{
5852 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5853 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005854 hdd_adapter_t *adapter;
5855 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005856 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5857 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005858 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005859
Jeff Johnson1f61b612016-02-12 16:28:33 -08005860 ENTER_DEV(dev);
5861
Peng Xu4d67c8f2015-10-16 16:02:26 -07005862 ret = wlan_hdd_validate_context(hdd_ctx);
5863 if (ret)
5864 return ret;
5865
5866 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5867
5868 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5869 data, data_len, NULL)) {
5870 hdd_err("Invalid ATTR");
5871 return -EINVAL;
5872 }
5873
5874 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5875 hdd_err("attr tx power decrease db value failed");
5876 return -EINVAL;
5877 }
5878
5879 scale_value = nla_get_u8(tb
5880 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5881
Peng Xu62c8c432016-05-09 15:23:02 -07005882 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5883 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005884
Peng Xu62c8c432016-05-09 15:23:02 -07005885 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005886 hdd_err("Set tx power decrease db failed");
5887 return -EINVAL;
5888 }
5889
5890 return 0;
5891}
5892
5893/**
5894 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5895 * @wiphy: Pointer to wireless phy
5896 * @wdev: Pointer to wireless device
5897 * @data: Pointer to data
5898 * @data_len: Data length
5899 *
5900 * Return: 0 on success, negative errno on failure
5901 */
5902static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5903 struct wireless_dev *wdev,
5904 const void *data,
5905 int data_len)
5906{
Peng Xu62c8c432016-05-09 15:23:02 -07005907 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005908
5909 cds_ssr_protect(__func__);
5910 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5911 data, data_len);
5912 cds_ssr_unprotect(__func__);
5913
5914 return ret;
5915}
Peng Xu8fdaa492016-06-22 10:20:47 -07005916
5917/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305918 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5919 * @wiphy: Pointer to wireless phy
5920 * @wdev: Pointer to wireless device
5921 * @data: Pointer to data
5922 * @data_len: Data length
5923 *
5924 * Processes the conditional channel switch request and invokes the helper
5925 * APIs to process the channel switch request.
5926 *
5927 * Return: 0 on success, negative errno on failure
5928 */
5929static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5930 struct wireless_dev *wdev,
5931 const void *data,
5932 int data_len)
5933{
5934 int ret;
5935 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5936 struct net_device *dev = wdev->netdev;
5937 hdd_adapter_t *adapter;
5938 struct nlattr
5939 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5940 uint32_t freq_len, i;
5941 uint32_t *freq;
5942 uint8_t chans[QDF_MAX_NUM_CHAN];
5943
5944 ENTER_DEV(dev);
5945
5946 ret = wlan_hdd_validate_context(hdd_ctx);
5947 if (ret)
5948 return ret;
5949
5950 if (!hdd_ctx->config->enableDFSMasterCap) {
5951 hdd_err("DFS master capability is not present in the driver");
5952 return -EINVAL;
5953 }
5954
5955 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5956 hdd_err("Command not allowed in FTM mode");
5957 return -EPERM;
5958 }
5959
5960 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5961 if (adapter->device_mode != QDF_SAP_MODE) {
5962 hdd_err("Invalid device mode %d", adapter->device_mode);
5963 return -EINVAL;
5964 }
5965
5966 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5967 data, data_len, NULL)) {
5968 hdd_err("Invalid ATTR");
5969 return -EINVAL;
5970 }
5971
5972 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5973 hdd_err("Frequency list is missing");
5974 return -EINVAL;
5975 }
5976
5977 freq_len = nla_len(
5978 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5979 sizeof(uint32_t);
5980
5981 if (freq_len > QDF_MAX_NUM_CHAN) {
5982 hdd_err("insufficient space to hold channels");
5983 return -ENOMEM;
5984 }
5985
5986 hdd_debug("freq_len=%d", freq_len);
5987
5988 freq = nla_data(
5989 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5990
5991
5992 for (i = 0; i < freq_len; i++) {
5993 if (freq[i] == 0)
5994 chans[i] = 0;
5995 else
5996 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5997
5998 hdd_debug("freq[%d]=%d", i, freq[i]);
5999 }
6000
6001 /*
6002 * The input frequency list from user space is designed to be a
6003 * priority based frequency list. This is only to accommodate any
6004 * future request. But, current requirement is only to perform CAC
6005 * on a single channel. So, the first entry from the list is picked.
6006 *
6007 * If channel is zero, any channel in the available outdoor regulatory
6008 * domain will be selected.
6009 */
6010 ret = wlan_hdd_request_pre_cac(chans[0]);
6011 if (ret) {
6012 hdd_err("pre cac request failed with reason:%d", ret);
6013 return ret;
6014 }
6015
6016 return 0;
6017}
6018
6019/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006020 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6021 * @wiphy: Pointer to wireless phy
6022 * @wdev: Pointer to wireless device
6023 * @data: Pointer to data
6024 * @data_len: Data length
6025 *
6026 * This function is to process the p2p listen offload start vendor
6027 * command. It parses the input parameters and invoke WMA API to
6028 * send the command to firmware.
6029 *
6030 * Return: 0 on success, negative errno on failure
6031 */
6032static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6033 struct wireless_dev *wdev,
6034 const void *data,
6035 int data_len)
6036{
6037 int ret;
6038 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6039 struct net_device *dev = wdev->netdev;
6040 hdd_adapter_t *adapter;
6041 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6042 struct sir_p2p_lo_start params;
6043 QDF_STATUS status;
6044
6045 ENTER_DEV(dev);
6046
6047 ret = wlan_hdd_validate_context(hdd_ctx);
6048 if (ret)
6049 return ret;
6050
6051 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6052 hdd_err("Command not allowed in FTM mode");
6053 return -EPERM;
6054 }
6055
6056 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6057 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6058 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6059 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6060 hdd_err("Invalid device mode %d", adapter->device_mode);
6061 return -EINVAL;
6062 }
6063
6064 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6065 data, data_len, NULL)) {
6066 hdd_err("Invalid ATTR");
6067 return -EINVAL;
6068 }
6069
6070 memset(&params, 0, sizeof(params));
6071
6072 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6073 params.ctl_flags = 1; /* set to default value */
6074 else
6075 params.ctl_flags = nla_get_u32(tb
6076 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6077
6078 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6079 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6080 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6081 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6082 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6083 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6084 hdd_err("Attribute parsing failed");
6085 return -EINVAL;
6086 }
6087
6088 params.vdev_id = adapter->sessionId;
6089 params.freq = nla_get_u32(tb
6090 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6091 if ((params.freq != 2412) && (params.freq != 2437) &&
6092 (params.freq != 2462)) {
6093 hdd_err("Invalid listening channel: %d", params.freq);
6094 return -EINVAL;
6095 }
6096
6097 params.period = nla_get_u32(tb
6098 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6099 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6100 hdd_err("Invalid period: %d", params.period);
6101 return -EINVAL;
6102 }
6103
6104 params.interval = nla_get_u32(tb
6105 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6106 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6107 hdd_err("Invalid interval: %d", params.interval);
6108 return -EINVAL;
6109 }
6110
6111 params.count = nla_get_u32(tb
6112 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6113 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6114 hdd_err("Invalid count: %d", params.count);
6115 return -EINVAL;
6116 }
6117
6118 params.device_types = nla_data(tb
6119 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6120 if (params.device_types == NULL) {
6121 hdd_err("Invalid device types");
6122 return -EINVAL;
6123 }
6124
6125 params.dev_types_len = nla_len(tb
6126 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6127 if (params.dev_types_len < 8) {
6128 hdd_err("Invalid device type length: %d", params.dev_types_len);
6129 return -EINVAL;
6130 }
6131
6132 params.probe_resp_tmplt = nla_data(tb
6133 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6134 if (params.probe_resp_tmplt == NULL) {
6135 hdd_err("Invalid probe response template");
6136 return -EINVAL;
6137 }
6138
6139 params.probe_resp_len = nla_len(tb
6140 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6141 if (params.probe_resp_len == 0) {
6142 hdd_err("Invalid probe resp template length: %d",
6143 params.probe_resp_len);
6144 return -EINVAL;
6145 }
6146
6147 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6148 params.freq, params.period, params.interval, params.count);
6149
6150 status = wma_p2p_lo_start(&params);
6151
6152 if (!QDF_IS_STATUS_SUCCESS(status)) {
6153 hdd_err("P2P LO start failed");
6154 return -EINVAL;
6155 }
6156
6157 return 0;
6158}
6159
6160
6161/**
6162 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6163 * @wiphy: Pointer to wireless phy
6164 * @wdev: Pointer to wireless device
6165 * @data: Pointer to data
6166 * @data_len: Data length
6167 *
6168 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6169 * to process p2p listen offload start vendor command.
6170 *
6171 * Return: 0 on success, negative errno on failure
6172 */
6173static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6174 struct wireless_dev *wdev,
6175 const void *data,
6176 int data_len)
6177{
6178 int ret = 0;
6179
6180 cds_ssr_protect(__func__);
6181 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6182 data, data_len);
6183 cds_ssr_unprotect(__func__);
6184
6185 return ret;
6186}
6187
6188/**
6189 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6190 * @wiphy: Pointer to wireless phy
6191 * @wdev: Pointer to wireless device
6192 * @data: Pointer to data
6193 * @data_len: Data length
6194 *
6195 * This function is to process the p2p listen offload stop vendor
6196 * command. It invokes WMA API to send command to firmware.
6197 *
6198 * Return: 0 on success, negative errno on failure
6199 */
6200static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6201 struct wireless_dev *wdev,
6202 const void *data,
6203 int data_len)
6204{
6205 QDF_STATUS status;
6206 hdd_adapter_t *adapter;
6207 struct net_device *dev = wdev->netdev;
6208
6209 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6210 hdd_err("Command not allowed in FTM mode");
6211 return -EPERM;
6212 }
6213
6214 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6215 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6216 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6217 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6218 hdd_err("Invalid device mode");
6219 return -EINVAL;
6220 }
6221
6222 status = wma_p2p_lo_stop(adapter->sessionId);
6223
6224 if (!QDF_IS_STATUS_SUCCESS(status)) {
6225 hdd_err("P2P LO stop failed");
6226 return -EINVAL;
6227 }
6228
6229 return 0;
6230}
6231
6232/**
6233 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6234 * @wiphy: Pointer to wireless phy
6235 * @wdev: Pointer to wireless device
6236 * @data: Pointer to data
6237 * @data_len: Data length
6238 *
6239 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6240 * to process p2p listen offload stop vendor command.
6241 *
6242 * Return: 0 on success, negative errno on failure
6243 */
6244static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6245 struct wireless_dev *wdev,
6246 const void *data,
6247 int data_len)
6248{
6249 int ret = 0;
6250
6251 cds_ssr_protect(__func__);
6252 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6253 data, data_len);
6254 cds_ssr_unprotect(__func__);
6255
6256 return ret;
6257}
6258
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306259/**
6260 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6261 * @wiphy: Pointer to wireless phy
6262 * @wdev: Pointer to wireless device
6263 * @data: Pointer to data
6264 * @data_len: Data length
6265 *
6266 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6267 * to process the conditional channel switch request.
6268 *
6269 * Return: 0 on success, negative errno on failure
6270 */
6271static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6272 struct wireless_dev *wdev,
6273 const void *data,
6274 int data_len)
6275{
6276 int ret;
6277
6278 cds_ssr_protect(__func__);
6279 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6280 data, data_len);
6281 cds_ssr_unprotect(__func__);
6282
6283 return ret;
6284}
6285
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306286/*
6287 * define short names for the global vendor params
6288 * used by __wlan_hdd_cfg80211_bpf_offload()
6289 */
6290#define BPF_INVALID \
6291 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6292#define BPF_SET_RESET \
6293 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6294#define BPF_VERSION \
6295 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6296#define BPF_FILTER_ID \
6297 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6298#define BPF_PACKET_SIZE \
6299 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6300#define BPF_CURRENT_OFFSET \
6301 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6302#define BPF_PROGRAM \
6303 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6304#define BPF_MAX \
6305 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006306
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306307static const struct nla_policy
6308wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6309 [BPF_SET_RESET] = {.type = NLA_U32},
6310 [BPF_VERSION] = {.type = NLA_U32},
6311 [BPF_FILTER_ID] = {.type = NLA_U32},
6312 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6313 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6314 [BPF_PROGRAM] = {.type = NLA_U8},
6315};
6316
6317/**
6318 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6319 * @hdd_context: hdd_context
6320 * @bpf_get_offload: struct for get offload
6321 *
6322 * This function receives the response/data from the lower layer and
6323 * checks to see if the thread is still waiting then post the results to
6324 * upper layer, if the request has timed out then ignore.
6325 *
6326 * Return: None
6327 */
6328void hdd_get_bpf_offload_cb(void *hdd_context,
6329 struct sir_bpf_get_offload *data)
6330{
6331 hdd_context_t *hdd_ctx = hdd_context;
6332 struct hdd_bpf_context *context;
6333
6334 ENTER();
6335
6336 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006337 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306338 data);
6339 return;
6340 }
6341
6342 spin_lock(&hdd_context_lock);
6343
6344 context = &bpf_context;
6345 /* The caller presumably timed out so there is nothing we can do */
6346 if (context->magic != BPF_CONTEXT_MAGIC) {
6347 spin_unlock(&hdd_context_lock);
6348 return;
6349 }
6350
6351 /* context is valid so caller is still waiting */
6352 /* paranoia: invalidate the magic */
6353 context->magic = 0;
6354
6355 context->capability_response = *data;
6356 complete(&context->completion);
6357
6358 spin_unlock(&hdd_context_lock);
6359
6360 return;
6361}
6362
6363/**
6364 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6365 * @hdd_context: hdd_context
6366 * @bpf_get_offload: struct for get offload
6367 *
6368 * Return: 0 on success, error number otherwise.
6369 */
6370static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6371 struct sir_bpf_get_offload *bpf_get_offload)
6372{
6373 struct sk_buff *skb;
6374 uint32_t nl_buf_len;
6375
6376 ENTER();
6377
6378 nl_buf_len = NLMSG_HDRLEN;
6379 nl_buf_len +=
6380 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6381 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6382
6383 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6384 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006385 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306386 return -ENOMEM;
6387 }
6388
Jeff Johnson77848112016-06-29 14:52:06 -07006389 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306390 bpf_get_offload->bpf_version,
6391 bpf_get_offload->max_bytes_for_bpf_inst);
6392
6393 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6394 bpf_get_offload->max_bytes_for_bpf_inst) ||
6395 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006396 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306397 goto nla_put_failure;
6398 }
6399
6400 cfg80211_vendor_cmd_reply(skb);
6401 EXIT();
6402 return 0;
6403
6404nla_put_failure:
6405 kfree_skb(skb);
6406 return -EINVAL;
6407}
6408
6409/**
6410 * hdd_get_bpf_offload - Get BPF offload Capabilities
6411 * @hdd_ctx: Hdd context
6412 *
6413 * Return: 0 on success, errno on failure
6414 */
6415static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6416{
6417 unsigned long rc;
6418 struct hdd_bpf_context *context;
6419 QDF_STATUS status;
6420 int ret;
6421
6422 ENTER();
6423
6424 spin_lock(&hdd_context_lock);
6425 context = &bpf_context;
6426 context->magic = BPF_CONTEXT_MAGIC;
6427 INIT_COMPLETION(context->completion);
6428 spin_unlock(&hdd_context_lock);
6429
6430 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6431 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006432 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306433 return -EINVAL;
6434 }
6435 /* request was sent -- wait for the response */
6436 rc = wait_for_completion_timeout(&context->completion,
6437 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6438 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006439 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306440 spin_lock(&hdd_context_lock);
6441 context->magic = 0;
6442 spin_unlock(&hdd_context_lock);
6443
6444 return -ETIMEDOUT;
6445 }
6446 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6447 &bpf_context.capability_response);
6448 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006449 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306450
6451 EXIT();
6452 return ret;
6453}
6454
6455/**
6456 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6457 * @hdd_ctx: Hdd context
6458 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306459 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306460 *
6461 * Return: 0 on success; errno on failure
6462 */
6463static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6464 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306465 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306466{
6467 struct sir_bpf_set_offload *bpf_set_offload;
6468 QDF_STATUS status;
6469 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306470 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306471
6472 ENTER();
6473
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306474 if (adapter->device_mode == QDF_STA_MODE ||
6475 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6476 if (!hdd_conn_is_connected(
6477 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6478 hdd_err("Not in Connected state!");
6479 return -ENOTSUPP;
6480 }
6481 }
6482
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306483 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6484 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006485 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306486 return -ENOMEM;
6487 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306488
6489 /* Parse and fetch bpf packet size */
6490 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006491 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306492 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306493 goto fail;
6494 }
6495 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6496
6497 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006498 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306499 goto post_sme;
6500 }
6501
6502 /* Parse and fetch bpf program */
6503 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006504 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306505 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306506 goto fail;
6507 }
6508
6509 prog_len = nla_len(tb[BPF_PROGRAM]);
6510 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306511
6512 if (bpf_set_offload->program == NULL) {
6513 hdd_err("qdf_mem_malloc failed for bpf offload program");
6514 ret = -ENOMEM;
6515 goto fail;
6516 }
6517
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306518 bpf_set_offload->current_length = prog_len;
6519 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306520 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306521
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306522 hdd_info("BPF set instructions");
6523 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6524 bpf_set_offload->program, prog_len);
6525
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306526 /* Parse and fetch filter Id */
6527 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006528 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306529 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306530 goto fail;
6531 }
6532 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6533
6534 /* Parse and fetch current offset */
6535 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006536 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306537 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306538 goto fail;
6539 }
6540 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6541
6542post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006543 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 +05306544 bpf_set_offload->session_id,
6545 bpf_set_offload->version,
6546 bpf_set_offload->filter_id,
6547 bpf_set_offload->total_length,
6548 bpf_set_offload->current_length,
6549 bpf_set_offload->current_offset);
6550
6551 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6552 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006553 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306554 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306555 goto fail;
6556 }
6557 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306558
6559fail:
6560 if (bpf_set_offload->current_length)
6561 qdf_mem_free(bpf_set_offload->program);
6562 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306563 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306564}
6565
6566/**
6567 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6568 * @wiphy: wiphy structure pointer
6569 * @wdev: Wireless device structure pointer
6570 * @data: Pointer to the data received
6571 * @data_len: Length of @data
6572 *
6573 * Return: 0 on success; errno on failure
6574 */
6575static int
6576__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6577 struct wireless_dev *wdev,
6578 const void *data, int data_len)
6579{
6580 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6581 struct net_device *dev = wdev->netdev;
6582 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6583 struct nlattr *tb[BPF_MAX + 1];
6584 int ret_val, packet_filter_subcmd;
6585
6586 ENTER();
6587
6588 ret_val = wlan_hdd_validate_context(hdd_ctx);
6589 if (ret_val)
6590 return ret_val;
6591
6592 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006593 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306594 return -EINVAL;
6595 }
6596
6597 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006598 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306599 return -ENOTSUPP;
6600 }
6601
6602 if (nla_parse(tb, BPF_MAX, data, data_len,
6603 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006604 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306605 return -EINVAL;
6606 }
6607
6608 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006609 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306610 return -EINVAL;
6611 }
6612
6613 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6614
6615 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6616 return hdd_get_bpf_offload(hdd_ctx);
6617 else
6618 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306619 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306620}
6621
6622/**
6623 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6624 * @wiphy: wiphy structure pointer
6625 * @wdev: Wireless device structure pointer
6626 * @data: Pointer to the data received
6627 * @data_len: Length of @data
6628 *
6629 * Return: 0 on success; errno on failure
6630 */
6631
6632static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6633 struct wireless_dev *wdev,
6634 const void *data, int data_len)
6635{
6636 int ret;
6637
6638 cds_ssr_protect(__func__);
6639 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6640 cds_ssr_unprotect(__func__);
6641
6642 return ret;
6643}
6644
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306645/**
6646 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6647 * @pre_cac_adapter: AP adapter used for pre cac
6648 * @status: Status (true or false)
6649 * @handle: Global handle
6650 *
6651 * Sets the status of pre cac i.e., whether the pre cac is active or not
6652 *
6653 * Return: Zero on success, non-zero on failure
6654 */
6655static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6656 bool status, tHalHandle handle)
6657{
6658 QDF_STATUS ret;
6659
6660 ret = wlan_sap_set_pre_cac_status(
6661 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6662 if (QDF_IS_STATUS_ERROR(ret))
6663 return -EINVAL;
6664
6665 return 0;
6666}
6667
6668/**
6669 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6670 * @ap_adapter: AP adapter
6671 * @chan_before_pre_cac: Channel
6672 *
6673 * Saves the channel which the AP was beaconing on before moving to the pre
6674 * cac channel. If radar is detected on the pre cac channel, this saved
6675 * channel will be used for AP operations.
6676 *
6677 * Return: Zero on success, non-zero on failure
6678 */
6679static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6680 uint8_t chan_before_pre_cac)
6681{
6682 QDF_STATUS ret;
6683
6684 ret = wlan_sap_set_chan_before_pre_cac(
6685 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6686 if (QDF_IS_STATUS_ERROR(ret))
6687 return -EINVAL;
6688
6689 return 0;
6690}
6691
6692/**
6693 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6694 * @ap_adapter: AP adapter
6695 * @nol: Non-occupancy list
6696 * @nol_len: Length of NOL
6697 *
6698 * Get the NOL for SAP
6699 *
6700 * Return: Zero on success, non-zero on failure
6701 */
6702static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6703 uint32_t *nol_len)
6704{
6705 QDF_STATUS ret;
6706
6707 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6708 nol, nol_len);
6709 if (QDF_IS_STATUS_ERROR(ret))
6710 return -EINVAL;
6711
6712 return 0;
6713}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306714
6715/**
6716 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6717 * @hdd_ctx: HDD context
6718 * @ap_adapter: AP adapter
6719 * @channel: Channel requested by userspace
6720 * @pre_cac_chan: Pointer to the pre CAC channel
6721 *
6722 * Validates the channel provided by userspace. If user provided channel 0,
6723 * a valid outdoor channel must be selected from the regulatory channel.
6724 *
6725 * Return: Zero on success and non zero value on error
6726 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006727static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6728 hdd_adapter_t *ap_adapter,
6729 uint8_t channel,
6730 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306731{
6732 uint32_t i, j;
6733 QDF_STATUS status;
6734 int ret;
6735 uint8_t nol[QDF_MAX_NUM_CHAN];
6736 uint32_t nol_len = 0, weight_len = 0;
6737 bool found;
6738 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6739 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6740 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6741
6742 if (0 == channel) {
6743 /* Channel is not obtained from PCL because PCL may not have
6744 * the entire channel list. For example: if SAP is up on
6745 * channel 6 and PCL is queried for the next SAP interface,
6746 * if SCC is preferred, the PCL will contain only the channel
6747 * 6. But, we are in need of a DFS channel. So, going with the
6748 * first channel from the valid channel list.
6749 */
6750 status = cds_get_valid_chans(channel_list, &len);
6751 if (QDF_IS_STATUS_ERROR(status)) {
6752 hdd_err("Failed to get channel list");
6753 return -EINVAL;
6754 }
6755 cds_update_with_safe_channel_list(channel_list, &len,
6756 pcl_weights, weight_len);
6757 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6758 for (i = 0; i < len; i++) {
6759 found = false;
6760 for (j = 0; j < nol_len; j++) {
6761 if (channel_list[i] == nol[j]) {
6762 found = true;
6763 break;
6764 }
6765 }
6766 if (found)
6767 continue;
6768 if (CDS_IS_DFS_CH(channel_list[i])) {
6769 *pre_cac_chan = channel_list[i];
6770 break;
6771 }
6772 }
6773 if (*pre_cac_chan == 0) {
6774 hdd_err("unable to find outdoor channel");
6775 return -EINVAL;
6776 }
6777 } else {
6778 /* Only when driver selects a channel, check is done for
6779 * unnsafe and NOL channels. When user provides a fixed channel
6780 * the user is expected to take care of this.
6781 */
6782 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6783 !CDS_IS_DFS_CH(channel)) {
6784 hdd_err("Invalid channel for pre cac:%d", channel);
6785 return -EINVAL;
6786 } else {
6787 *pre_cac_chan = channel;
6788 }
6789 }
6790 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6791 return 0;
6792}
6793
6794/**
6795 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6796 * @channel: Channel option provided by userspace
6797 *
6798 * Sets the driver to the required hardware mode and start an adapater for
6799 * pre CAC which will mimic an AP.
6800 *
6801 * Return: Zero on success, non-zero value on error
6802 */
6803int wlan_hdd_request_pre_cac(uint8_t channel)
6804{
6805 uint8_t pre_cac_chan = 0;
6806 hdd_context_t *hdd_ctx;
6807 int ret;
6808 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6809 hdd_ap_ctx_t *hdd_ap_ctx;
6810 QDF_STATUS status;
6811 struct wiphy *wiphy;
6812 struct net_device *dev;
6813 struct cfg80211_chan_def chandef;
6814 enum nl80211_channel_type channel_type;
6815 uint32_t freq;
6816 struct ieee80211_channel *chan;
6817 tHalHandle handle;
6818 bool val;
6819
6820 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6821 if (0 != wlan_hdd_validate_context(hdd_ctx))
6822 return -EINVAL;
6823
6824 if (cds_get_connection_count() > 1) {
6825 hdd_err("pre cac not allowed in concurrency");
6826 return -EINVAL;
6827 }
6828
6829 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6830 if (!ap_adapter) {
6831 hdd_err("unable to get SAP adapter");
6832 return -EINVAL;
6833 }
6834
6835 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6836 if (!handle) {
6837 hdd_err("Invalid handle");
6838 return -EINVAL;
6839 }
6840
6841 val = wlan_sap_is_pre_cac_active(handle);
6842 if (val) {
6843 hdd_err("pre cac is already in progress");
6844 return -EINVAL;
6845 }
6846
6847 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6848 if (!hdd_ap_ctx) {
6849 hdd_err("SAP context is NULL");
6850 return -EINVAL;
6851 }
6852
6853 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6854 hdd_err("SAP is already on DFS channel:%d",
6855 hdd_ap_ctx->operatingChannel);
6856 return -EINVAL;
6857 }
6858
6859 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6860 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6861 hdd_ap_ctx->operatingChannel);
6862 return -EINVAL;
6863 }
6864
6865 hdd_info("channel:%d", channel);
6866
6867 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6868 &pre_cac_chan);
6869 if (ret != 0)
6870 return ret;
6871
6872 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6873 * connection update should result in DBS mode
6874 */
6875 status = cds_update_and_wait_for_connection_update(
6876 ap_adapter->sessionId,
6877 pre_cac_chan,
6878 SIR_UPDATE_REASON_PRE_CAC);
6879 if (QDF_IS_STATUS_ERROR(status)) {
6880 hdd_err("error in moving to DBS mode");
6881 return -EINVAL;
6882 }
6883
6884 hdd_debug("starting pre cac SAP adapter");
6885
6886 /* Starting a SAP adapter:
6887 * Instead of opening an adapter, we could just do a SME open session
6888 * for AP type. But, start BSS would still need an adapter.
6889 * So, this option is not taken.
6890 *
6891 * hdd open adapter is going to register this precac interface with
6892 * user space. This interface though exposed to user space will be in
6893 * DOWN state. Consideration was done to avoid this registration to the
6894 * user space. But, as part of SAP operations multiple events are sent
6895 * to user space. Some of these events received from unregistered
6896 * interface was causing crashes. So, retaining the registration.
6897 *
6898 * So, this interface would remain registered and will remain in DOWN
6899 * state for the CAC duration. We will add notes in the feature
6900 * announcement to not use this temporary interface for any activity
6901 * from user space.
6902 */
6903 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6904 wlan_hdd_get_intf_addr(hdd_ctx),
6905 NET_NAME_UNKNOWN, true);
6906 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306907 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306908 return -EINVAL;
6909 }
6910
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306911 /*
6912 * This interface is internally created by the driver. So, no interface
6913 * up comes for this interface from user space and hence starting
6914 * the adapter internally.
6915 */
6916 if (hdd_start_adapter(pre_cac_adapter)) {
6917 hdd_err("error starting the pre cac adapter");
6918 goto close_pre_cac_adapter;
6919 }
6920
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306921 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6922
6923 wiphy = hdd_ctx->wiphy;
6924 dev = pre_cac_adapter->dev;
6925
6926 /* Since this is only a dummy interface lets us use the IEs from the
6927 * other active SAP interface. In regular scenarios, these IEs would
6928 * come from the user space entity
6929 */
6930 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6931 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6932 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6933 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306934 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306935 }
6936 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6937 ap_adapter->sessionCtx.ap.beacon,
6938 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6939 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6940 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6941 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6942 ap_adapter->sessionCtx.ap.sapConfig.authType;
6943
6944 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6945 * to operate on the same bandwidth as that of the 2.4GHz operations.
6946 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6947 */
6948 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6949 case CH_WIDTH_20MHZ:
6950 channel_type = NL80211_CHAN_HT20;
6951 break;
6952 case CH_WIDTH_40MHZ:
6953 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6954 ap_adapter->sessionCtx.ap.sapConfig.channel)
6955 channel_type = NL80211_CHAN_HT40PLUS;
6956 else
6957 channel_type = NL80211_CHAN_HT40MINUS;
6958 break;
6959 default:
6960 channel_type = NL80211_CHAN_NO_HT;
6961 break;
6962 }
6963
6964 freq = cds_chan_to_freq(pre_cac_chan);
6965 chan = __ieee80211_get_channel(wiphy, freq);
6966 if (!chan) {
6967 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306968 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306969 }
6970
6971 cfg80211_chandef_create(&chandef, chan, channel_type);
6972
6973 hdd_debug("orig width:%d channel_type:%d freq:%d",
6974 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6975 channel_type, freq);
6976
6977 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6978 if (0 != ret) {
6979 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306980 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306981 }
6982
6983 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6984 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6985 eHIDDEN_SSID_NOT_IN_USE, false);
6986 if (QDF_IS_STATUS_ERROR(status)) {
6987 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306988 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306989 }
6990
6991 /*
6992 * The pre cac status is set here. But, it would not be reset explicitly
6993 * anywhere, since after the pre cac success/failure, the pre cac
6994 * adapter itself would be removed.
6995 */
6996 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6997 if (0 != ret) {
6998 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306999 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307000 }
7001
7002 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7003 hdd_ap_ctx->operatingChannel);
7004 if (0 != ret) {
7005 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307006 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307007 }
7008
7009 ap_adapter->pre_cac_chan = pre_cac_chan;
7010
7011 return 0;
7012
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307013stop_close_pre_cac_adapter:
7014 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307015 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7016 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307017close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307018 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
7019 return -EINVAL;
7020}
7021
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307022/**
7023 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7024 *
7025 * Return: None
7026 */
7027void hdd_init_bpf_completion(void)
7028{
7029 init_completion(&bpf_context.completion);
7030}
7031
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307032static const struct nla_policy
7033wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7034 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7035};
7036
Agrawal Ashish65634612016-08-18 13:24:32 +05307037static const struct nla_policy
7038wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7039 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7040 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7041};
7042
7043/**
7044 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7045 * @wiphy: Pointer to wireless phy
7046 * @wdev: Pointer to wireless device
7047 * @data: Pointer to data
7048 * @data_len: Length of @data
7049 *
7050 * This function parses the incoming NL vendor command data attributes and
7051 * updates the SAP context about channel_hint and DFS mode.
7052 * If channel_hint is set, SAP will choose that channel
7053 * as operating channel.
7054 *
7055 * If DFS mode is enabled, driver will include DFS channels
7056 * in ACS else driver will skip DFS channels.
7057 *
7058 * Return: 0 on success, negative errno on failure
7059 */
7060static int
7061__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7062 struct wireless_dev *wdev,
7063 const void *data, int data_len)
7064{
7065 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7066 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7067 int ret;
7068 struct acs_dfs_policy *acs_policy;
7069 int mode = DFS_MODE_NONE;
7070 int channel_hint = 0;
7071
7072 ENTER_DEV(wdev->netdev);
7073
7074 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7075 hdd_err("Command not allowed in FTM mode");
7076 return -EINVAL;
7077 }
7078
7079 ret = wlan_hdd_validate_context(hdd_ctx);
7080 if (0 != ret)
7081 return ret;
7082
7083 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7084 data, data_len,
7085 wlan_hdd_set_acs_dfs_config_policy)) {
7086 hdd_err("invalid attr");
7087 return -EINVAL;
7088 }
7089
7090 acs_policy = &hdd_ctx->acs_policy;
7091 /*
7092 * SCM sends this attribute to restrict SAP from choosing
7093 * DFS channels from ACS.
7094 */
7095 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7096 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7097
7098 if (!IS_DFS_MODE_VALID(mode)) {
7099 hdd_err("attr acs dfs mode is not valid");
7100 return -EINVAL;
7101 }
7102 acs_policy->acs_dfs_mode = mode;
7103
7104 /*
7105 * SCM sends this attribute to provide an active channel,
7106 * to skip redundant ACS between drivers, and save driver start up time
7107 */
7108 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7109 channel_hint = nla_get_u8(
7110 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7111
7112 if (!IS_CHANNEL_VALID(channel_hint)) {
7113 hdd_err("acs channel is not valid");
7114 return -EINVAL;
7115 }
7116 acs_policy->acs_channel = channel_hint;
7117
7118 return 0;
7119}
7120
7121/**
7122 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7123 * @wiphy: wiphy structure pointer
7124 * @wdev: Wireless device structure pointer
7125 * @data: Pointer to the data received
7126 * @data_len: Length of @data
7127 *
7128 * This function parses the incoming NL vendor command data attributes and
7129 * updates the SAP context about channel_hint and DFS mode.
7130 *
7131 * Return: 0 on success; errno on failure
7132 */
7133static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7134 struct wireless_dev *wdev,
7135 const void *data, int data_len)
7136{
7137 int ret;
7138
7139 cds_ssr_protect(__func__);
7140 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7141 cds_ssr_unprotect(__func__);
7142
7143 return ret;
7144}
7145
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307146/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307147 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7148 * @mode : cfg80211 dfs mode
7149 *
7150 * Return: return csr sta roam dfs mode else return NONE
7151 */
7152static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7153 enum dfs_mode mode)
7154{
7155 switch (mode) {
7156 case DFS_MODE_ENABLE:
7157 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7158 break;
7159 case DFS_MODE_DISABLE:
7160 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7161 break;
7162 case DFS_MODE_DEPRIORITIZE:
7163 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7164 break;
7165 default:
7166 hdd_err("STA Roam policy dfs mode is NONE");
7167 return CSR_STA_ROAM_POLICY_NONE;
7168 }
7169}
7170
7171static const struct nla_policy
7172wlan_hdd_set_sta_roam_config_policy[
7173QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7174 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7175 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7176};
7177
7178/**
7179 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7180 * for station connection or roaming.
7181 * @wiphy: Pointer to wireless phy
7182 * @wdev: Pointer to wireless device
7183 * @data: Pointer to data
7184 * @data_len: Length of @data
7185 *
7186 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7187 * channels needs to be skipped in scanning or not.
7188 * If dfs_mode is disabled, driver will not scan DFS channels.
7189 * If skip_unsafe_channels is set, driver will skip unsafe channels
7190 * in Scanning.
7191 *
7192 * Return: 0 on success, negative errno on failure
7193 */
7194static int
7195__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7196 struct wireless_dev *wdev,
7197 const void *data, int data_len)
7198{
7199 struct net_device *dev = wdev->netdev;
7200 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7201 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7202 struct nlattr *tb[
7203 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7204 int ret;
7205 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7206 enum dfs_mode mode = DFS_MODE_NONE;
7207 bool skip_unsafe_channels = false;
7208 QDF_STATUS status;
7209
7210 ENTER_DEV(dev);
7211
7212 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7213 hdd_err("Command not allowed in FTM mode");
7214 return -EINVAL;
7215 }
7216
7217 ret = wlan_hdd_validate_context(hdd_ctx);
7218 if (0 != ret)
7219 return ret;
7220 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7221 data, data_len,
7222 wlan_hdd_set_sta_roam_config_policy)) {
7223 hdd_err("invalid attr");
7224 return -EINVAL;
7225 }
7226 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7227 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7228 if (!IS_DFS_MODE_VALID(mode)) {
7229 hdd_err("attr sta roam dfs mode policy is not valid");
7230 return -EINVAL;
7231 }
7232
7233 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7234
7235 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7236 skip_unsafe_channels = nla_get_u8(
7237 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7238
7239 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7240 skip_unsafe_channels, adapter->sessionId);
7241
7242 if (!QDF_IS_STATUS_SUCCESS(status)) {
7243 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7244 return -EINVAL;
7245 }
7246 return 0;
7247}
7248
7249/**
7250 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7251 * connection and roaming for station.
7252 * @wiphy: wiphy structure pointer
7253 * @wdev: Wireless device structure pointer
7254 * @data: Pointer to the data received
7255 * @data_len: Length of @data
7256 *
7257 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7258 * channels needs to be skipped in scanning or not.
7259 * If dfs_mode is disabled, driver will not scan DFS channels.
7260 * If skip_unsafe_channels is set, driver will skip unsafe channels
7261 * in Scanning.
7262 * Return: 0 on success; errno on failure
7263 */
7264static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7265 struct wireless_dev *wdev,
7266 const void *data, int data_len)
7267{
7268 int ret;
7269
7270 cds_ssr_protect(__func__);
7271 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7272 cds_ssr_unprotect(__func__);
7273
7274 return ret;
7275}
7276
Agrawal Ashish467dde42016-09-08 18:44:22 +05307277#ifdef FEATURE_WLAN_CH_AVOID
7278/**
7279 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7280 * is on unsafe channel.
7281 * @wiphy: wiphy structure pointer
7282 * @wdev: Wireless device structure pointer
7283 * @data: Pointer to the data received
7284 * @data_len: Length of @data
7285 *
7286 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7287 * on any of unsafe channels.
7288 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7289 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7290 *
7291 * Return: 0 on success; errno on failure
7292 */
7293static int
7294__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7295 struct wireless_dev *wdev,
7296 const void *data, int data_len)
7297{
7298 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7299 int ret;
7300 uint16_t unsafe_channel_count;
7301 int unsafe_channel_index;
7302 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7303
7304 ENTER_DEV(wdev->netdev);
7305
7306 if (!qdf_ctx) {
7307 cds_err("qdf_ctx is NULL");
7308 return -EINVAL;
7309 }
7310
7311 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7312 hdd_err("Command not allowed in FTM mode");
7313 return -EINVAL;
7314 }
7315
7316 ret = wlan_hdd_validate_context(hdd_ctx);
7317 if (0 != ret)
7318 return ret;
7319 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7320 &(hdd_ctx->unsafe_channel_count),
7321 sizeof(hdd_ctx->unsafe_channel_list));
7322
7323 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7324 (uint16_t)NUM_CHANNELS);
7325 for (unsafe_channel_index = 0;
7326 unsafe_channel_index < unsafe_channel_count;
7327 unsafe_channel_index++) {
7328 hdd_info("Channel %d is not safe",
7329 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7330 }
7331 hdd_unsafe_channel_restart_sap(hdd_ctx);
7332 return 0;
7333}
7334
7335/**
7336 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7337 * is on unsafe channel.
7338 * @wiphy: wiphy structure pointer
7339 * @wdev: Wireless device structure pointer
7340 * @data: Pointer to the data received
7341 * @data_len: Length of @data
7342 *
7343 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7344 * on any of unsafe channels.
7345 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7346 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7347 *
7348 * Return: 0 on success; errno on failure
7349 */
7350static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7351 struct wireless_dev *wdev,
7352 const void *data, int data_len)
7353{
7354 int ret;
7355
7356 cds_ssr_protect(__func__);
7357 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7358 cds_ssr_unprotect(__func__);
7359
7360 return ret;
7361}
7362
7363#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307364/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307365 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7366 * SAP is on unsafe channel.
7367 * @wiphy: wiphy structure pointer
7368 * @wdev: Wireless device structure pointer
7369 * @data: Pointer to the data received
7370 * @data_len: Length of @data
7371 *
7372 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7373 * driver.
7374 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7375 * will initiate restart of sap.
7376 *
7377 * Return: 0 on success; errno on failure
7378 */
7379static int
7380__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7381 struct wireless_dev *wdev,
7382 const void *data, int data_len)
7383{
7384 struct net_device *ndev = wdev->netdev;
7385 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7386 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7387 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7388 uint8_t config_channel = 0;
7389 hdd_ap_ctx_t *ap_ctx;
7390 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307391 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307392
7393 ENTER();
7394
7395 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007396 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307397 return -EINVAL;
7398 }
7399
7400 ret = wlan_hdd_validate_context(hdd_ctx);
7401 if (0 != ret)
7402 return -EINVAL;
7403
7404 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7405 data, data_len,
7406 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007407 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307408 return -EINVAL;
7409 }
7410
7411 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7412 if (!test_bit(SOFTAP_BSS_STARTED,
7413 &hostapd_adapter->event_flags)) {
7414 hdd_err("SAP is not started yet. Restart sap will be invalid");
7415 return -EINVAL;
7416 }
7417
7418 config_channel =
7419 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7420
7421 if (!((IS_24G_CH(config_channel)) ||
7422 (IS_5G_CH(config_channel)))) {
7423 hdd_err("Channel %d is not valid to restart SAP",
7424 config_channel);
7425 return -ENOTSUPP;
7426 }
7427
7428 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7429 ap_ctx->sapConfig.channel = config_channel;
7430 ap_ctx->sapConfig.ch_params.ch_width =
7431 ap_ctx->sapConfig.ch_width_orig;
7432
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007433 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307434 ap_ctx->sapConfig.sec_ch,
7435 &ap_ctx->sapConfig.ch_params);
7436
7437 cds_restart_sap(hostapd_adapter);
7438 }
7439
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307440 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7441 uint32_t freq_len, i;
7442 uint32_t *freq;
7443 uint8_t chans[QDF_MAX_NUM_CHAN];
7444
7445 hdd_debug("setting mandatory freq/chan list");
7446
7447 freq_len = nla_len(
7448 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7449 sizeof(uint32_t);
7450
7451 if (freq_len > QDF_MAX_NUM_CHAN) {
7452 hdd_err("insufficient space to hold channels");
7453 return -ENOMEM;
7454 }
7455
7456 freq = nla_data(
7457 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7458
7459 hdd_debug("freq_len=%d", freq_len);
7460
7461 for (i = 0; i < freq_len; i++) {
7462 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7463 hdd_debug("freq[%d]=%d", i, freq[i]);
7464 }
7465
7466 status = cds_set_sap_mandatory_channels(chans, freq_len);
7467 if (QDF_IS_STATUS_ERROR(status))
7468 return -EINVAL;
7469 }
7470
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307471 return 0;
7472}
7473
7474/**
7475 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7476 * @wiphy: wiphy structure pointer
7477 * @wdev: Wireless device structure pointer
7478 * @data: Pointer to the data received
7479 * @data_len: Length of @data
7480 *
7481 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7482 * driver.
7483 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7484 * will initiate restart of sap.
7485 *
7486 * Return: 0 on success; errno on failure
7487 */
7488static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7489 struct wireless_dev *wdev,
7490 const void *data, int data_len)
7491{
7492 int ret;
7493
7494 cds_ssr_protect(__func__);
7495 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7496 wdev, data, data_len);
7497 cds_ssr_unprotect(__func__);
7498
7499 return ret;
7500}
7501
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307502#undef BPF_INVALID
7503#undef BPF_SET_RESET
7504#undef BPF_VERSION
7505#undef BPF_ID
7506#undef BPF_PACKET_SIZE
7507#undef BPF_CURRENT_OFFSET
7508#undef BPF_PROGRAM
7509#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307510
7511/**
7512 * define short names for the global vendor params
7513 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7514 */
7515#define PARAM_TOTAL_CMD_EVENT_WAKE \
7516 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7517#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7518 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7519#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7520 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7521#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7522 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7523#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7524 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7525#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7526 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7527#define PARAM_TOTAL_RX_DATA_WAKE \
7528 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7529#define PARAM_RX_UNICAST_CNT \
7530 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7531#define PARAM_RX_MULTICAST_CNT \
7532 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7533#define PARAM_RX_BROADCAST_CNT \
7534 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7535#define PARAM_ICMP_PKT \
7536 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7537#define PARAM_ICMP6_PKT \
7538 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7539#define PARAM_ICMP6_RA \
7540 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7541#define PARAM_ICMP6_NA \
7542 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7543#define PARAM_ICMP6_NS \
7544 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7545#define PARAM_ICMP4_RX_MULTICAST_CNT \
7546 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7547#define PARAM_ICMP6_RX_MULTICAST_CNT \
7548 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7549#define PARAM_OTHER_RX_MULTICAST_CNT \
7550 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7551
7552
7553/**
7554 * hdd_send_wakelock_stats() - API to send wakelock stats
7555 * @ctx: context to be passed to callback
7556 * @data: data passed to callback
7557 *
7558 * This function is used to send wake lock stats to HAL layer
7559 *
7560 * Return: 0 on success, error number otherwise.
7561 */
7562static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7563 const struct sir_wake_lock_stats *data)
7564{
7565 struct sk_buff *skb;
7566 uint32_t nl_buf_len;
7567 uint32_t total_rx_data_wake, rx_multicast_cnt;
7568 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307569 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307570
7571 ENTER();
7572
7573 nl_buf_len = NLMSG_HDRLEN;
7574 nl_buf_len +=
7575 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7576 (NLMSG_HDRLEN + sizeof(uint32_t));
7577
7578 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7579
7580 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007581 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307582 return -ENOMEM;
7583 }
7584
Jeff Johnson64943bd2016-08-23 13:14:06 -07007585 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307586 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007587 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307588 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007589 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307590 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007591 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307592 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007593 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307594 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007595 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307596 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007597 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307598 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007599 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7600 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307601 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307602
7603 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307604 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307605
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307606 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307607 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307608
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307609 rx_multicast_cnt =
7610 data->wow_ipv4_mcast_wake_up_count +
7611 ipv6_rx_multicast_addr_cnt;
7612
7613 total_rx_data_wake =
7614 data->wow_ucast_wake_up_count +
7615 data->wow_bcast_wake_up_count +
7616 rx_multicast_cnt;
7617
7618 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7619 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7620 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7621 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7622 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7623 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7624 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7625 total_rx_data_wake) ||
7626 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7627 data->wow_ucast_wake_up_count) ||
7628 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7629 rx_multicast_cnt) ||
7630 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7631 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307632 nla_put_u32(skb, PARAM_ICMP_PKT,
7633 data->wow_icmpv4_count) ||
7634 nla_put_u32(skb, PARAM_ICMP6_PKT,
7635 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307636 nla_put_u32(skb, PARAM_ICMP6_RA,
7637 data->wow_ipv6_mcast_ra_stats) ||
7638 nla_put_u32(skb, PARAM_ICMP6_NA,
7639 data->wow_ipv6_mcast_na_stats) ||
7640 nla_put_u32(skb, PARAM_ICMP6_NS,
7641 data->wow_ipv6_mcast_ns_stats) ||
7642 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7643 data->wow_ipv4_mcast_wake_up_count) ||
7644 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7645 ipv6_rx_multicast_addr_cnt) ||
7646 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007647 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307648 goto nla_put_failure;
7649 }
7650
7651 cfg80211_vendor_cmd_reply(skb);
7652
7653 EXIT();
7654 return 0;
7655
7656nla_put_failure:
7657 kfree_skb(skb);
7658 return -EINVAL;
7659}
7660
7661/**
7662 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7663 * @wiphy: wiphy pointer
7664 * @wdev: pointer to struct wireless_dev
7665 * @data: pointer to incoming NL vendor data
7666 * @data_len: length of @data
7667 *
7668 * This function parses the incoming NL vendor command data attributes and
7669 * invokes the SME Api and blocks on a completion variable.
7670 * WMA copies required data and invokes callback
7671 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7672 *
7673 * Return: 0 on success; error number otherwise.
7674 */
7675static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7676 struct wireless_dev *wdev,
7677 const void *data,
7678 int data_len)
7679{
7680 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7681 int status, ret;
7682 struct sir_wake_lock_stats wake_lock_stats;
7683 QDF_STATUS qdf_status;
7684
7685 ENTER();
7686
7687 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007688 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307689 return -EINVAL;
7690 }
7691
7692 status = wlan_hdd_validate_context(hdd_ctx);
7693 if (0 != status)
7694 return -EINVAL;
7695
7696 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7697 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007698 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307699 return -EINVAL;
7700 }
7701
7702 ret = hdd_send_wakelock_stats(hdd_ctx,
7703 &wake_lock_stats);
7704 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007705 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307706
7707 EXIT();
7708 return ret;
7709}
7710
7711/**
7712 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7713 * @wiphy: wiphy pointer
7714 * @wdev: pointer to struct wireless_dev
7715 * @data: pointer to incoming NL vendor data
7716 * @data_len: length of @data
7717 *
7718 * This function parses the incoming NL vendor command data attributes and
7719 * invokes the SME Api and blocks on a completion variable.
7720 * WMA copies required data and invokes callback
7721 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7722 *
7723 * Return: 0 on success; error number otherwise.
7724 */
7725static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7726 struct wireless_dev *wdev,
7727 const void *data, int data_len)
7728{
7729 int ret;
7730
7731 cds_ssr_protect(__func__);
7732 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7733 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007734 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307735
7736 return ret;
7737}
7738
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307739/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307740 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7741 * @wiphy: wiphy structure pointer
7742 * @wdev: Wireless device structure pointer
7743 * @data: Pointer to the data received
7744 * @data_len: Length of @data
7745 *
7746 * This function reads wmi max bus size and fill in the skb with
7747 * NL attributes and send up the NL event.
7748 * Return: 0 on success; errno on failure
7749 */
7750static int
7751__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7752 struct wireless_dev *wdev,
7753 const void *data, int data_len)
7754{
7755 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7756 int ret_val;
7757 struct sk_buff *skb;
7758 uint32_t nl_buf_len;
7759
7760 ENTER();
7761
7762 ret_val = wlan_hdd_validate_context(hdd_ctx);
7763 if (ret_val)
7764 return ret_val;
7765
7766 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7767 hdd_err("Command not allowed in FTM mode");
7768 return -EINVAL;
7769 }
7770
7771 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7772
7773 nl_buf_len = NLMSG_HDRLEN;
7774 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7775
7776 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7777 if (!skb) {
7778 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7779 return -ENOMEM;
7780 }
7781
7782 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7783 hdd_ctx->wmi_max_len)) {
7784 hdd_err("nla put failure");
7785 goto nla_put_failure;
7786 }
7787
7788 cfg80211_vendor_cmd_reply(skb);
7789
7790 EXIT();
7791
7792 return 0;
7793
7794nla_put_failure:
7795 kfree_skb(skb);
7796 return -EINVAL;
7797}
7798
7799/**
7800 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7801 * @wiphy: wiphy structure pointer
7802 * @wdev: Wireless device structure pointer
7803 * @data: Pointer to the data received
7804 * @data_len: Length of @data
7805 *
7806 * Return: 0 on success; errno on failure
7807 */
7808static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7809 struct wireless_dev *wdev,
7810 const void *data, int data_len)
7811{
7812 int ret;
7813
7814 cds_ssr_protect(__func__);
7815 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7816 cds_ssr_unprotect(__func__);
7817
7818 return ret;
7819}
7820
7821/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307822 *__wlan_hdd_cfg80211_setband() - set band
7823 * @wiphy: Pointer to wireless phy
7824 * @wdev: Pointer to wireless device
7825 * @data: Pointer to data
7826 * @data_len: Length of @data
7827 *
7828 * Return: 0 on success, negative errno on failure
7829 */
7830static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7831 struct wireless_dev *wdev,
7832 const void *data, int data_len)
7833{
7834 struct net_device *dev = wdev->netdev;
7835 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7836 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7837 int ret;
7838 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7839 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7840
7841 ENTER();
7842
7843 ret = wlan_hdd_validate_context(hdd_ctx);
7844 if (ret)
7845 return ret;
7846
7847 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7848 hdd_err(FL("Invalid ATTR"));
7849 return -EINVAL;
7850 }
7851
7852 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7853 hdd_err(FL("attr SETBAND_VALUE failed"));
7854 return -EINVAL;
7855 }
7856
7857 ret = hdd_set_band(dev,
7858 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7859
7860 EXIT();
7861 return ret;
7862}
7863
7864/**
7865 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7866 * @wiphy: wiphy structure pointer
7867 * @wdev: Wireless device structure pointer
7868 * @data: Pointer to the data received
7869 * @data_len: Length of @data
7870 *
7871 * Return: 0 on success; errno on failure
7872 */
7873static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7874 struct wireless_dev *wdev,
7875 const void *data, int data_len)
7876{
7877 int ret;
7878
7879 cds_ssr_protect(__func__);
7880 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7881 cds_ssr_unprotect(__func__);
7882
7883 return ret;
7884}
7885
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307886static const struct
7887nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7888 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7889 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7890 .len = QDF_MAC_ADDR_SIZE},
7891};
7892
7893/**
7894 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7895 * @wiphy: Pointer to wireless phy
7896 * @wdev: Pointer to wireless device
7897 * @data: Pointer to data
7898 * @data_len: Length of @data
7899 *
7900 * This function is used to enable/disable roaming using vendor commands
7901 *
7902 * Return: 0 on success, negative errno on failure
7903 */
7904static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7905 struct wireless_dev *wdev,
7906 const void *data, int data_len)
7907{
7908 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7909 struct net_device *dev = wdev->netdev;
7910 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7911 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7912 uint32_t is_fast_roam_enabled;
7913 int ret;
7914
7915 ENTER_DEV(dev);
7916
7917 ret = wlan_hdd_validate_context(hdd_ctx);
7918 if (0 != ret)
7919 return ret;
7920
7921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7922 hdd_err("Command not allowed in FTM mode");
7923 return -EINVAL;
7924 }
7925
7926 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7927 qca_wlan_vendor_attr);
7928 if (ret) {
7929 hdd_err("Invalid ATTR");
7930 return -EINVAL;
7931 }
7932
7933 /* Parse and fetch Enable flag */
7934 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7935 hdd_err("attr enable failed");
7936 return -EINVAL;
7937 }
7938
7939 is_fast_roam_enabled = nla_get_u32(
7940 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7941 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7942
7943 /* Update roaming */
7944 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7945 is_fast_roam_enabled);
7946 if (ret)
7947 hdd_err("sme_config_fast_roaming failed");
7948 EXIT();
7949 return ret;
7950}
7951
7952/**
7953 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7954 * @wiphy: Pointer to wireless phy
7955 * @wdev: Pointer to wireless device
7956 * @data: Pointer to data
7957 * @data_len: Length of @data
7958 *
7959 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7960 *
7961 * Return: 0 on success, negative errno on failure
7962 */
7963static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7964 struct wireless_dev *wdev,
7965 const void *data, int data_len)
7966{
7967 int ret;
7968
7969 cds_ssr_protect(__func__);
7970 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7971 cds_ssr_unprotect(__func__);
7972
7973 return ret;
7974}
7975
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007976const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7977 {
7978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7979 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307981 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007982 .doit = is_driver_dfs_capable
7983 },
7984
7985#ifdef WLAN_FEATURE_NAN
7986 {
7987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7988 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7989 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7990 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7991 .doit = wlan_hdd_cfg80211_nan_request
7992 },
7993#endif
7994
7995#ifdef WLAN_FEATURE_STATS_EXT
7996 {
7997 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7998 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7999 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8000 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8001 .doit = wlan_hdd_cfg80211_stats_ext_request
8002 },
8003#endif
8004#ifdef FEATURE_WLAN_EXTSCAN
8005 {
8006 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8007 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8008 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8009 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8010 .doit = wlan_hdd_cfg80211_extscan_start
8011 },
8012 {
8013 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8014 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8015 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8016 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8017 .doit = wlan_hdd_cfg80211_extscan_stop
8018 },
8019 {
8020 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8021 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8022 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8023 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8024 },
8025 {
8026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8027 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8029 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8030 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8031 },
8032 {
8033 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8034 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8035 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8036 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8037 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8038 },
8039 {
8040 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8041 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8042 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8043 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8044 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8045 },
8046 {
8047 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8048 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8049 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8050 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8051 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8052 },
8053 {
8054 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8055 .info.subcmd =
8056 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8057 .flags =
8058 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8059 WIPHY_VENDOR_CMD_NEED_RUNNING,
8060 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8061 },
8062 {
8063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8064 .info.subcmd =
8065 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8066 .flags =
8067 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8068 WIPHY_VENDOR_CMD_NEED_RUNNING,
8069 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8070 },
8071 {
8072 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8073 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8074 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8075 WIPHY_VENDOR_CMD_NEED_NETDEV |
8076 WIPHY_VENDOR_CMD_NEED_RUNNING,
8077 .doit = wlan_hdd_cfg80211_set_epno_list
8078 },
8079#endif /* FEATURE_WLAN_EXTSCAN */
8080
8081#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8082 {
8083 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8084 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8085 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8086 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8087 .doit = wlan_hdd_cfg80211_ll_stats_clear
8088 },
8089
8090 {
8091 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8092 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8093 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8094 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8095 .doit = wlan_hdd_cfg80211_ll_stats_set
8096 },
8097
8098 {
8099 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8100 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8101 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8102 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8103 .doit = wlan_hdd_cfg80211_ll_stats_get
8104 },
8105#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8106#ifdef FEATURE_WLAN_TDLS
8107 {
8108 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8109 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8110 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8111 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8112 .doit = wlan_hdd_cfg80211_exttdls_enable
8113 },
8114 {
8115 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8116 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8117 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8118 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8119 .doit = wlan_hdd_cfg80211_exttdls_disable
8120 },
8121 {
8122 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8123 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8124 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8125 .doit = wlan_hdd_cfg80211_exttdls_get_status
8126 },
8127#endif
8128 {
8129 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8130 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8131 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8132 .doit = wlan_hdd_cfg80211_get_supported_features
8133 },
8134 {
8135 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8136 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8137 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8138 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8139 },
8140 {
8141 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8142 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8143 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308144 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008145 },
8146 {
8147 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8148 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8149 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8150 WIPHY_VENDOR_CMD_NEED_NETDEV,
8151 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8152 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008153 {
8154 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8155 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8156 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8157 WIPHY_VENDOR_CMD_NEED_NETDEV,
8158 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8159 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008160 {
8161 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308162 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8163 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8164 WIPHY_VENDOR_CMD_NEED_NETDEV |
8165 WIPHY_VENDOR_CMD_NEED_RUNNING,
8166 .doit = hdd_cfg80211_get_station_cmd
8167 },
8168 {
8169 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008170 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8171 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8172 WIPHY_VENDOR_CMD_NEED_NETDEV |
8173 WIPHY_VENDOR_CMD_NEED_RUNNING,
8174 .doit = wlan_hdd_cfg80211_do_acs
8175 },
8176
8177 {
8178 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8179 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8180 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8181 WIPHY_VENDOR_CMD_NEED_NETDEV,
8182 .doit = wlan_hdd_cfg80211_get_features
8183 },
8184#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8185 {
8186 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8187 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8188 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8189 WIPHY_VENDOR_CMD_NEED_NETDEV |
8190 WIPHY_VENDOR_CMD_NEED_RUNNING,
8191 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8192 },
8193#endif
8194#ifdef FEATURE_WLAN_EXTSCAN
8195 {
8196 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8197 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8198 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8199 WIPHY_VENDOR_CMD_NEED_NETDEV |
8200 WIPHY_VENDOR_CMD_NEED_RUNNING,
8201 .doit = wlan_hdd_cfg80211_set_passpoint_list
8202 },
8203 {
8204 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8205 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8206 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8207 WIPHY_VENDOR_CMD_NEED_NETDEV |
8208 WIPHY_VENDOR_CMD_NEED_RUNNING,
8209 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8210 },
8211 {
8212 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8213 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8214 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8215 WIPHY_VENDOR_CMD_NEED_NETDEV |
8216 WIPHY_VENDOR_CMD_NEED_RUNNING,
8217 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8218 },
8219 {
8220 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8221 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8222 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8223 WIPHY_VENDOR_CMD_NEED_NETDEV |
8224 WIPHY_VENDOR_CMD_NEED_RUNNING,
8225 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8226 },
8227#endif /* FEATURE_WLAN_EXTSCAN */
8228 {
8229 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8230 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8231 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8232 WIPHY_VENDOR_CMD_NEED_NETDEV,
8233 .doit = wlan_hdd_cfg80211_get_wifi_info
8234 },
8235 {
8236 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8237 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8238 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8239 WIPHY_VENDOR_CMD_NEED_NETDEV |
8240 WIPHY_VENDOR_CMD_NEED_RUNNING,
8241 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8242 },
8243 {
8244 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8245 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8246 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8247 WIPHY_VENDOR_CMD_NEED_NETDEV,
8248 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8249 },
8250 {
8251 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8252 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8253 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8254 WIPHY_VENDOR_CMD_NEED_NETDEV,
8255 .doit = wlan_hdd_cfg80211_wifi_logger_start
8256 },
8257 {
8258 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8259 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8260 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8261 WIPHY_VENDOR_CMD_NEED_NETDEV,
8262 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8263 },
8264 {
8265 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8266 .info.subcmd =
8267 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8268 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8269 WIPHY_VENDOR_CMD_NEED_NETDEV |
8270 WIPHY_VENDOR_CMD_NEED_RUNNING,
8271 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8272 },
8273 {
8274 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8275 .info.subcmd =
8276 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8277 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8278 WIPHY_VENDOR_CMD_NEED_NETDEV |
8279 WIPHY_VENDOR_CMD_NEED_RUNNING,
8280 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8281 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008282#ifdef WLAN_FEATURE_TSF
8283 {
8284 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8285 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8286 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8287 WIPHY_VENDOR_CMD_NEED_NETDEV |
8288 WIPHY_VENDOR_CMD_NEED_RUNNING,
8289 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8290 },
8291#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008292#ifdef FEATURE_WLAN_TDLS
8293 {
8294 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8295 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8296 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8297 WIPHY_VENDOR_CMD_NEED_NETDEV |
8298 WIPHY_VENDOR_CMD_NEED_RUNNING,
8299 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8300 },
8301#endif
8302#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8303 {
8304 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8305 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8306 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8307 WIPHY_VENDOR_CMD_NEED_NETDEV |
8308 WIPHY_VENDOR_CMD_NEED_RUNNING,
8309 .doit = wlan_hdd_cfg80211_offloaded_packets
8310 },
8311#endif
8312 {
8313 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8314 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8315 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8316 WIPHY_VENDOR_CMD_NEED_NETDEV |
8317 WIPHY_VENDOR_CMD_NEED_RUNNING,
8318 .doit = wlan_hdd_cfg80211_monitor_rssi
8319 },
8320 {
8321 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308322 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8323 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8324 WIPHY_VENDOR_CMD_NEED_NETDEV |
8325 WIPHY_VENDOR_CMD_NEED_RUNNING,
8326 .doit = wlan_hdd_cfg80211_set_ns_offload
8327 },
8328 {
8329 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008330 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8331 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8332 WIPHY_VENDOR_CMD_NEED_NETDEV |
8333 WIPHY_VENDOR_CMD_NEED_RUNNING,
8334 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8335 },
8336#ifdef WLAN_FEATURE_MEMDUMP
8337 {
8338 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8339 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8340 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8341 WIPHY_VENDOR_CMD_NEED_NETDEV |
8342 WIPHY_VENDOR_CMD_NEED_RUNNING,
8343 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8344 },
8345#endif /* WLAN_FEATURE_MEMDUMP */
8346 {
8347 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8348 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8349 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8350 WIPHY_VENDOR_CMD_NEED_NETDEV |
8351 WIPHY_VENDOR_CMD_NEED_RUNNING,
8352 .doit = wlan_hdd_cfg80211_vendor_scan
8353 },
8354
8355 /* OCB commands */
8356 {
8357 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8358 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8359 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8360 WIPHY_VENDOR_CMD_NEED_NETDEV |
8361 WIPHY_VENDOR_CMD_NEED_RUNNING,
8362 .doit = wlan_hdd_cfg80211_ocb_set_config
8363 },
8364 {
8365 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8366 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8367 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8368 WIPHY_VENDOR_CMD_NEED_NETDEV |
8369 WIPHY_VENDOR_CMD_NEED_RUNNING,
8370 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8371 },
8372 {
8373 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8374 .info.subcmd =
8375 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8376 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8377 WIPHY_VENDOR_CMD_NEED_NETDEV |
8378 WIPHY_VENDOR_CMD_NEED_RUNNING,
8379 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8380 },
8381 {
8382 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8383 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8384 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8385 WIPHY_VENDOR_CMD_NEED_NETDEV |
8386 WIPHY_VENDOR_CMD_NEED_RUNNING,
8387 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8388 },
8389 {
8390 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8391 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8392 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8393 WIPHY_VENDOR_CMD_NEED_NETDEV |
8394 WIPHY_VENDOR_CMD_NEED_RUNNING,
8395 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8396 },
8397 {
8398 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8399 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8400 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8401 WIPHY_VENDOR_CMD_NEED_NETDEV |
8402 WIPHY_VENDOR_CMD_NEED_RUNNING,
8403 .doit = wlan_hdd_cfg80211_dcc_get_stats
8404 },
8405 {
8406 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8407 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8408 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8409 WIPHY_VENDOR_CMD_NEED_NETDEV |
8410 WIPHY_VENDOR_CMD_NEED_RUNNING,
8411 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8412 },
8413 {
8414 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8415 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8416 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8417 WIPHY_VENDOR_CMD_NEED_NETDEV |
8418 WIPHY_VENDOR_CMD_NEED_RUNNING,
8419 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8420 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308421 {
8422 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8423 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8425 WIPHY_VENDOR_CMD_NEED_NETDEV |
8426 WIPHY_VENDOR_CMD_NEED_RUNNING,
8427 .doit = wlan_hdd_cfg80211_get_link_properties
8428 },
Peng Xu278d0122015-09-24 16:34:17 -07008429 {
Peng Xud2220962016-07-11 17:59:17 -07008430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008431 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8432 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8433 WIPHY_VENDOR_CMD_NEED_NETDEV |
8434 WIPHY_VENDOR_CMD_NEED_RUNNING,
8435 .doit = wlan_hdd_cfg80211_set_ota_test
8436 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008437#ifdef FEATURE_LFR_SUBNET_DETECTION
8438 {
8439 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8440 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8441 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8442 WIPHY_VENDOR_CMD_NEED_NETDEV |
8443 WIPHY_VENDOR_CMD_NEED_RUNNING,
8444 .doit = wlan_hdd_cfg80211_set_gateway_params
8445 },
8446#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008447 {
Peng Xud2220962016-07-11 17:59:17 -07008448 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008449 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8450 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8451 WIPHY_VENDOR_CMD_NEED_NETDEV |
8452 WIPHY_VENDOR_CMD_NEED_RUNNING,
8453 .doit = wlan_hdd_cfg80211_txpower_scale
8454 },
8455 {
8456 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8457 .info.subcmd =
8458 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8459 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8460 WIPHY_VENDOR_CMD_NEED_NETDEV |
8461 WIPHY_VENDOR_CMD_NEED_RUNNING,
8462 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8463 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308464 {
8465 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8466 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8467 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8468 WIPHY_VENDOR_CMD_NEED_NETDEV |
8469 WIPHY_VENDOR_CMD_NEED_RUNNING,
8470 .doit = wlan_hdd_cfg80211_bpf_offload
8471 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308472 {
8473 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308474 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8475 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8476 WIPHY_VENDOR_CMD_NEED_NETDEV |
8477 WIPHY_VENDOR_CMD_NEED_RUNNING,
8478 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8479 },
8480 {
8481 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308482 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8483 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8484 WIPHY_VENDOR_CMD_NEED_NETDEV |
8485 WIPHY_VENDOR_CMD_NEED_RUNNING,
8486 .doit = wlan_hdd_cfg80211_sta_roam_policy
8487 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308488#ifdef FEATURE_WLAN_CH_AVOID
8489 {
8490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8491 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8492 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8493 WIPHY_VENDOR_CMD_NEED_NETDEV |
8494 WIPHY_VENDOR_CMD_NEED_RUNNING,
8495 .doit = wlan_hdd_cfg80211_avoid_freq
8496 },
8497#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308498 {
8499 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308500 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8501 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8502 WIPHY_VENDOR_CMD_NEED_NETDEV |
8503 WIPHY_VENDOR_CMD_NEED_RUNNING,
8504 .doit = wlan_hdd_cfg80211_sap_configuration_set
8505 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008506 {
Peng Xu4225c152016-07-14 21:18:14 -07008507 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008508 .info.subcmd =
8509 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8510 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8511 WIPHY_VENDOR_CMD_NEED_NETDEV |
8512 WIPHY_VENDOR_CMD_NEED_RUNNING,
8513 .doit = wlan_hdd_cfg80211_p2p_lo_start
8514 },
8515 {
8516 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8517 .info.subcmd =
8518 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8519 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8520 WIPHY_VENDOR_CMD_NEED_NETDEV |
8521 WIPHY_VENDOR_CMD_NEED_RUNNING,
8522 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8523 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308524 {
8525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8526 .info.subcmd =
8527 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8529 WIPHY_VENDOR_CMD_NEED_NETDEV |
8530 WIPHY_VENDOR_CMD_NEED_RUNNING,
8531 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8532 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008533#ifdef WLAN_FEATURE_NAN_DATAPATH
8534 {
8535 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8536 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8537 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8538 WIPHY_VENDOR_CMD_NEED_NETDEV |
8539 WIPHY_VENDOR_CMD_NEED_RUNNING,
8540 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8541 },
8542#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308543 {
8544 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8545 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8546 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8547 WIPHY_VENDOR_CMD_NEED_NETDEV |
8548 WIPHY_VENDOR_CMD_NEED_RUNNING,
8549 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8550 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308551 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8555 WIPHY_VENDOR_CMD_NEED_NETDEV |
8556 WIPHY_VENDOR_CMD_NEED_RUNNING,
8557 .doit = wlan_hdd_cfg80211_get_bus_size
8558 },
8559 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308560 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8561 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8562 WIPHY_VENDOR_CMD_NEED_NETDEV |
8563 WIPHY_VENDOR_CMD_NEED_RUNNING,
8564 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308565 },
8566 {
8567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8568 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8569 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8570 WIPHY_VENDOR_CMD_NEED_NETDEV |
8571 WIPHY_VENDOR_CMD_NEED_RUNNING,
8572 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308573 },
8574#ifdef WLAN_FEATURE_DISA
8575 {
8576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8577 .info.subcmd =
8578 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8579 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8580 WIPHY_VENDOR_CMD_NEED_NETDEV |
8581 WIPHY_VENDOR_CMD_NEED_RUNNING,
8582 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8583 },
8584#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008585};
8586
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008587/**
8588 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8589 * @priv_size: Size of the hdd context.
8590 *
8591 * Allocate wiphy context and hdd context.
8592 *
8593 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008594 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008595hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008596{
8597 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008598 hdd_context_t *hdd_ctx;
8599
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008600 ENTER();
8601
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008602 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8603
8604 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008605 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008606 return NULL;
8607 }
8608
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008609 hdd_ctx = wiphy_priv(wiphy);
8610
8611 hdd_ctx->wiphy = wiphy;
8612
8613 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008614}
8615
8616/*
8617 * FUNCTION: wlan_hdd_cfg80211_update_band
8618 * This function is called from the supplicant through a
8619 * private ioctl to change the band value
8620 */
8621int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8622{
8623 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008624 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008625
8626 ENTER();
8627
Dustin Browna30892e2016-10-12 17:28:36 -07008628 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008629
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008630 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008631 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008632
8633 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8634 struct ieee80211_supported_band *band = wiphy->bands[i];
8635
8636 channelEnabledState =
8637 cds_get_channel_state(band->channels[j].
8638 hw_value);
8639
Dustin Browna30892e2016-10-12 17:28:36 -07008640 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008641 /* 5G only */
8642#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8643 /* Enable Social channels for P2P */
8644 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8645 (band->channels[j].center_freq)
8646 && CHANNEL_STATE_ENABLE ==
8647 channelEnabledState)
8648 band->channels[j].flags &=
8649 ~IEEE80211_CHAN_DISABLED;
8650 else
8651#endif
8652 band->channels[j].flags |=
8653 IEEE80211_CHAN_DISABLED;
8654 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008655 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008656 eCSR_BAND_24 == eBand) {
8657 /* 2G only */
8658 band->channels[j].flags |=
8659 IEEE80211_CHAN_DISABLED;
8660 continue;
8661 }
8662
Amar Singhal6842e8f2016-02-23 16:30:32 -08008663 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008664 band->channels[j].flags &=
8665 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008666 }
8667 }
8668 return 0;
8669}
8670
8671/*
8672 * FUNCTION: wlan_hdd_cfg80211_init
8673 * This function is called by hdd_wlan_startup()
8674 * during initialization.
8675 * This function is used to initialize and register wiphy structure.
8676 */
8677int wlan_hdd_cfg80211_init(struct device *dev,
8678 struct wiphy *wiphy, struct hdd_config *pCfg)
8679{
8680 int i, j;
8681 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8682
8683 ENTER();
8684
8685 /* Now bind the underlying wlan device with wiphy */
8686 set_wiphy_dev(wiphy, dev);
8687
8688 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008690#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8691 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008692 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008693#else
8694 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008695 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008696#endif
8697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008698 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8699 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8700 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8701#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8702 | WIPHY_FLAG_4ADDR_STATION
8703#endif
8704 | WIPHY_FLAG_OFFCHAN_TX;
8705
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8707 wiphy->wowlan = &wowlan_support_cfg80211_init;
8708#else
8709 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8710 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8711 wiphy->wowlan.pattern_min_len = 1;
8712 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8713#endif
8714
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008715 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008716#ifdef FEATURE_WLAN_ESE
8717 || pCfg->isEseIniFeatureEnabled
8718#endif
8719 ) {
8720 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8721 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008722#ifdef FEATURE_WLAN_TDLS
8723 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8724 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8725#endif
8726
8727 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8728
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008729#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8730 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8731#endif
8732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008733#ifdef FEATURE_WLAN_SCAN_PNO
8734 if (pCfg->configPNOScanSupport) {
8735 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8736 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8737 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8738 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008739#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8740 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8741#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008742 }
8743#endif /*FEATURE_WLAN_SCAN_PNO */
8744
8745#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308746 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008747#endif
8748
8749 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8750 driver can still register regulatory callback and
8751 it will get regulatory settings in wiphy->band[], but
8752 driver need to determine what to do with both
8753 regulatory settings */
8754
8755 wiphy->reg_notifier = hdd_reg_notifier;
8756
8757#if defined QCA_WIFI_FTM
8758}
8759#endif
8760
8761 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8762
8763 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8764
8765 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8766
Arun Khandavallifae92942016-08-01 13:31:08 +05308767 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8768 | BIT(NL80211_IFTYPE_ADHOC)
8769 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8770 | BIT(NL80211_IFTYPE_P2P_GO)
8771 | BIT(NL80211_IFTYPE_AP)
8772 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008773
Arun Khandavallifae92942016-08-01 13:31:08 +05308774 if (pCfg->advertiseConcurrentOperation) {
8775 if (pCfg->enableMCC) {
8776 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008777
Arun Khandavallifae92942016-08-01 13:31:08 +05308778 for (i = 0;
8779 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8780 i++) {
8781 if (!pCfg->allowMCCGODiffBI)
8782 wlan_hdd_iface_combination[i].
8783 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008784 }
8785 }
8786 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308787 ARRAY_SIZE(wlan_hdd_iface_combination);
8788 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008789 }
8790
8791 /* Before registering we need to update the ht capabilitied based
8792 * on ini values*/
8793 if (!pCfg->ShortGI20MhzEnable) {
8794 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8795 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008796 }
8797
8798 if (!pCfg->ShortGI40MhzEnable) {
8799 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8800 }
8801
8802 if (!pCfg->nChannelBondingMode5GHz) {
8803 wlan_hdd_band_5_ghz.ht_cap.cap &=
8804 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8805 }
8806
Abhishek Singhf512bf32016-05-04 16:47:46 +05308807 /*
8808 * In case of static linked driver at the time of driver unload,
8809 * module exit doesn't happens. Module cleanup helps in cleaning
8810 * of static memory.
8811 * If driver load happens statically, at the time of driver unload,
8812 * wiphy flags don't get reset because of static memory.
8813 * It's better not to store channel in static memory.
8814 */
Dustin Browna30892e2016-10-12 17:28:36 -07008815 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8816 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308817 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008818 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308819 hdd_err("Not enough memory to allocate channels");
8820 return -ENOMEM;
8821 }
Dustin Browna30892e2016-10-12 17:28:36 -07008822 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308823 &hdd_channels_2_4_ghz[0],
8824 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308825 if ((hdd_is_5g_supported(pHddCtx)) &&
8826 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8827 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8828 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8829 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008830 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8831 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308832 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008833 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308834 hdd_err("Not enough memory to allocate channels");
8835 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008836 bands[NL80211_BAND_2GHZ]->channels);
8837 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308838 return -ENOMEM;
8839 }
Dustin Browna30892e2016-10-12 17:28:36 -07008840 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308841 &hdd_channels_5_ghz[0],
8842 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008843 }
8844
Dustin Browna30892e2016-10-12 17:28:36 -07008845 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008846
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008847 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008848 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008849
8850 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8851 struct ieee80211_supported_band *band = wiphy->bands[i];
8852
Dustin Browna30892e2016-10-12 17:28:36 -07008853 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008854 eCSR_BAND_5G == pCfg->nBandCapability) {
8855 /* 5G only */
8856#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8857 /* Enable social channels for P2P */
8858 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8859 (band->channels[j].center_freq))
8860 band->channels[j].flags &=
8861 ~IEEE80211_CHAN_DISABLED;
8862 else
8863#endif
8864 band->channels[j].flags |=
8865 IEEE80211_CHAN_DISABLED;
8866 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008867 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008868 eCSR_BAND_24 == pCfg->nBandCapability) {
8869 /* 2G only */
8870 band->channels[j].flags |=
8871 IEEE80211_CHAN_DISABLED;
8872 continue;
8873 }
8874 }
8875 }
8876 /*Initialise the supported cipher suite details */
8877 wiphy->cipher_suites = hdd_cipher_suites;
8878 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8879
8880 /*signal strength in mBm (100*dBm) */
8881 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8882 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8883
Anurag Chouhan6d760662016-02-20 16:05:43 +05308884 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008885 wiphy->n_vendor_commands =
8886 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8887 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8888
8889 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8890 wiphy->n_vendor_events =
8891 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8892 }
8893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008894 if (pCfg->enableDFSMasterCap) {
8895 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8896 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008897
8898 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8899
8900#ifdef QCA_HT_2040_COEX
8901 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8902#endif
8903
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308904 hdd_add_channel_switch_support(&wiphy->flags);
8905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008906 EXIT();
8907 return 0;
8908}
8909
Abhishek Singhf512bf32016-05-04 16:47:46 +05308910/**
8911 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8912 * @ wiphy: the wiphy to validate against
8913 *
8914 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308915 * memory allocated in wlan_hdd_cfg80211_init also
8916 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308917 *
8918 * Return: void
8919 */
8920void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8921{
8922 int i;
8923
Dustin Browna30892e2016-10-12 17:28:36 -07008924 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308925 if (NULL != wiphy->bands[i] &&
8926 (NULL != wiphy->bands[i]->channels)) {
8927 qdf_mem_free(wiphy->bands[i]->channels);
8928 wiphy->bands[i]->channels = NULL;
8929 }
8930 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308931 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308932}
8933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008934/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308935 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008936 * initialization. In wlan_hdd_cfg80211_init, only the
8937 * default values will be initialized. The final initialization
8938 * of all required members can be done here.
8939 */
8940void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8941{
8942 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8943}
8944
8945/* In this function we are registering wiphy. */
8946int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8947{
8948 ENTER();
8949 /* Register our wiphy dev with cfg80211 */
8950 if (0 > wiphy_register(wiphy)) {
8951 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008952 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008953 return -EIO;
8954 }
8955
8956 EXIT();
8957 return 0;
8958}
8959
8960/*
8961 HDD function to update wiphy capability based on target offload status.
8962
8963 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8964 capability even before downloading firmware to the target. In discrete
8965 case, host will get know certain offload capability (say sched_scan
8966 caps) only after downloading firmware to the target and target boots up.
8967 This function is used to override setting done in wlan_hdd_cfg80211_init()
8968 based on target capability.
8969 */
8970void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8971{
8972#ifdef FEATURE_WLAN_SCAN_PNO
8973 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8974 struct hdd_config *pCfg = pHddCtx->config;
8975
8976 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8977 * control comes here. Here just we need to clear it if firmware doesn't
8978 * have PNO support. */
8979 if (!pCfg->PnoOffload) {
8980 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8981 wiphy->max_sched_scan_ssids = 0;
8982 wiphy->max_match_sets = 0;
8983 wiphy->max_sched_scan_ie_len = 0;
8984 }
8985#endif
8986}
8987
8988/* This function registers for all frame which supplicant is interested in */
8989void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8990{
8991 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8992 /* Register for all P2P action, public action etc frames */
8993 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8994
8995 ENTER();
8996
Abhishek Singh7996eb72015-12-30 17:24:02 +05308997 /* Register frame indication call back */
8998 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8999
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309000 /* Register for p2p ack indication */
9001 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9002
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009003 /* Right now we are registering these frame when driver is getting
9004 initialized. Once we will move to 2.6.37 kernel, in which we have
9005 frame register ops, we will move this code as a part of that */
9006 /* GAS Initial Request */
9007 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9008 (uint8_t *) GAS_INITIAL_REQ,
9009 GAS_INITIAL_REQ_SIZE);
9010
9011 /* GAS Initial Response */
9012 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9013 (uint8_t *) GAS_INITIAL_RSP,
9014 GAS_INITIAL_RSP_SIZE);
9015
9016 /* GAS Comeback Request */
9017 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9018 (uint8_t *) GAS_COMEBACK_REQ,
9019 GAS_COMEBACK_REQ_SIZE);
9020
9021 /* GAS Comeback Response */
9022 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9023 (uint8_t *) GAS_COMEBACK_RSP,
9024 GAS_COMEBACK_RSP_SIZE);
9025
9026 /* P2P Public Action */
9027 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9028 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9029 P2P_PUBLIC_ACTION_FRAME_SIZE);
9030
9031 /* P2P Action */
9032 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9033 (uint8_t *) P2P_ACTION_FRAME,
9034 P2P_ACTION_FRAME_SIZE);
9035
9036 /* WNM BSS Transition Request frame */
9037 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9038 (uint8_t *) WNM_BSS_ACTION_FRAME,
9039 WNM_BSS_ACTION_FRAME_SIZE);
9040
9041 /* WNM-Notification */
9042 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9043 (uint8_t *) WNM_NOTIFICATION_FRAME,
9044 WNM_NOTIFICATION_FRAME_SIZE);
9045}
9046
9047void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9048{
9049 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9050 /* Register for all P2P action, public action etc frames */
9051 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9052
9053 ENTER();
9054
9055 /* Right now we are registering these frame when driver is getting
9056 initialized. Once we will move to 2.6.37 kernel, in which we have
9057 frame register ops, we will move this code as a part of that */
9058 /* GAS Initial Request */
9059
9060 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9061 (uint8_t *) GAS_INITIAL_REQ,
9062 GAS_INITIAL_REQ_SIZE);
9063
9064 /* GAS Initial Response */
9065 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9066 (uint8_t *) GAS_INITIAL_RSP,
9067 GAS_INITIAL_RSP_SIZE);
9068
9069 /* GAS Comeback Request */
9070 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9071 (uint8_t *) GAS_COMEBACK_REQ,
9072 GAS_COMEBACK_REQ_SIZE);
9073
9074 /* GAS Comeback Response */
9075 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9076 (uint8_t *) GAS_COMEBACK_RSP,
9077 GAS_COMEBACK_RSP_SIZE);
9078
9079 /* P2P Public Action */
9080 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9081 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9082 P2P_PUBLIC_ACTION_FRAME_SIZE);
9083
9084 /* P2P Action */
9085 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9086 (uint8_t *) P2P_ACTION_FRAME,
9087 P2P_ACTION_FRAME_SIZE);
9088
9089 /* WNM-Notification */
9090 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9091 (uint8_t *) WNM_NOTIFICATION_FRAME,
9092 WNM_NOTIFICATION_FRAME_SIZE);
9093}
9094
9095#ifdef FEATURE_WLAN_WAPI
9096void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9097 const uint8_t *mac_addr, const uint8_t *key,
9098 int key_Len)
9099{
9100 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9101 tCsrRoamSetKey setKey;
9102 bool isConnected = true;
9103 int status = 0;
9104 uint32_t roamId = 0xFF;
9105 uint8_t *pKeyPtr = NULL;
9106 int n = 0;
9107
Jeff Johnson46b40792016-06-29 14:03:14 -07009108 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009109 hdd_device_mode_to_string(pAdapter->device_mode),
9110 pAdapter->device_mode);
9111
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309112 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113 setKey.keyId = key_index; /* Store Key ID */
9114 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9115 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9116 setKey.paeRole = 0; /* the PAE role */
9117 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309118 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009119 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309120 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009121 }
9122 setKey.keyLength = key_Len;
9123 pKeyPtr = setKey.Key;
9124 memcpy(pKeyPtr, key, key_Len);
9125
Jeff Johnson46b40792016-06-29 14:03:14 -07009126 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009127 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009128 hdd_notice("WAPI KEY Data[%d]:%02x ",
9129 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009130
9131 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9132 if (isConnected) {
9133 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9134 pAdapter->sessionId, &setKey, &roamId);
9135 }
9136 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009137 hdd_err("sme_roam_set_key returned ERROR status= %d",
9138 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009139 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9140 }
9141}
9142#endif /* FEATURE_WLAN_WAPI */
9143
9144uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9145 uint8_t eid)
9146{
9147 int left = length;
9148 uint8_t *ptr = (uint8_t *)ies_ptr;
9149 uint8_t elem_id, elem_len;
9150
9151 while (left >= 2) {
9152 elem_id = ptr[0];
9153 elem_len = ptr[1];
9154 left -= 2;
9155 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009156 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009157 eid, elem_len, left);
9158 return NULL;
9159 }
9160 if (elem_id == eid) {
9161 return ptr;
9162 }
9163
9164 left -= elem_len;
9165 ptr += (elem_len + 2);
9166 }
9167 return NULL;
9168}
9169
9170/*
9171 * FUNCTION: wlan_hdd_validate_operation_channel
9172 * called by wlan_hdd_cfg80211_start_bss() and
9173 * wlan_hdd_set_channel()
9174 * This function validates whether given channel is part of valid
9175 * channel list.
9176 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309177QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009178 int channel)
9179{
9180
9181 uint32_t num_ch = 0;
9182 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9183 u32 indx = 0;
9184 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9185 uint8_t fValidChannel = false, count = 0;
9186 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9187
9188 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9189
9190 if (hdd_pConfig_ini->sapAllowAllChannel) {
9191 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009192 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009193 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009194 fValidChannel = true;
9195 break;
9196 }
9197 }
9198 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009199 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309200 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009201 }
9202 } else {
9203 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9204 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009205 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309206 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009207 }
9208 for (indx = 0; indx < num_ch; indx++) {
9209 if (channel == valid_ch[indx]) {
9210 break;
9211 }
9212 }
9213
9214 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009215 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309216 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009217 }
9218 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309219 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009220
9221}
9222
9223#ifdef DHCP_SERVER_OFFLOAD
9224static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9225{
9226 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9227 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9228 uint8_t numEntries = 0;
9229 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9230 uint8_t num;
9231 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309232 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009233 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009234 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009235 return;
9236 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009237 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9238 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9239 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9240 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9241 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9242 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009243 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009244 goto end;
9245 }
9246 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009247 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009248 goto end;
9249 }
9250 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009251 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009252 goto end;
9253 }
9254 for (num = 0; num < numEntries; num++) {
9255 temp = srv_ip[num];
9256 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9257 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309258 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009259 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009260 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009261 goto end;
9262 }
Jeff Johnson77848112016-06-29 14:52:06 -07009263 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009264end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309265 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009266 return;
9267}
9268#endif /* DHCP_SERVER_OFFLOAD */
9269
9270static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9271 struct net_device *dev,
9272 struct bss_parameters *params)
9273{
9274 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9275 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9276 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309277 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009278
9279 ENTER();
9280
Anurag Chouhan6d760662016-02-20 16:05:43 +05309281 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009282 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009283 return -EINVAL;
9284 }
9285
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309286 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009287 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9288 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009289 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009290 hdd_device_mode_to_string(pAdapter->device_mode),
9291 pAdapter->device_mode, params->ap_isolate);
9292
9293 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9294 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309295 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009296 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009297
Krunal Sonib4326f22016-03-10 13:05:51 -08009298 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9299 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009300 return -EOPNOTSUPP;
9301 }
9302
9303 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9304 * want to update this parameter */
9305 if (-1 != params->ap_isolate) {
9306 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9307 !!params->ap_isolate;
9308
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309309 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009310 pAdapter->sessionId,
9311 pAdapter->sessionCtx.
9312 ap.
9313 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309314 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009315 ret = -EINVAL;
9316 }
9317 }
9318
9319 EXIT();
9320 return ret;
9321}
9322
Krunal Soni8c37e322016-02-03 16:08:37 -08009323/**
9324 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9325 * @ndev: pointer to net device provided by supplicant
9326 * @type: type of the interface, upper layer wanted to change
9327 *
9328 * Upper layer provides the new interface mode that needs to be changed
9329 * for given net device
9330 *
9331 * Return: success or failure in terms of integer value
9332 */
9333static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009334 enum nl80211_iftype type)
9335{
Krunal Soni8c37e322016-02-03 16:08:37 -08009336 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9337 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9338 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009339 hdd_wext_state_t *wext;
9340 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309341 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342
9343 ENTER();
9344
Krunal Soni8c37e322016-02-03 16:08:37 -08009345 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009346 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347 return 0;
9348 }
9349
9350 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009351 hdd_stop_adapter(hdd_ctx, adapter, true);
9352 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009353 wdev->iftype = type;
9354 /*Check for sub-string p2p to confirm its a p2p interface */
9355 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009356 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009357 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009358 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009359 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009360 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009361 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009362 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009363 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009364 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009365 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009366 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9367 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009368 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9369 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009370 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009371 adapter->scan_info.scanAddIE.length;
9372 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309373 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009374 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9375 wext->roamProfile.phyMode =
9376 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9377 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009378 EXIT();
9379 return status;
9380}
9381
9382static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9383 struct net_device *dev,
9384 struct bss_parameters *params)
9385{
9386 int ret;
9387
9388 cds_ssr_protect(__func__);
9389 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9390 cds_ssr_unprotect(__func__);
9391
9392 return ret;
9393}
9394
9395/* FUNCTION: wlan_hdd_change_country_code_cd
9396 * to wait for contry code completion
9397 */
9398void *wlan_hdd_change_country_code_cb(void *pAdapter)
9399{
9400 hdd_adapter_t *call_back_pAdapter = pAdapter;
9401 complete(&call_back_pAdapter->change_country_code);
9402 return NULL;
9403}
9404
Rajeev Kumar98edb772016-01-19 12:42:19 -08009405/**
9406 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9407 * @wiphy: Pointer to the wiphy structure
9408 * @ndev: Pointer to the net device
9409 * @type: Interface type
9410 * @flags: Flags for change interface
9411 * @params: Pointer to change interface parameters
9412 *
9413 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009414 */
9415static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9416 struct net_device *ndev,
9417 enum nl80211_iftype type,
9418 u32 *flags,
9419 struct vif_params *params)
9420{
9421 struct wireless_dev *wdev;
9422 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9423 hdd_context_t *pHddCtx;
9424 tCsrRoamProfile *pRoamProfile = NULL;
9425 eCsrRoamBssType LastBSSType;
9426 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309427 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009428 int status;
9429
9430 ENTER();
9431
Anurag Chouhan6d760662016-02-20 16:05:43 +05309432 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009433 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009434 return -EINVAL;
9435 }
9436
9437 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9438 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309439 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009441
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309442 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009443 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9444 pAdapter->sessionId, type));
9445
Jeff Johnson77848112016-06-29 14:52:06 -07009446 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009447 pAdapter->device_mode, type);
9448
Arun Khandavallifae92942016-08-01 13:31:08 +05309449 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9450 if (status) {
9451 hdd_err("Failed to start modules");
9452 return -EINVAL;
9453 }
9454
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009455 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009456 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9457 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009458 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009459 return -EINVAL;
9460 }
9461
9462 pConfig = pHddCtx->config;
9463 wdev = ndev->ieee80211_ptr;
9464
9465 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009466 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009467
9468 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9469
Krunal Sonib4326f22016-03-10 13:05:51 -08009470 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9471 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9472 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9473 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009474 hdd_wext_state_t *pWextState =
9475 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9476
9477 pRoamProfile = &pWextState->roamProfile;
9478 LastBSSType = pRoamProfile->BSSType;
9479
9480 switch (type) {
9481 case NL80211_IFTYPE_STATION:
9482 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009483 case NL80211_IFTYPE_ADHOC:
9484 if (type == NL80211_IFTYPE_ADHOC) {
9485 wlan_hdd_tdls_exit(pAdapter);
9486 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009487 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009488 }
9489 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9490 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309491 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009492 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309493 if (hdd_start_adapter(pAdapter)) {
9494 hdd_err("Failed to start adapter :%d",
9495 pAdapter->device_mode);
9496 return -EINVAL;
9497 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009498 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009499 case NL80211_IFTYPE_AP:
9500 case NL80211_IFTYPE_P2P_GO:
9501 {
Jeff Johnson77848112016-06-29 14:52:06 -07009502 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009503 (type ==
9504 NL80211_IFTYPE_AP) ? "SoftAP" :
9505 "P2pGo");
9506
9507 /* Cancel any remain on channel for GO mode */
9508 if (NL80211_IFTYPE_P2P_GO == type) {
9509 wlan_hdd_cancel_existing_remain_on_channel
9510 (pAdapter);
9511 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009512
Arun Khandavallifae92942016-08-01 13:31:08 +05309513 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009514 /* De-init the adapter */
9515 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9516 memset(&pAdapter->sessionCtx, 0,
9517 sizeof(pAdapter->sessionCtx));
9518 pAdapter->device_mode =
9519 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009520 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9521 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009522
9523 /*
9524 * Fw will take care incase of concurrency
9525 */
9526
Krunal Sonib4326f22016-03-10 13:05:51 -08009527 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009528 && (pConfig->apRandomBssidEnabled)) {
9529 /* To meet Android requirements create a randomized
9530 MAC address of the form 02:1A:11:Fx:xx:xx */
9531 get_random_bytes(&ndev->dev_addr[3], 3);
9532 ndev->dev_addr[0] = 0x02;
9533 ndev->dev_addr[1] = 0x1A;
9534 ndev->dev_addr[2] = 0x11;
9535 ndev->dev_addr[3] |= 0xF0;
9536 memcpy(pAdapter->macAddressCurrent.
9537 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309538 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009539 pr_info("wlan: Generated HotSpot BSSID "
9540 MAC_ADDRESS_STR "\n",
9541 MAC_ADDR_ARRAY(ndev->dev_addr));
9542 }
9543
9544 hdd_set_ap_ops(pAdapter->dev);
9545
Arun Khandavallifae92942016-08-01 13:31:08 +05309546 if (hdd_start_adapter(pAdapter)) {
9547 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009548 return -EINVAL;
9549 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009550 /* Interface type changed update in wiphy structure */
9551 if (wdev) {
9552 wdev->iftype = type;
9553 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009554 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009555 return -EINVAL;
9556 }
9557 goto done;
9558 }
9559
9560 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009561 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009562 type);
9563 return -EOPNOTSUPP;
9564 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009565 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9566 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009567 switch (type) {
9568 case NL80211_IFTYPE_STATION:
9569 case NL80211_IFTYPE_P2P_CLIENT:
9570 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009571 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9572 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309573 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009574 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309575 if (hdd_start_adapter(pAdapter)) {
9576 hdd_err("Failed to start adapter :%d",
9577 pAdapter->device_mode);
9578 return -EINVAL;
9579 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009580 goto done;
9581
9582 case NL80211_IFTYPE_AP:
9583 case NL80211_IFTYPE_P2P_GO:
9584 wdev->iftype = type;
9585 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009586 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009587 goto done;
9588
9589 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009590 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009591 type);
9592 return -EOPNOTSUPP;
9593 }
9594 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009595 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009596 pAdapter->device_mode);
9597 return -EOPNOTSUPP;
9598 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009599done:
9600 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009601 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009602
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009603 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009604
9605 EXIT();
9606 return 0;
9607}
9608
Rajeev Kumar98edb772016-01-19 12:42:19 -08009609/**
9610 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9611 * @wiphy: Pointer to the wiphy structure
9612 * @ndev: Pointer to the net device
9613 * @type: Interface type
9614 * @flags: Flags for change interface
9615 * @params: Pointer to change interface parameters
9616 *
9617 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009618 */
9619static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9620 struct net_device *ndev,
9621 enum nl80211_iftype type,
9622 u32 *flags,
9623 struct vif_params *params)
9624{
9625 int ret;
9626
9627 cds_ssr_protect(__func__);
9628 ret =
9629 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9630 cds_ssr_unprotect(__func__);
9631
9632 return ret;
9633}
9634
9635#ifdef FEATURE_WLAN_TDLS
9636static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9637 int index, uint8_t match)
9638{
9639 int i;
9640 for (i = 0; i < index; i++) {
9641 if (arr[i] == match)
9642 return true;
9643 }
9644 return false;
9645}
9646#endif
9647
9648/**
9649 * __wlan_hdd_change_station() - change station
9650 * @wiphy: Pointer to the wiphy structure
9651 * @dev: Pointer to the net device.
9652 * @mac: bssid
9653 * @params: Pointer to station parameters
9654 *
9655 * Return: 0 for success, error number on failure.
9656 */
9657#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9658static int __wlan_hdd_change_station(struct wiphy *wiphy,
9659 struct net_device *dev,
9660 const uint8_t *mac,
9661 struct station_parameters *params)
9662#else
9663static int __wlan_hdd_change_station(struct wiphy *wiphy,
9664 struct net_device *dev,
9665 uint8_t *mac,
9666 struct station_parameters *params)
9667#endif
9668{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309669 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009670 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9671 hdd_context_t *pHddCtx;
9672 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309673 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009674#ifdef FEATURE_WLAN_TDLS
9675 tCsrStaParams StaParams = { 0 };
9676 uint8_t isBufSta = 0;
9677 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309678 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009679#endif
9680 int ret;
9681
9682 ENTER();
9683
Anurag Chouhan6d760662016-02-20 16:05:43 +05309684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009685 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686 return -EINVAL;
9687 }
9688
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309689 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009690 TRACE_CODE_HDD_CHANGE_STATION,
9691 pAdapter->sessionId, params->listen_interval));
9692
9693 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9694 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309695 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009696 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009697
9698 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9699
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309700 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701
Krunal Sonib4326f22016-03-10 13:05:51 -08009702 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9703 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009704 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9705 status =
9706 hdd_softap_change_sta_state(pAdapter,
9707 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009708 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009709
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309710 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009711 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009712 return -EINVAL;
9713 }
9714 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009715 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9716 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717#ifdef FEATURE_WLAN_TDLS
9718 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009719
9720 if (cds_is_sub_20_mhz_enabled()) {
9721 hdd_err("TDLS not allowed with sub 20 MHz");
9722 return -EINVAL;
9723 }
9724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009725 StaParams.capability = params->capability;
9726 StaParams.uapsd_queues = params->uapsd_queues;
9727 StaParams.max_sp = params->max_sp;
9728
9729 /* Convert (first channel , number of channels) tuple to
9730 * the total list of channels. This goes with the assumption
9731 * that if the first channel is < 14, then the next channels
9732 * are an incremental of 1 else an incremental of 4 till the number
9733 * of channels.
9734 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009735 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009736 if (0 != params->supported_channels_len) {
9737 int i = 0, j = 0, k = 0, no_of_channels = 0;
9738 int num_unique_channels;
9739 int next;
9740 for (i = 0;
9741 i < params->supported_channels_len
9742 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9743 int wifi_chan_index;
9744 if (!wlan_hdd_is_duplicate_channel
9745 (StaParams.supported_channels, j,
9746 params->supported_channels[i])) {
9747 StaParams.
9748 supported_channels[j] =
9749 params->
9750 supported_channels[i];
9751 } else {
9752 continue;
9753 }
9754 wifi_chan_index =
9755 ((StaParams.supported_channels[j] <=
9756 HDD_CHANNEL_14) ? 1 : 4);
9757 no_of_channels =
9758 params->supported_channels[i + 1];
9759
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009760 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 -08009761 StaParams.
9762 supported_channels[j],
9763 wifi_chan_index,
9764 no_of_channels);
9765 for (k = 1; k <= no_of_channels &&
9766 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9767 k++) {
9768 next =
9769 StaParams.
9770 supported_channels[j] +
9771 wifi_chan_index;
9772 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9773 StaParams.
9774 supported_channels[j
9775 +
9776 1]
9777 = next;
9778 } else {
9779 continue;
9780 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009781 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009782 j + 1,
9783 StaParams.
9784 supported_channels[j +
9785 1]);
9786 j += 1;
9787 }
9788 }
9789 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009790 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009792 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009793 StaParams.
9794 supported_channels[i]);
9795 }
9796 if (MAX_CHANNEL < num_unique_channels)
9797 num_unique_channels = MAX_CHANNEL;
9798 StaParams.supported_channels_len =
9799 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009800 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009801 StaParams.supported_channels_len);
9802 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309803 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009804 params->supported_oper_classes,
9805 params->supported_oper_classes_len);
9806 StaParams.supported_oper_classes_len =
9807 params->supported_oper_classes_len;
9808
9809 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309810 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009811 params->ext_capab,
9812 sizeof(StaParams.extn_capability));
9813
9814 if (NULL != params->ht_capa) {
9815 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309816 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009817 sizeof(tSirHTCap));
9818 }
9819
9820 StaParams.supported_rates_len =
9821 params->supported_rates_len;
9822
9823 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9824 * The supported_rates array , for all the structures propogating till Add Sta
9825 * to the firmware has to be modified , if the supplicant (ieee80211) is
9826 * modified to send more rates.
9827 */
9828
9829 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9830 */
9831 if (StaParams.supported_rates_len >
9832 SIR_MAC_MAX_SUPP_RATES)
9833 StaParams.supported_rates_len =
9834 SIR_MAC_MAX_SUPP_RATES;
9835
9836 if (0 != StaParams.supported_rates_len) {
9837 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309838 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009839 params->supported_rates,
9840 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009841 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009842 StaParams.supported_rates_len);
9843 for (i = 0; i < StaParams.supported_rates_len;
9844 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009845 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009846 StaParams.supported_rates[i]);
9847 }
9848
9849 if (NULL != params->vht_capa) {
9850 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309851 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009852 params->vht_capa,
9853 sizeof(tSirVHTCap));
9854 }
9855
9856 if (0 != params->ext_capab_len) {
9857 /*Define A Macro : TODO Sunil */
9858 if ((1 << 4) & StaParams.extn_capability[3]) {
9859 isBufSta = 1;
9860 }
9861 /* TDLS Channel Switching Support */
9862 if ((1 << 6) & StaParams.extn_capability[3]) {
9863 isOffChannelSupported = 1;
9864 }
9865 }
9866
Nitesh Shah99934ac2016-09-05 15:54:08 +05309867 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309868 (params->ht_capa || params->vht_capa ||
9869 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309870 is_qos_wmm_sta = true;
9871
9872 hdd_notice("%s: TDLS Peer is QOS capable"
9873 " is_qos_wmm_sta= %d HTcapPresent = %d",
9874 __func__, is_qos_wmm_sta,
9875 StaParams.htcap_present);
9876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009877 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309878 &StaParams,
9879 isBufSta,
9880 isOffChannelSupported,
9881 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309882 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009883 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009884 return -EINVAL;
9885 }
9886
9887 status =
9888 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9889 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309890 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009891 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009892 return -EINVAL;
9893 }
9894 }
9895#endif
9896 }
9897 EXIT();
9898 return ret;
9899}
9900
9901/**
9902 * wlan_hdd_change_station() - cfg80211 change station handler function
9903 * @wiphy: Pointer to the wiphy structure
9904 * @dev: Pointer to the net device.
9905 * @mac: bssid
9906 * @params: Pointer to station parameters
9907 *
9908 * This is the cfg80211 change station handler function which invokes
9909 * the internal function @__wlan_hdd_change_station with
9910 * SSR protection.
9911 *
9912 * Return: 0 for success, error number on failure.
9913 */
9914#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9915static int wlan_hdd_change_station(struct wiphy *wiphy,
9916 struct net_device *dev,
9917 const u8 *mac,
9918 struct station_parameters *params)
9919#else
9920static int wlan_hdd_change_station(struct wiphy *wiphy,
9921 struct net_device *dev,
9922 u8 *mac,
9923 struct station_parameters *params)
9924#endif
9925{
9926 int ret;
9927
9928 cds_ssr_protect(__func__);
9929 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9930 cds_ssr_unprotect(__func__);
9931
9932 return ret;
9933}
9934
9935/*
9936 * FUNCTION: __wlan_hdd_cfg80211_add_key
9937 * This function is used to initialize the key information
9938 */
9939static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9940 struct net_device *ndev,
9941 u8 key_index, bool pairwise,
9942 const u8 *mac_addr,
9943 struct key_params *params)
9944{
9945 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9946 tCsrRoamSetKey setKey;
9947 int status;
9948 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009949 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309950 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009951 hdd_context_t *pHddCtx;
9952 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9953
9954 ENTER();
9955
Anurag Chouhan6d760662016-02-20 16:05:43 +05309956 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009957 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009958 return -EINVAL;
9959 }
9960
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309961 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009962 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9963 pAdapter->sessionId, params->key_len));
9964 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9965 status = wlan_hdd_validate_context(pHddCtx);
9966
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309967 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009968 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009969
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009970 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009971 hdd_device_mode_to_string(pAdapter->device_mode),
9972 pAdapter->device_mode);
9973
9974 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009975 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009976
9977 return -EINVAL;
9978 }
9979
9980 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009981 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009982
9983 return -EINVAL;
9984 }
9985
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009986 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009987
9988 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309989 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 setKey.keyId = key_index;
9991 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309992 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009993
9994 switch (params->cipher) {
9995 case WLAN_CIPHER_SUITE_WEP40:
9996 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9997 break;
9998
9999 case WLAN_CIPHER_SUITE_WEP104:
10000 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10001 break;
10002
10003 case WLAN_CIPHER_SUITE_TKIP:
10004 {
10005 u8 *pKey = &setKey.Key[0];
10006 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10007
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010008 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010009
10010 /*Supplicant sends the 32bytes key in this order
10011
10012 |--------------|----------|----------|
10013 | Tk1 |TX-MIC | RX Mic |
10014 |||--------------|----------|----------|
10015 <---16bytes---><--8bytes--><--8bytes-->
10016
10017 */
10018 /*Sme expects the 32 bytes key to be in the below order
10019
10020 |--------------|----------|----------|
10021 | Tk1 |RX-MIC | TX Mic |
10022 |||--------------|----------|----------|
10023 <---16bytes---><--8bytes--><--8bytes-->
10024 */
10025 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010026 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027
10028 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010029 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010030
10031 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010032 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010033
10034 break;
10035 }
10036
10037 case WLAN_CIPHER_SUITE_CCMP:
10038 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10039 break;
10040
10041#ifdef FEATURE_WLAN_WAPI
10042 case WLAN_CIPHER_SUITE_SMS4:
10043 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010044 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010045 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10046 mac_addr, params->key,
10047 params->key_len);
10048 return 0;
10049 }
10050#endif
10051
10052#ifdef FEATURE_WLAN_ESE
10053 case WLAN_CIPHER_SUITE_KRK:
10054 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10055 break;
10056#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10057 case WLAN_CIPHER_SUITE_BTK:
10058 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10059 break;
10060#endif
10061#endif
10062
10063#ifdef WLAN_FEATURE_11W
10064 case WLAN_CIPHER_SUITE_AES_CMAC:
10065 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10066 break;
10067#endif
10068
10069 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010070 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010071 return -EOPNOTSUPP;
10072 }
10073
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010074 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010075
10076 if (!pairwise) {
10077 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010078 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010079 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010080 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010081 } else {
10082 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010083 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010084 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010085 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010086 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010087 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010088 /* if a key is already installed, block all subsequent ones */
10089 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010090 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010091 return 0;
10092 }
10093
10094 setKey.keyDirection = eSIR_TX_RX;
10095 /*Set the group key */
10096 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10097 pAdapter->sessionId, &setKey, &roamId);
10098
10099 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010100 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101 return -EINVAL;
10102 }
10103 /*Save the keys here and call sme_roam_set_key for setting
10104 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010105 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010106 &setKey, sizeof(tCsrRoamSetKey));
10107
10108 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10109 return status;
10110 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010111 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10112 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010113 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10114 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010115 status = wlansap_set_key_sta(
10116 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010117 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010118 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010119 __LINE__, status);
10120 }
10121 }
10122
10123 /* Save the key in ap ctx for use on START_BASS and restart */
10124 if (pairwise ||
10125 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10126 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010127 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 sizeof(tCsrRoamSetKey));
10129 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010130 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131 sizeof(tCsrRoamSetKey));
10132
Krunal Sonib4326f22016-03-10 13:05:51 -080010133 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10134 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 hdd_wext_state_t *pWextState =
10136 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10137 hdd_station_ctx_t *pHddStaCtx =
10138 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10139
10140 if (!pairwise) {
10141 /* set group key */
10142 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010143 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010144 __func__, __LINE__);
10145 hdd_perform_roam_set_key_complete(pAdapter);
10146 }
10147 }
10148
10149 pWextState->roamProfile.Keys.KeyLength[key_index] =
10150 (u8) params->key_len;
10151
10152 pWextState->roamProfile.Keys.defaultIndex = key_index;
10153
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010154 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010155 KeyMaterial[key_index][0], params->key,
10156 params->key_len);
10157
10158 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10159
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010160 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10162 setKey.keyDirection);
10163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010164 /* The supplicant may attempt to set the PTK once pre-authentication
10165 is done. Save the key in the UMAC and include it in the ADD BSS
10166 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010167 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010168 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010169 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010170 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010172 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010173 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010174 return -EINVAL;
10175 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176
10177 /* issue set key request to SME */
10178 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10179 pAdapter->sessionId, &setKey, &roamId);
10180
10181 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010182 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183 pHddStaCtx->roam_info.roamingState =
10184 HDD_ROAM_STATE_NONE;
10185 return -EINVAL;
10186 }
10187
10188 /* in case of IBSS as there was no information available about WEP keys during
10189 * IBSS join, group key intialized with NULL key, so re-initialize group key
10190 * with correct value*/
10191 if ((eCSR_BSS_TYPE_START_IBSS ==
10192 pWextState->roamProfile.BSSType)
10193 &&
10194 !((IW_AUTH_KEY_MGMT_802_1X ==
10195 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10196 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10197 pHddStaCtx->conn_info.authType)
10198 )
10199 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10200 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10201 )
10202 ) {
10203 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010204 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010205
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010206 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010207 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10208 setKey.keyDirection);
10209
10210 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10211 pAdapter->sessionId, &setKey,
10212 &roamId);
10213
10214 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010215 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216 pHddStaCtx->roam_info.roamingState =
10217 HDD_ROAM_STATE_NONE;
10218 return -EINVAL;
10219 }
10220 }
10221 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010222 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223 return 0;
10224}
10225
10226static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10227 struct net_device *ndev,
10228 u8 key_index, bool pairwise,
10229 const u8 *mac_addr,
10230 struct key_params *params)
10231{
10232 int ret;
10233 cds_ssr_protect(__func__);
10234 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10235 mac_addr, params);
10236 cds_ssr_unprotect(__func__);
10237
10238 return ret;
10239}
10240
10241/*
10242 * FUNCTION: __wlan_hdd_cfg80211_get_key
10243 * This function is used to get the key information
10244 */
10245static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10246 struct net_device *ndev,
10247 u8 key_index, bool pairwise,
10248 const u8 *mac_addr, void *cookie,
10249 void (*callback)(void *cookie,
10250 struct key_params *)
10251 )
10252{
10253 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10254 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10255 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10256 struct key_params params;
10257
10258 ENTER();
10259
Anurag Chouhan6d760662016-02-20 16:05:43 +053010260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010261 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262 return -EINVAL;
10263 }
10264
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010265 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010266 hdd_device_mode_to_string(pAdapter->device_mode),
10267 pAdapter->device_mode);
10268
10269 memset(&params, 0, sizeof(params));
10270
10271 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010272 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010273 key_index);
10274 return -EINVAL;
10275 }
10276
10277 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10278 case eCSR_ENCRYPT_TYPE_NONE:
10279 params.cipher = IW_AUTH_CIPHER_NONE;
10280 break;
10281
10282 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10283 case eCSR_ENCRYPT_TYPE_WEP40:
10284 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10285 break;
10286
10287 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10288 case eCSR_ENCRYPT_TYPE_WEP104:
10289 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10290 break;
10291
10292 case eCSR_ENCRYPT_TYPE_TKIP:
10293 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10294 break;
10295
10296 case eCSR_ENCRYPT_TYPE_AES:
10297 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10298 break;
10299
10300 default:
10301 params.cipher = IW_AUTH_CIPHER_NONE;
10302 break;
10303 }
10304
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010305 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306 TRACE_CODE_HDD_CFG80211_GET_KEY,
10307 pAdapter->sessionId, params.cipher));
10308
10309 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10310 params.seq_len = 0;
10311 params.seq = NULL;
10312 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10313 callback(cookie, &params);
10314
10315 EXIT();
10316 return 0;
10317}
10318
10319static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10320 struct net_device *ndev,
10321 u8 key_index, bool pairwise,
10322 const u8 *mac_addr, void *cookie,
10323 void (*callback)(void *cookie,
10324 struct key_params *)
10325 )
10326{
10327 int ret;
10328
10329 cds_ssr_protect(__func__);
10330 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10331 mac_addr, cookie, callback);
10332 cds_ssr_unprotect(__func__);
10333
10334 return ret;
10335}
10336
10337/**
10338 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10339 * @wiphy: wiphy interface context
10340 * @ndev: pointer to net device
10341 * @key_index: Key index used in 802.11 frames
10342 * @unicast: true if it is unicast key
10343 * @multicast: true if it is multicast key
10344 *
10345 * This function is required for cfg80211_ops API.
10346 * It is used to delete the key information
10347 * Underlying hardware implementation does not have API to delete the
10348 * encryption key. It is automatically deleted when the peer is
10349 * removed. Hence this function currently does nothing.
10350 * Future implementation may interprete delete key operation to
10351 * replacing the key with a random junk value, effectively making it
10352 * useless.
10353 *
10354 * Return: status code, always 0.
10355 */
10356
10357static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10358 struct net_device *ndev,
10359 u8 key_index,
10360 bool pairwise, const u8 *mac_addr)
10361{
10362 EXIT();
10363 return 0;
10364}
10365
10366/**
10367 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10368 * @wiphy: Pointer to wiphy structure.
10369 * @dev: Pointer to net_device structure.
10370 * @key_index: key index
10371 * @pairwise: pairwise
10372 * @mac_addr: mac address
10373 *
10374 * This is the cfg80211 delete key handler function which invokes
10375 * the internal function @__wlan_hdd_cfg80211_del_key with
10376 * SSR protection.
10377 *
10378 * Return: 0 for success, error number on failure.
10379 */
10380static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10381 struct net_device *dev,
10382 u8 key_index,
10383 bool pairwise, const u8 *mac_addr)
10384{
10385 int ret;
10386
10387 cds_ssr_protect(__func__);
10388 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10389 pairwise, mac_addr);
10390 cds_ssr_unprotect(__func__);
10391
10392 return ret;
10393}
10394
10395/*
10396 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10397 * This function is used to set the default tx key index
10398 */
10399static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10400 struct net_device *ndev,
10401 u8 key_index,
10402 bool unicast, bool multicast)
10403{
10404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10405 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10406 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10407 hdd_context_t *pHddCtx;
10408 int status;
10409
10410 ENTER();
10411
Anurag Chouhan6d760662016-02-20 16:05:43 +053010412 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010413 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414 return -EINVAL;
10415 }
10416
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010417 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010418 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10419 pAdapter->sessionId, key_index));
10420
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010421 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 hdd_device_mode_to_string(pAdapter->device_mode),
10423 pAdapter->device_mode, key_index);
10424
10425 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010426 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010427 return -EINVAL;
10428 }
10429
10430 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10431 status = wlan_hdd_validate_context(pHddCtx);
10432
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010433 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010434 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010435
Krunal Sonib4326f22016-03-10 13:05:51 -080010436 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10437 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010438 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10439 pHddStaCtx->conn_info.ucEncryptionType) &&
10440 (eCSR_ENCRYPT_TYPE_AES !=
10441 pHddStaCtx->conn_info.ucEncryptionType)) {
10442 /* If default key index is not same as previous one,
10443 * then update the default key index */
10444
10445 tCsrRoamSetKey setKey;
10446 uint32_t roamId = 0xFF;
10447 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10448
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010449 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010450
10451 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010452 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453 setKey.keyId = key_index;
10454 setKey.keyLength = Keys->KeyLength[key_index];
10455
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010456 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010457 &Keys->KeyMaterial[key_index][0],
10458 Keys->KeyLength[key_index]);
10459
10460 setKey.keyDirection = eSIR_TX_RX;
10461
Anurag Chouhanc5548422016-02-24 18:33:27 +053010462 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010463 &pHddStaCtx->conn_info.bssId);
10464
10465 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10466 pWextState->roamProfile.EncryptionType.
10467 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10468 /* In the case of dynamic wep supplicant hardcodes DWEP type
10469 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10470 * WEP-40 encryption. In this canse the key length is 5 but the
10471 * encryption type is 104 hence checking the key langht(5) and
10472 * encryption type(104) and switching encryption type to 40*/
10473 pWextState->roamProfile.EncryptionType.
10474 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10475 pWextState->roamProfile.mcEncryptionType.
10476 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10477 }
10478
10479 setKey.encType =
10480 pWextState->roamProfile.EncryptionType.
10481 encryptionType[0];
10482
10483 /* Issue set key request */
10484 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10485 pAdapter->sessionId, &setKey,
10486 &roamId);
10487
10488 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010489 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010490 status);
10491 return -EINVAL;
10492 }
10493 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010494 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010495 /* In SoftAp mode setting key direction for default mode */
10496 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10497 pWextState->roamProfile.EncryptionType.encryptionType[0])
10498 && (eCSR_ENCRYPT_TYPE_AES !=
10499 pWextState->roamProfile.EncryptionType.
10500 encryptionType[0])) {
10501 /* Saving key direction for default key index to TX default */
10502 hdd_ap_ctx_t *pAPCtx =
10503 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10504 pAPCtx->wepKey[key_index].keyDirection =
10505 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010506 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010507 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010508 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509 }
10510 }
10511
10512 EXIT();
10513 return status;
10514}
10515
10516static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10517 struct net_device *ndev,
10518 u8 key_index,
10519 bool unicast, bool multicast)
10520{
10521 int ret;
10522 cds_ssr_protect(__func__);
10523 ret =
10524 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10525 multicast);
10526 cds_ssr_unprotect(__func__);
10527
10528 return ret;
10529}
10530
Abhishek Singhc9941602016-08-09 16:06:22 +053010531/*
10532 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10533 * @wiphy: wiphy pointer
10534 * @channel: channel of the BSS
10535 * @bssid: Bssid of BSS
10536 * @ssid: Ssid of the BSS
10537 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010538 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010539 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010540 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010541#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010542static
Abhishek Singhc9941602016-08-09 16:06:22 +053010543struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10544 struct ieee80211_channel *channel, const u8 *bssid,
10545 const u8 *ssid, size_t ssid_len)
10546{
10547 return cfg80211_get_bss(wiphy, channel, bssid,
10548 ssid,
10549 ssid_len,
10550 WLAN_CAPABILITY_ESS,
10551 WLAN_CAPABILITY_ESS);
10552}
10553#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010554static
Abhishek Singhc9941602016-08-09 16:06:22 +053010555struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10556 struct ieee80211_channel *channel, const u8 *bssid,
10557 const u8 *ssid, size_t ssid_len)
10558{
10559 return cfg80211_get_bss(wiphy, channel, bssid,
10560 ssid,
10561 ssid_len,
10562 IEEE80211_BSS_TYPE_ESS,
10563 IEEE80211_PRIVACY_ANY);
10564}
10565#endif
10566
10567
10568/*
10569 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10570 * interface that BSS might have been lost.
10571 * @pAdapter: adaptor
10572 * @bssid: bssid which might have been lost
10573 *
10574 * Return: bss which is unlinked from kernel cache
10575 */
10576struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10577 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010578{
10579 struct net_device *dev = pAdapter->dev;
10580 struct wireless_dev *wdev = dev->ieee80211_ptr;
10581 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010582 struct cfg80211_bss *bss = NULL;
10583
Abhishek Singhc9941602016-08-09 16:06:22 +053010584 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10585 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010586 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010587 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010588 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010589 hdd_info("cfg80211_unlink_bss called for BSSID "
10590 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010591 cfg80211_unlink_bss(wiphy, bss);
10592 }
10593 return bss;
10594}
10595
Abhishek Singhc9941602016-08-09 16:06:22 +053010596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010597/**
10598 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10599 * @pAdapter: Pointer to adapter
10600 * @bss_desc: Pointer to bss descriptor
10601 *
10602 * This function is used to inform the BSS details to nl80211 interface.
10603 *
10604 * Return: struct cfg80211_bss pointer
10605 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010606struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10607 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010608{
10609 /*
10610 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10611 * already exists in bss data base of cfg80211 for that particular BSS
10612 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10613 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10614 * As of now there is no possibility to get the mgmt(probe response)
10615 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10616 * and passing to cfg80211_inform_bss_frame.
10617 */
10618 struct net_device *dev = pAdapter->dev;
10619 struct wireless_dev *wdev = dev->ieee80211_ptr;
10620 struct wiphy *wiphy = wdev->wiphy;
10621 int chan_no = bss_desc->channelId;
10622#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10623 qcom_ie_age *qie_age = NULL;
10624 int ie_length =
10625 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10626#else
10627 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10628#endif
10629 const char *ie =
10630 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10631 unsigned int freq;
10632 struct ieee80211_channel *chan;
10633 struct ieee80211_mgmt *mgmt = NULL;
10634 struct cfg80211_bss *bss_status = NULL;
10635 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10636 int rssi = 0;
10637 hdd_context_t *pHddCtx;
10638 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010639 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010640 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010641
10642 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10643 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010644 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010645 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010646
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010647 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010648 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10649 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010650 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010651 return NULL;
10652 }
10653
10654 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010656 /* Android does not want the timestamp from the frame.
10657 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010658 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659 mgmt->u.probe_resp.timestamp =
10660 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661
10662 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10663 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10664
10665#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10666 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10667 /* Assuming this is the last IE, copy at the end */
10668 ie_length -= sizeof(qcom_ie_age);
10669 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10670 qie_age->element_id = QCOM_VENDOR_IE_ID;
10671 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10672 qie_age->oui_1 = QCOM_OUI1;
10673 qie_age->oui_2 = QCOM_OUI2;
10674 qie_age->oui_3 = QCOM_OUI3;
10675 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10676 qie_age->age =
Jeff Johnsonfeb22892016-10-27 14:12:38 -070010677 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010678 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010679 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10680 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010681 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10682 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010683#endif
10684
10685 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10686 if (bss_desc->fProbeRsp) {
10687 mgmt->frame_control |=
10688 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10689 } else {
10690 mgmt->frame_control |=
10691 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10692 }
10693
10694 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010695 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010696 freq =
10697 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010698 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010700 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010701 freq =
10702 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010703 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010705 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706 kfree(mgmt);
10707 return NULL;
10708 }
10709
10710 chan = __ieee80211_get_channel(wiphy, freq);
10711 /* When the band is changed on the fly using the GUI, three things are done
10712 * 1. scan abort
10713 * 2. flush scan results from cache
10714 * 3. update the band with the new band user specified (refer to the
10715 * hdd_set_band_helper function) as part of the scan abort, message will be
10716 * queued to PE and we proceed with flushing and changinh the band.
10717 * PE will stop the scanning further and report back the results what ever
10718 * it had till now by calling the call back function.
10719 * if the time between update band and scandone call back is sufficient
10720 * enough the band change reflects in SME, SME validates the channels
10721 * and discards the channels correponding to previous band and calls back
10722 * with zero bss results. but if the time between band update and scan done
10723 * callback is very small then band change will not reflect in SME and SME
10724 * reports to HDD all the channels correponding to previous band.this is due
10725 * to race condition.but those channels are invalid to the new band and so
10726 * this function __ieee80211_get_channel will return NULL.Each time we
10727 * report scan result with this pointer null warning kernel trace is printed.
10728 * if the scan results contain large number of APs continuosly kernel
10729 * warning trace is printed and it will lead to apps watch dog bark.
10730 * So drop the bss and continue to next bss.
10731 */
10732 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010733 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10734 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010735 kfree(mgmt);
10736 return NULL;
10737 }
10738
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010739 /* Based on .ini configuration, raw rssi can be reported for bss.
10740 * Raw rssi is typically used for estimating power.
10741 */
10742
10743 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10744 bss_desc->rssi;
10745
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010746 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010747 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010748
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010749 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010750 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010751 (int)(rssi / 100),
10752 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010753
10754 bss_status =
10755 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10756 GFP_KERNEL);
10757 kfree(mgmt);
10758 return bss_status;
10759}
10760
10761/**
10762 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10763 * @pAdapter: Pointer to adapter
10764 * @pRoamInfo: Pointer to roam info
10765 *
10766 * This function is used to update the BSS data base of CFG8011
10767 *
10768 * Return: struct cfg80211_bss pointer
10769 */
10770struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10771 tCsrRoamInfo *pRoamInfo)
10772{
10773 tCsrRoamConnectedProfile roamProfile;
10774 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10775 struct cfg80211_bss *bss = NULL;
10776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10778 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10779
10780 if (NULL != roamProfile.pBssDesc) {
10781 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10782 roamProfile.pBssDesc);
10783
10784 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010785 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010786
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010787 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010789 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010790 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010791 return bss;
10792}
10793/**
10794 * wlan_hdd_cfg80211_update_bss() - update bss
10795 * @wiphy: Pointer to wiphy
10796 * @pAdapter: Pointer to adapter
10797 * @scan_time: scan request timestamp
10798 *
10799 * Return: zero if success, non-zero otherwise
10800 */
10801int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10802 hdd_adapter_t *pAdapter,
10803 uint32_t scan_time)
10804{
10805 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10806 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010807 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808 tScanResultHandle pResult;
10809 struct cfg80211_bss *bss_status = NULL;
10810 hdd_context_t *pHddCtx;
10811 int ret;
10812
10813 ENTER();
10814
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010815 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10817 NO_SESSION, pAdapter->sessionId));
10818
10819 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10820 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010821 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010822 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010823
10824 /* start getting scan results and populate cgf80211 BSS database */
10825 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10826
10827 /* no scan results */
10828 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010829 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010830 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 }
10832
10833 pScanResult = sme_scan_result_get_first(hHal, pResult);
10834
10835 while (pScanResult) {
10836 /*
10837 * - cfg80211_inform_bss() is not updating ie field of bss
10838 * entry if entry already exists in bss data base of cfg80211
10839 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10840 * to update thebss entry instead of cfg80211_inform_bss,
10841 * But this call expects mgmt packet as input. As of now
10842 * there is no possibility to get the mgmt(probe response)
10843 * frame from PE, converting bss_desc to
10844 * ieee80211_mgmt(probe response) and passing to c
10845 * fg80211_inform_bss_frame.
10846 * - Update BSS only if beacon timestamp is later than
10847 * scan request timestamp.
10848 */
10849 if ((scan_time == 0) ||
10850 (scan_time <
Jeff Johnsonfeb22892016-10-27 14:12:38 -070010851 pScanResult->BssDescriptor.nReceivedTime)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010852 bss_status =
10853 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10854 &pScanResult->BssDescriptor);
10855
10856 if (NULL == bss_status) {
10857 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10858 } else {
10859 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010860 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 bss_status);
10862 }
10863 } else {
10864 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10865 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10866 }
10867 pScanResult = sme_scan_result_get_next(hHal, pResult);
10868 }
10869
10870 sme_scan_result_purge(hHal, pResult);
10871 /*
10872 * For SAP mode, scan is invoked by hostapd during SAP start
10873 * if hostapd is restarted, we need to flush previous scan
10874 * result so that it will reflect environment change
10875 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010876 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10878 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10879#endif
10880 )
10881 sme_scan_flush_result(hHal);
10882
10883 EXIT();
10884 return 0;
10885}
10886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887/**
10888 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10889 * @pAdapter: Pointer to adapter
10890 * @pRoamInfo: Pointer to roam info
10891 * @index: Index
10892 * @preauth: Preauth flag
10893 *
10894 * This function is used to notify the supplicant of a new PMKSA candidate.
10895 *
10896 * Return: 0 for success, non-zero for failure
10897 */
10898int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10899 tCsrRoamInfo *pRoamInfo,
10900 int index, bool preauth)
10901{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010902 struct net_device *dev = pAdapter->dev;
10903 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10904
10905 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010906 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907
10908 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010909 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 return -EINVAL;
10911 }
10912
10913 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010914 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010915 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10916 cfg80211_pmksa_candidate_notify(dev, index,
10917 pRoamInfo->bssid.bytes,
10918 preauth, GFP_KERNEL);
10919 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920 return 0;
10921}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010922
10923#ifdef FEATURE_WLAN_LFR_METRICS
10924/**
10925 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10926 * @pAdapter: Pointer to adapter
10927 * @pRoamInfo: Pointer to roam info
10928 *
10929 * 802.11r/LFR metrics reporting function to report preauth initiation
10930 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010931 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932 */
10933#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010934QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010935 tCsrRoamInfo *pRoamInfo)
10936{
10937 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10938 union iwreq_data wrqu;
10939
10940 ENTER();
10941
10942 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010943 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010944 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945 }
10946
10947 /* create the event */
10948 memset(&wrqu, 0, sizeof(wrqu));
10949 memset(metrics_notification, 0, sizeof(metrics_notification));
10950
10951 wrqu.data.pointer = metrics_notification;
10952 wrqu.data.length = scnprintf(metrics_notification,
10953 sizeof(metrics_notification),
10954 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10955 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10956
10957 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10958 metrics_notification);
10959
10960 EXIT();
10961
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010962 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010963}
10964
10965/**
10966 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10967 * @pAdapter: Pointer to adapter
10968 * @pRoamInfo: Pointer to roam info
10969 * @preauth_status: Preauth status
10970 *
10971 * 802.11r/LFR metrics reporting function to report handover initiation
10972 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010973 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010975QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010976wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10977 tCsrRoamInfo *pRoamInfo,
10978 bool preauth_status)
10979{
10980 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10981 union iwreq_data wrqu;
10982
10983 ENTER();
10984
10985 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010986 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010987 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010988 }
10989
10990 /* create the event */
10991 memset(&wrqu, 0, sizeof(wrqu));
10992 memset(metrics_notification, 0, sizeof(metrics_notification));
10993
10994 scnprintf(metrics_notification, sizeof(metrics_notification),
10995 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10996 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10997
10998 if (1 == preauth_status)
10999 strlcat(metrics_notification, " true",
11000 sizeof(metrics_notification));
11001 else
11002 strlcat(metrics_notification, " false",
11003 sizeof(metrics_notification));
11004
11005 wrqu.data.pointer = metrics_notification;
11006 wrqu.data.length = strlen(metrics_notification);
11007
11008 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11009 metrics_notification);
11010
11011 EXIT();
11012
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011013 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014}
11015
11016/**
11017 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11018 * @pAdapter: Pointer to adapter
11019 * @pRoamInfo: Pointer to roam info
11020 *
11021 * 802.11r/LFR metrics reporting function to report handover initiation
11022 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011023 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011024 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011025QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026 tCsrRoamInfo *pRoamInfo)
11027{
11028 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11029 union iwreq_data wrqu;
11030
11031 ENTER();
11032
11033 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011034 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011035 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011036 }
11037
11038 /* create the event */
11039 memset(&wrqu, 0, sizeof(wrqu));
11040 memset(metrics_notification, 0, sizeof(metrics_notification));
11041
11042 wrqu.data.pointer = metrics_notification;
11043 wrqu.data.length = scnprintf(metrics_notification,
11044 sizeof(metrics_notification),
11045 "QCOM: LFR_PREAUTH_HANDOVER "
11046 MAC_ADDRESS_STR,
11047 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11048
11049 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11050 metrics_notification);
11051
11052 EXIT();
11053
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011054 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011055}
11056#endif
11057
11058/**
11059 * hdd_select_cbmode() - select channel bonding mode
11060 * @pAdapter: Pointer to adapter
11061 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011062 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011063 *
11064 * Return: none
11065 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011066void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11067 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011068{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011069 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011070 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011071 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011072
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011073 /*
11074 * CDS api expects secondary channel for calculating
11075 * the channel params
11076 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011077 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011078 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11079 if (operationChannel >= 1 && operationChannel <= 5)
11080 sec_ch = operationChannel + 4;
11081 else if (operationChannel >= 6 && operationChannel <= 13)
11082 sec_ch = operationChannel - 4;
11083 }
11084
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011085 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011086 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011087
11088 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011089 eHddDot11Mode hdd_dot11_mode;
11090 uint8_t iniDot11Mode =
11091 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11092
11093 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11094 switch (iniDot11Mode) {
11095 case eHDD_DOT11_MODE_AUTO:
11096 case eHDD_DOT11_MODE_11ac:
11097 case eHDD_DOT11_MODE_11ac_ONLY:
11098 if (sme_is_feature_supported_by_fw(DOT11AC))
11099 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11100 else
11101 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11102 break;
11103 case eHDD_DOT11_MODE_11n:
11104 case eHDD_DOT11_MODE_11n_ONLY:
11105 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11106 break;
11107 default:
11108 hdd_dot11_mode = iniDot11Mode;
11109 break;
11110 }
11111 ch_info->channel_width = ch_params->ch_width;
11112 ch_info->phy_mode =
11113 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011114 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011115 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011116 hdd_info("ch_info width %d, phymode %d channel %d",
11117 ch_info->channel_width, ch_info->phy_mode,
11118 ch_info->channel);
11119 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011120}
11121
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011122/**
11123 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11124 * @adapter: STA adapter
11125 * @roam_profile: STA roam profile
11126 *
11127 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11128 *
11129 * Return: false if sta-sap conc is not allowed, else return true
11130 */
11131static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11132 tCsrRoamProfile *roam_profile)
11133{
11134 hdd_context_t *hdd_ctx;
11135 hdd_adapter_t *ap_adapter;
11136 hdd_ap_ctx_t *hdd_ap_ctx;
11137 hdd_hostapd_state_t *hostapd_state;
11138 uint8_t channel = 0;
11139 QDF_STATUS status;
11140
11141 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11142 if (!hdd_ctx) {
11143 hdd_err("HDD context is NULL");
11144 return true;
11145 }
11146
11147 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11148 /* probably no sap running, no handling required */
11149 if (ap_adapter == NULL)
11150 return true;
11151
11152 /*
11153 * sap is not in started state, so it is fine to go ahead with sta.
11154 * if sap is currently doing CAC then don't allow sta to go further.
11155 */
11156 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11157 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11158 return true;
11159
11160 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11161 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11162 return false;
11163 }
11164
11165 /*
11166 * log and return error, if we allow STA to go through, we don't
11167 * know what is going to happen better stop sta connection
11168 */
11169 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11170 if (NULL == hdd_ap_ctx) {
11171 hdd_err("AP context not found");
11172 return false;
11173 }
11174
11175 /* sap is on non-dfs channel, nothing to handle */
11176 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11177 hdd_info("sap is on non-dfs channel, sta is allowed");
11178 return true;
11179 }
11180 /*
11181 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011182 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011183 */
11184 status = cds_get_channel_from_scan_result(adapter,
11185 roam_profile, &channel);
11186
Nitesh Shah59774522016-09-16 15:14:21 +053011187 /*
11188 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11189 * channels for roaming case.
11190 */
11191 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11192 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11193 return true;
11194 }
11195
11196 /*
11197 * If channel is 0 or DFS then better to call pcl and find out the
11198 * best channel. If channel is non-dfs 5 GHz then better move SAP
11199 * to STA's channel to make scc, so we have room for 3port MCC
11200 * scenario.
11201 */
11202 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011203 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11204 true);
11205
11206 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11207 qdf_event_reset(&hostapd_state->qdf_event);
11208 status = wlansap_set_channel_change_with_csa(
11209 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11210 hdd_ap_ctx->sapConfig.ch_width_orig);
11211
11212 if (QDF_STATUS_SUCCESS != status) {
11213 hdd_err("Set channel with CSA IE failed, can't allow STA");
11214 return false;
11215 }
11216
11217 /*
11218 * wait here for SAP to finish the channel switch. When channel
11219 * switch happens, SAP sends few beacons with CSA_IE. After
11220 * successfully Transmission of those beacons, it will move its
11221 * state from started to disconnected and move to new channel.
11222 * once it moves to new channel, sap again moves its state
11223 * machine from disconnected to started and set this event.
11224 * wait for 10 secs to finish this.
11225 */
11226 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11227 if (!QDF_IS_STATUS_SUCCESS(status)) {
11228 hdd_err("wait for qdf_event failed, STA not allowed!!");
11229 return false;
11230 }
11231
11232 return true;
11233}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234
Krunal Soni31949422016-07-29 17:17:53 -070011235/**
11236 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011237 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011238 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239 * @ssid_len: Length of ssid
11240 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011241 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011243 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011244 *
11245 * This function is used to start the association process
11246 *
11247 * Return: 0 for success, non-zero for failure
11248 */
Krunal Soni31949422016-07-29 17:17:53 -070011249static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011251 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011252 u8 operatingChannel,
11253 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254{
11255 int status = 0;
11256 hdd_wext_state_t *pWextState;
11257 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011258 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259 uint32_t roamId;
11260 tCsrRoamProfile *pRoamProfile;
11261 eCsrAuthType RSNAuthType;
11262 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011263 uint8_t channel = 0;
11264 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011265
11266 ENTER();
11267
11268 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11269 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011270 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011271
11272 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011273 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011275
11276 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011277 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011278 return -EINVAL;
11279 }
11280
11281 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011282 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11283 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011284
11285 if (pRoamProfile) {
11286 hdd_station_ctx_t *pHddStaCtx;
11287 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11288
11289 if (HDD_WMM_USER_MODE_NO_QOS ==
11290 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11291 /*QoS not enabled in cfg file */
11292 pRoamProfile->uapsd_mask = 0;
11293 } else {
11294 /*QoS enabled, update uapsd mask from cfg file */
11295 pRoamProfile->uapsd_mask =
11296 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11297 }
11298
11299 pRoamProfile->SSIDs.numOfSSIDs = 1;
11300 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011301 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011302 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011303 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304 ssid, ssid_len);
11305
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011306 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011307 if (bssid) {
11308 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011309 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011310 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011311 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011312 /*
11313 * Save BSSID in seperate variable as
11314 * pRoamProfile's BSSID is getting zeroed out in the
11315 * association process. In case of join failure
11316 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011318 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011319 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011320 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011321 } else if (bssid_hint) {
11322 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011323 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011324 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011325 /*
11326 * Save BSSID in a separate variable as
11327 * pRoamProfile's BSSID is getting zeroed out in the
11328 * association process. In case of join failure
11329 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011330 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011331 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011332 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011333 hdd_info("bssid_hint is given by upper layer %pM",
11334 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011336 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011337 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011338 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 }
11340
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011341 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 pRoamProfile->SSIDs.SSIDList->SSID.length,
11343 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11344 operatingChannel);
11345
11346 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11347 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011349 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11350 }
11351#ifdef FEATURE_WLAN_WAPI
11352 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011353 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 switch (pAdapter->wapi_info.wapiAuthMode) {
11355 case WAPI_AUTH_MODE_PSK:
11356 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011357 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358 pAdapter->wapi_info.wapiAuthMode);
11359 pRoamProfile->AuthType.authType[0] =
11360 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11361 break;
11362 }
11363 case WAPI_AUTH_MODE_CERT:
11364 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011365 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011366 pAdapter->wapi_info.wapiAuthMode);
11367 pRoamProfile->AuthType.authType[0] =
11368 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11369 break;
11370 }
11371 } /* End of switch */
11372 if (pAdapter->wapi_info.wapiAuthMode ==
11373 WAPI_AUTH_MODE_PSK
11374 || pAdapter->wapi_info.wapiAuthMode ==
11375 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011376 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 pRoamProfile->AuthType.numEntries = 1;
11378 pRoamProfile->EncryptionType.numEntries = 1;
11379 pRoamProfile->EncryptionType.encryptionType[0] =
11380 eCSR_ENCRYPT_TYPE_WPI;
11381 pRoamProfile->mcEncryptionType.numEntries = 1;
11382 pRoamProfile->mcEncryptionType.
11383 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11384 }
11385 }
Krunal Soni31949422016-07-29 17:17:53 -070011386#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011387#ifdef WLAN_FEATURE_GTK_OFFLOAD
11388 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011389 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11390 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11392 sizeof(tSirGtkOffloadParams));
11393 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11394 GTK_OFFLOAD_DISABLE;
11395 }
11396#endif
11397 pRoamProfile->csrPersona = pAdapter->device_mode;
11398
11399 if (operatingChannel) {
11400 pRoamProfile->ChannelInfo.ChannelList =
11401 &operatingChannel;
11402 pRoamProfile->ChannelInfo.numOfChannels = 1;
11403 } else {
11404 pRoamProfile->ChannelInfo.ChannelList = NULL;
11405 pRoamProfile->ChannelInfo.numOfChannels = 0;
11406 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011407 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011408 && operatingChannel) {
11409 /*
11410 * Need to post the IBSS power save parameters
11411 * to WMA. WMA will configure this parameters
11412 * to firmware if power save is enabled by the
11413 * firmware.
11414 */
11415 status = hdd_set_ibss_power_save_params(pAdapter);
11416
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011417 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011418 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419 return -EINVAL;
11420 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011421 pRoamProfile->ch_params.ch_width =
11422 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011423 /*
11424 * In IBSS mode while operating in 2.4 GHz,
11425 * the device supports only 20 MHz.
11426 */
11427 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11428 pRoamProfile->ch_params.ch_width =
11429 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011430 hdd_select_cbmode(pAdapter, operatingChannel,
11431 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011432 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011433 /*
11434 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11435 * or pmf=2 is an explicit configuration in the supplicant
11436 * configuration, drop the connection request.
11437 */
11438 if (pWextState->roamProfile.MFPEnabled &&
11439 !(pWextState->roamProfile.MFPRequired ||
11440 pWextState->roamProfile.MFPCapable)) {
11441 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11442 pWextState->roamProfile.MFPEnabled,
11443 pWextState->roamProfile.MFPRequired,
11444 pWextState->roamProfile.MFPCapable);
11445 return -EINVAL;
11446 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447
Krunal Soni3091bcc2016-06-23 12:28:21 -070011448 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011449 hdd_err("Connection refused: conn in progress");
11450 return -EINVAL;
11451 }
11452
Krunal Soni31949422016-07-29 17:17:53 -070011453 /*
11454 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011456 * enhancements, the supplicant is not issuing the scan command
11457 * now. So the unicast frames which are sent from the host are
11458 * not having the additional IEs. If it is P2P CLIENT and there
11459 * is no additional IE present in roamProfile, then use the
11460 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 */
11462
Krunal Sonib4326f22016-03-10 13:05:51 -080011463 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 (!pRoamProfile->pAddIEScan)) {
11465 pRoamProfile->pAddIEScan =
11466 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11467 pRoamProfile->nAddIEScanLength =
11468 pAdapter->scan_info.scanAddIE.length;
11469 }
11470 /*
11471 * When policy manager is enabled from ini file, we shouldn't
11472 * check for other concurrency rules.
11473 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011474 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011475 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011476 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 pAdapter, pRoamProfile, &roamId))
11478 return 0;
11479 }
11480
Krunal Soni3091bcc2016-06-23 12:28:21 -070011481 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011482 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11483 pRoamProfile))) {
11484 hdd_err("sap-sta conc will fail, can't allow sta");
11485 hdd_conn_set_connection_state(pAdapter,
11486 eConnectionState_NotConnected);
11487 return -ENOMEM;
11488 }
11489
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011490 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011491 if (!sme_config) {
11492 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011493 hdd_conn_set_connection_state(pAdapter,
11494 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495 return -ENOMEM;
11496 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011497 sme_get_config_param(pHddCtx->hHal, sme_config);
11498 /* These values are not sessionized. So, any change in these SME
11499 * configs on an older or parallel interface will affect the
11500 * cb mode. So, restoring the default INI params before starting
11501 * interfaces such as sta, cli etc.,
11502 */
11503 sme_config->csrConfig.channelBondingMode5GHz =
11504 pHddCtx->config->nChannelBondingMode5GHz;
11505 sme_config->csrConfig.channelBondingMode24GHz =
11506 pHddCtx->config->nChannelBondingMode24GHz;
11507 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011508 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011509 /*
11510 * Change conn_state to connecting before sme_roam_connect(),
11511 * because sme_roam_connect() has a direct path to call
11512 * hdd_sme_roam_callback(), which will change the conn_state
11513 * If direct path, conn_state will be accordingly changed to
11514 * NotConnected or Associated by either
11515 * hdd_association_completion_handler() or
11516 * hdd_dis_connect_handler() in sme_RoamCallback()if
11517 * sme_RomConnect is to be queued,
11518 * Connecting state will remain until it is completed.
11519 *
11520 * If connection state is not changed, connection state will
11521 * remain in eConnectionState_NotConnected state.
11522 * In hdd_association_completion_handler, "hddDisconInProgress"
11523 * is set to true if conn state is
11524 * eConnectionState_NotConnected.
11525 * If "hddDisconInProgress" is set to true then cfg80211 layer
11526 * is not informed of connect result indication which
11527 * is an issue.
11528 */
11529 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011530 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011531 hdd_conn_set_connection_state(pAdapter,
11532 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011533
Komal Seelama89be8d2016-09-29 11:09:26 +053011534 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11535 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011536 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11537 pAdapter->sessionId, pRoamProfile,
11538 &roamId);
11539
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011540 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011541 (QDF_STA_MODE == pAdapter->device_mode ||
11542 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011543 hdd_err("sme_roam_connect (session %d) failed with "
11544 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545 pAdapter->sessionId, status);
11546 /* change back to NotAssociated */
11547 hdd_conn_set_connection_state(pAdapter,
11548 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011549 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11550 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551 }
11552
11553 pRoamProfile->ChannelInfo.ChannelList = NULL;
11554 pRoamProfile->ChannelInfo.numOfChannels = 0;
11555
Nitesh Shah044fd672016-10-13 18:53:25 +053011556 if (!QDF_IS_STATUS_SUCCESS(
11557 wma_get_current_hw_mode(&hw_mode))) {
11558 hdd_err("wma_get_current_hw_mode failed");
11559 return status;
11560 }
11561
11562 if ((QDF_STA_MODE == pAdapter->device_mode)
11563 && hw_mode.dbs_cap) {
11564 cds_get_channel_from_scan_result(pAdapter,
11565 pRoamProfile, &channel);
11566 if (channel)
11567 cds_checkn_update_hw_mode_single_mac_mode
11568 (channel);
11569 }
11570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011571 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011572 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 return -EINVAL;
11574 }
11575 EXIT();
11576 return status;
11577}
11578
11579/**
11580 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11581 * @pAdapter: Pointer to adapter
11582 * @auth_type: Auth type
11583 *
11584 * This function is used to set the authentication type (OPEN/SHARED).
11585 *
11586 * Return: 0 for success, non-zero for failure
11587 */
11588static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11589 enum nl80211_auth_type auth_type)
11590{
11591 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11592 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11593
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011594 /*set authentication type */
11595 switch (auth_type) {
11596 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011597 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011598 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11599 break;
11600
11601 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011602 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011603 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011604 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11605 break;
11606
11607 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011608 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11610 break;
11611#ifdef FEATURE_WLAN_ESE
11612 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011613 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011614 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11615 break;
11616#endif
11617
11618 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011619 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11621 return -EINVAL;
11622 }
11623
11624 pWextState->roamProfile.AuthType.authType[0] =
11625 pHddStaCtx->conn_info.authType;
11626 return 0;
11627}
11628
11629/**
11630 * wlan_hdd_set_akm_suite() - set key management type
11631 * @pAdapter: Pointer to adapter
11632 * @key_mgmt: Key management type
11633 *
11634 * This function is used to set the key mgmt type(PSK/8021x).
11635 *
11636 * Return: 0 for success, non-zero for failure
11637 */
11638static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11639{
11640 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011642#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11643#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11644 /*set key mgmt type */
11645 switch (key_mgmt) {
11646 case WLAN_AKM_SUITE_PSK:
11647 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011648 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011649 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11651 break;
11652
11653 case WLAN_AKM_SUITE_8021X_SHA256:
11654 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011655 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011656 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11658 break;
11659#ifdef FEATURE_WLAN_ESE
11660#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11661#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11662 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011663 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11665 break;
11666#endif
11667#ifndef WLAN_AKM_SUITE_OSEN
11668#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11669#endif
11670 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011671 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011672 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11673 break;
11674
11675 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011676 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 return -EINVAL;
11678
11679 }
11680 return 0;
11681}
11682
11683/**
11684 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11685 * @pAdapter: Pointer to adapter
11686 * @cipher: Cipher type
11687 * @ucast: Unicast flag
11688 *
11689 * This function is used to set the encryption type
11690 * (NONE/WEP40/WEP104/TKIP/CCMP).
11691 *
11692 * Return: 0 for success, non-zero for failure
11693 */
11694static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11695 u32 cipher, bool ucast)
11696{
11697 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11698 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11699 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11700
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011701 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011702 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11704 } else {
11705
11706 /*set encryption method */
11707 switch (cipher) {
11708 case IW_AUTH_CIPHER_NONE:
11709 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11710 break;
11711
11712 case WLAN_CIPHER_SUITE_WEP40:
11713 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11714 break;
11715
11716 case WLAN_CIPHER_SUITE_WEP104:
11717 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11718 break;
11719
11720 case WLAN_CIPHER_SUITE_TKIP:
11721 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11722 break;
11723
11724 case WLAN_CIPHER_SUITE_CCMP:
11725 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11726 break;
11727#ifdef FEATURE_WLAN_WAPI
11728 case WLAN_CIPHER_SUITE_SMS4:
11729 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11730 break;
11731#endif
11732
11733#ifdef FEATURE_WLAN_ESE
11734 case WLAN_CIPHER_SUITE_KRK:
11735 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11736 break;
11737#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11738 case WLAN_CIPHER_SUITE_BTK:
11739 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11740 break;
11741#endif
11742#endif
11743 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011744 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011745 return -EOPNOTSUPP;
11746 }
11747 }
11748
11749 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011750 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011751 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11752 pWextState->roamProfile.EncryptionType.numEntries = 1;
11753 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11754 encryptionType;
11755 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011756 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11758 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11759 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11760 encryptionType;
11761 }
11762
11763 return 0;
11764}
11765
11766/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011767 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11768 * @wext_state: Pointer to wext state
11769 * @gen_ie: Pointer to IE data
11770 * @len: length of IE data
11771 *
11772 * Return: 0 for success, non-zero for failure
11773 */
11774static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11775 const uint8_t *gen_ie, uint16_t len)
11776{
11777 uint16_t cur_add_ie_len =
11778 wext_state->assocAddIE.length;
11779
11780 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11781 (wext_state->assocAddIE.length + len)) {
11782 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11783 QDF_ASSERT(0);
11784 return -ENOMEM;
11785 }
11786 memcpy(wext_state->assocAddIE.addIEdata +
11787 cur_add_ie_len, gen_ie, len);
11788 wext_state->assocAddIE.length += len;
11789
11790 wext_state->roamProfile.pAddIEAssoc =
11791 wext_state->assocAddIE.addIEdata;
11792 wext_state->roamProfile.nAddIEAssocLength =
11793 wext_state->assocAddIE.length;
11794 return 0;
11795}
11796
11797/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 * wlan_hdd_cfg80211_set_ie() - set IEs
11799 * @pAdapter: Pointer to adapter
11800 * @ie: Pointer ot ie
11801 * @ie: IE length
11802 *
11803 * Return: 0 for success, non-zero for failure
11804 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011805static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 size_t ie_len)
11807{
11808 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11809 const uint8_t *genie = ie;
11810 uint16_t remLen = ie_len;
11811#ifdef FEATURE_WLAN_WAPI
11812 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11813 u16 *tmp;
11814 uint16_t akmsuiteCount;
11815 int *akmlist;
11816#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011817 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011818
11819 /* clear previous assocAddIE */
11820 pWextState->assocAddIE.length = 0;
11821 pWextState->roamProfile.bWPSAssociation = false;
11822 pWextState->roamProfile.bOSENAssociation = false;
11823
11824 while (remLen >= 2) {
11825 uint16_t eLen = 0;
11826 uint8_t elementId;
11827 elementId = *genie++;
11828 eLen = *genie++;
11829 remLen -= 2;
11830
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011831 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832
11833 switch (elementId) {
11834 case DOT11F_EID_WPA:
11835 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 -070011836 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 return -EINVAL;
11838 } else if (0 ==
11839 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11840 uint16_t curAddIELen =
11841 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011842 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843
11844 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11845 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011846 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011847 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848 return -ENOMEM;
11849 }
11850 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11851 memcpy(pWextState->assocAddIE.addIEdata +
11852 curAddIELen, genie - 2, eLen + 2);
11853 pWextState->assocAddIE.length += eLen + 2;
11854
11855 pWextState->roamProfile.bWPSAssociation = true;
11856 pWextState->roamProfile.pAddIEAssoc =
11857 pWextState->assocAddIE.addIEdata;
11858 pWextState->roamProfile.nAddIEAssocLength =
11859 pWextState->assocAddIE.length;
11860 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011861 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011862 memset(pWextState->WPARSNIE, 0,
11863 MAX_WPA_RSN_IE_LEN);
11864 memcpy(pWextState->WPARSNIE, genie - 2,
11865 (eLen + 2));
11866 pWextState->roamProfile.pWPAReqIE =
11867 pWextState->WPARSNIE;
11868 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11869 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11870 P2P_OUI_TYPE_SIZE))) {
11871 uint16_t curAddIELen =
11872 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011873 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011874
11875 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11876 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011877 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011878 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011879 return -ENOMEM;
11880 }
11881 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11882 memcpy(pWextState->assocAddIE.addIEdata +
11883 curAddIELen, genie - 2, eLen + 2);
11884 pWextState->assocAddIE.length += eLen + 2;
11885
11886 pWextState->roamProfile.pAddIEAssoc =
11887 pWextState->assocAddIE.addIEdata;
11888 pWextState->roamProfile.nAddIEAssocLength =
11889 pWextState->assocAddIE.length;
11890 }
11891#ifdef WLAN_FEATURE_WFD
11892 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11893 WFD_OUI_TYPE_SIZE)) &&
11894 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011895 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011896 pAdapter->device_mode)) {
11897 uint16_t curAddIELen =
11898 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011899 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011900
11901 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11902 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011903 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011904 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 return -ENOMEM;
11906 }
11907 /* WFD IE is saved to Additional IE ; it should
11908 * be accumulated to handle WPS IE + P2P IE +
11909 * WFD IE */
11910 memcpy(pWextState->assocAddIE.addIEdata +
11911 curAddIELen, genie - 2, eLen + 2);
11912 pWextState->assocAddIE.length += eLen + 2;
11913
11914 pWextState->roamProfile.pAddIEAssoc =
11915 pWextState->assocAddIE.addIEdata;
11916 pWextState->roamProfile.nAddIEAssocLength =
11917 pWextState->assocAddIE.length;
11918 }
11919#endif
11920 /* Appending HS 2.0 Indication Element in Assiciation Request */
11921 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11922 HS20_OUI_TYPE_SIZE))) {
11923 uint16_t curAddIELen =
11924 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011925 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011926
11927 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11928 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011929 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011930 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931 return -ENOMEM;
11932 }
11933 memcpy(pWextState->assocAddIE.addIEdata +
11934 curAddIELen, genie - 2, eLen + 2);
11935 pWextState->assocAddIE.length += eLen + 2;
11936
11937 pWextState->roamProfile.pAddIEAssoc =
11938 pWextState->assocAddIE.addIEdata;
11939 pWextState->roamProfile.nAddIEAssocLength =
11940 pWextState->assocAddIE.length;
11941 }
11942 /* Appending OSEN Information Element in Assiciation Request */
11943 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11944 OSEN_OUI_TYPE_SIZE))) {
11945 uint16_t curAddIELen =
11946 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011947 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011948
11949 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11950 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011951 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011952 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011953 return -ENOMEM;
11954 }
11955 memcpy(pWextState->assocAddIE.addIEdata +
11956 curAddIELen, genie - 2, eLen + 2);
11957 pWextState->assocAddIE.length += eLen + 2;
11958
11959 pWextState->roamProfile.bOSENAssociation = true;
11960 pWextState->roamProfile.pAddIEAssoc =
11961 pWextState->assocAddIE.addIEdata;
11962 pWextState->roamProfile.nAddIEAssocLength =
11963 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011964 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11965 MBO_OUI_TYPE_SIZE))){
11966 hdd_info("Set MBO IE(len %d)", eLen + 2);
11967 status = wlan_hdd_add_assoc_ie(pWextState,
11968 genie - 2, eLen + 2);
11969 if (status)
11970 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011971 } else {
11972 uint16_t add_ie_len =
11973 pWextState->assocAddIE.length;
11974
11975 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11976
11977 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11978 (pWextState->assocAddIE.length + eLen)) {
11979 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011980 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011981 return -ENOMEM;
11982 }
11983
11984 memcpy(pWextState->assocAddIE.addIEdata +
11985 add_ie_len, genie - 2, eLen + 2);
11986 pWextState->assocAddIE.length += eLen + 2;
11987
11988 pWextState->roamProfile.pAddIEAssoc =
11989 pWextState->assocAddIE.addIEdata;
11990 pWextState->roamProfile.nAddIEAssocLength =
11991 pWextState->assocAddIE.length;
11992 }
11993 break;
11994 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011995 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11997 memcpy(pWextState->WPARSNIE, genie - 2,
11998 (eLen + 2));
11999 pWextState->roamProfile.pRSNReqIE =
12000 pWextState->WPARSNIE;
12001 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12002 break;
12003 /*
12004 * Appending Extended Capabilities with Interworking bit set
12005 * in Assoc Req.
12006 *
12007 * In assoc req this EXT Cap will only be taken into account if
12008 * interworkingService bit is set to 1. Currently
12009 * driver is only interested in interworkingService capability
12010 * from supplicant. If in future any other EXT Cap info is
12011 * required from supplicat, it needs to be handled while
12012 * sending Assoc Req in LIM.
12013 */
12014 case DOT11F_EID_EXTCAP:
12015 {
12016 uint16_t curAddIELen =
12017 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012018 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012019
12020 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12021 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012022 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012023 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012024 return -ENOMEM;
12025 }
12026 memcpy(pWextState->assocAddIE.addIEdata +
12027 curAddIELen, genie - 2, eLen + 2);
12028 pWextState->assocAddIE.length += eLen + 2;
12029
12030 pWextState->roamProfile.pAddIEAssoc =
12031 pWextState->assocAddIE.addIEdata;
12032 pWextState->roamProfile.nAddIEAssocLength =
12033 pWextState->assocAddIE.length;
12034 break;
12035 }
12036#ifdef FEATURE_WLAN_WAPI
12037 case WLAN_EID_WAPI:
12038 /* Setting WAPI Mode to ON=1 */
12039 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012040 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012041 tmp = (u16 *) ie;
12042 tmp = tmp + 2; /* Skip element Id and Len, Version */
12043 akmsuiteCount = WPA_GET_LE16(tmp);
12044 tmp = tmp + 1;
12045 akmlist = (int *)(tmp);
12046 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12047 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12048 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012049 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012050 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012051 return -EINVAL;
12052 }
12053
12054 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012055 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056 pAdapter->wapi_info.wapiAuthMode =
12057 WAPI_AUTH_MODE_PSK;
12058 }
12059 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012060 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 pAdapter->wapi_info.wapiAuthMode =
12062 WAPI_AUTH_MODE_CERT;
12063 }
12064 break;
12065#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012066 case DOT11F_EID_SUPPOPERATINGCLASSES:
12067 {
12068 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12069 status = wlan_hdd_add_assoc_ie(pWextState,
12070 genie - 2, eLen + 2);
12071 if (status)
12072 return status;
12073 break;
12074 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012075 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012076 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012077 /* when Unknown IE is received we should break and continue
12078 * to the next IE in the buffer instead we were returning
12079 * so changing this to break */
12080 break;
12081 }
12082 genie += eLen;
12083 remLen -= eLen;
12084 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012085 return 0;
12086}
12087
12088/**
12089 * hdd_is_wpaie_present() - check for WPA ie
12090 * @ie: Pointer to ie
12091 * @ie_len: Ie length
12092 *
12093 * Parse the received IE to find the WPA IE
12094 *
12095 * Return: true if wpa ie is found else false
12096 */
12097static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12098{
12099 uint8_t eLen = 0;
12100 uint16_t remLen = ie_len;
12101 uint8_t elementId = 0;
12102
12103 while (remLen >= 2) {
12104 elementId = *ie++;
12105 eLen = *ie++;
12106 remLen -= 2;
12107 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012108 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012109 return false;
12110 }
12111 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12112 /* OUI - 0x00 0X50 0XF2
12113 * WPA Information Element - 0x01
12114 * WPA version - 0x01
12115 */
12116 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12117 return true;
12118 }
12119 ie += eLen;
12120 remLen -= eLen;
12121 }
12122 return false;
12123}
12124
12125/**
12126 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12127 * @pAdapter: Pointer to adapter
12128 * @req: Pointer to security parameters
12129 *
12130 * Return: 0 for success, non-zero for failure
12131 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012132static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12133 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012134{
12135 int status = 0;
12136 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12137 ENTER();
12138
12139 /*set wpa version */
12140 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12141
12142 if (req->crypto.wpa_versions) {
12143 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12144 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12145 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12146 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12147 }
12148 }
12149
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012150 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012151
12152 /*set authentication type */
12153 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12154
12155 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012156 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012157 return status;
12158 }
12159
12160 /*set key mgmt type */
12161 if (req->crypto.n_akm_suites) {
12162 status =
12163 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12164 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012165 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012166 return status;
12167 }
12168 }
12169
12170 /*set pairwise cipher type */
12171 if (req->crypto.n_ciphers_pairwise) {
12172 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12173 req->crypto.
12174 ciphers_pairwise[0],
12175 true);
12176 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012177 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012178 return status;
12179 }
12180 } else {
12181 /*Reset previous cipher suite to none */
12182 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12183 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012184 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185 return status;
12186 }
12187 }
12188
12189 /*set group cipher type */
12190 status =
12191 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12192 false);
12193
12194 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012195 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012196 return status;
12197 }
12198#ifdef WLAN_FEATURE_11W
12199 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12200#endif
12201
12202 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12203 if (req->ie_len) {
12204 status =
12205 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12206 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012207 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012208 return status;
12209 }
12210 }
12211
12212 /*incase of WEP set default key information */
12213 if (req->key && req->key_len) {
12214 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12215 || (WLAN_CIPHER_SUITE_WEP104 ==
12216 req->crypto.ciphers_pairwise[0])
12217 ) {
12218 if (IW_AUTH_KEY_MGMT_802_1X
12219 ==
12220 (pWextState->
12221 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012222 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223 return -EOPNOTSUPP;
12224 } else {
12225 u8 key_len = req->key_len;
12226 u8 key_idx = req->key_idx;
12227
12228 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12229 key_len)
12230 && (CSR_MAX_NUM_KEY > key_idx)
12231 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012232 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012234 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012235 Keys.
12236 KeyMaterial[key_idx][0],
12237 req->key, key_len);
12238 pWextState->roamProfile.Keys.
12239 KeyLength[key_idx] = (u8) key_len;
12240 pWextState->roamProfile.Keys.
12241 defaultIndex = (u8) key_idx;
12242 }
12243 }
12244 }
12245 }
12246
12247 return status;
12248}
12249
12250/**
12251 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12252 * @pAdapter: Pointer to adapter
12253 *
12254 * This function is used to disconnect from previous connection
12255 *
12256 * Return: 0 for success, non-zero for failure
12257 */
12258static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12259{
12260 unsigned long rc;
12261 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012262 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263
12264 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12265
Jeff Johnson9edf9572016-10-03 15:24:49 -070012266 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012267 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12268 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12269 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012270 hdd_conn_set_connection_state(pAdapter,
12271 eConnectionState_Disconnecting);
12272 /* Issue disconnect to CSR */
12273 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012274
12275 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12276 pAdapter->sessionId,
12277 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12278 /*
12279 * Wait here instead of returning directly, this will block the
12280 * next connect command and allow processing of the scan for
12281 * ssid and the previous connect command in CSR. Else we might
12282 * hit some race conditions leading to SME and HDD out of sync.
12283 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012284 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012285 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12286 } else if (0 != status) {
12287 hdd_err("csrRoamDisconnect failure, returned %d",
12288 (int)status);
12289 pHddStaCtx->staDebugState = status;
12290 result = -EINVAL;
12291 goto disconnected;
12292 }
12293
12294 rc = wait_for_completion_timeout(
12295 &pAdapter->disconnect_comp_var,
12296 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012297 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012298 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12299 pAdapter->sessionId, pHddStaCtx->staDebugState);
12300 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301 }
12302 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012303 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012304 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012305 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012306 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012307 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012308 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012309 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310 }
12311 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012312disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012313 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12314 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012315}
12316
12317/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012318 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12319 * @adapter: Pointer to the HDD adapter
12320 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012321 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012322 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012323 * This function will start reassociation if prev_bssid is set and bssid/
12324 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012325 *
Naveen Rawat07332902016-07-27 09:13:17 -070012326 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012327 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012328#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12329 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012330static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12331 struct cfg80211_connect_params *req,
12332 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012333{
Naveen Rawat07332902016-07-27 09:13:17 -070012334 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012335 const uint8_t *bssid = NULL;
12336 uint16_t channel = 0;
12337
12338 if (req->bssid)
12339 bssid = req->bssid;
12340 else if (req->bssid_hint)
12341 bssid = req->bssid_hint;
12342
12343 if (req->channel)
12344 channel = req->channel->hw_value;
12345 else if (req->channel_hint)
12346 channel = req->channel_hint->hw_value;
12347
12348 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012349 reassoc = true;
12350 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012351 channel, MAC_ADDR_ARRAY(bssid));
12352 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012353 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012354 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012355 }
Naveen Rawat07332902016-07-27 09:13:17 -070012356 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012357}
12358#else
Naveen Rawat07332902016-07-27 09:13:17 -070012359static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12360 struct cfg80211_connect_params *req,
12361 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012362{
Naveen Rawat07332902016-07-27 09:13:17 -070012363 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012364}
12365#endif
12366
12367/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12369 * @wiphy: Pointer to wiphy
12370 * @dev: Pointer to network device
12371 * @req: Pointer to cfg80211 connect request
12372 *
12373 * This function is used to start the association process
12374 *
12375 * Return: 0 for success, non-zero for failure
12376 */
12377static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12378 struct net_device *ndev,
12379 struct cfg80211_connect_params *req)
12380{
12381 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012382 u16 channel;
12383#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12384 const u8 *bssid_hint = req->bssid_hint;
12385#else
12386 const u8 *bssid_hint = NULL;
12387#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12389 hdd_context_t *pHddCtx;
12390
12391 ENTER();
12392
Anurag Chouhan6d760662016-02-20 16:05:43 +053012393 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012394 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012395 return -EINVAL;
12396 }
12397
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012398 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012399 TRACE_CODE_HDD_CFG80211_CONNECT,
12400 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012401 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012402 hdd_device_mode_to_string(pAdapter->device_mode),
12403 pAdapter->device_mode);
12404
Krunal Sonib4326f22016-03-10 13:05:51 -080012405 if (pAdapter->device_mode != QDF_STA_MODE &&
12406 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012407 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 hdd_device_mode_to_string(pAdapter->device_mode),
12409 pAdapter->device_mode);
12410 return -EINVAL;
12411 }
12412
12413 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12414 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012415 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012416 return -EINVAL;
12417 }
12418
12419 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012420 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012421 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012422
Naveen Rawat07332902016-07-27 09:13:17 -070012423 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012424 return status;
12425
Agrawal Ashishf156e942016-08-04 14:54:47 +053012426 wlan_hdd_disable_roaming(pAdapter);
12427
12428 /* Try disconnecting if already in connected state */
12429 status = wlan_hdd_try_disconnect(pAdapter);
12430 if (0 > status) {
12431 hdd_err("Failed to disconnect the existing connection");
12432 return -EALREADY;
12433 }
12434
12435 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012437 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012438 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439 pAdapter->device_mode),
12440 req->channel->hw_value, HW_MODE_20_MHZ)) {
12441 hdd_err("This concurrency combination is not allowed");
12442 return -ECONNREFUSED;
12443 }
12444 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012445 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012446 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012447 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12448 hdd_err("This concurrency combination is not allowed");
12449 return -ECONNREFUSED;
12450 }
12451 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012453 /*initialise security parameters */
12454 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12455
12456 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012457 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 return status;
12459 }
12460
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012461 if (req->channel)
12462 channel = req->channel->hw_value;
12463 else
12464 channel = 0;
12465 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12466 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012467 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012468 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012469 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012470 return status;
12471 }
12472 EXIT();
12473 return status;
12474}
12475
12476/**
12477 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12478 * @wiphy: Pointer to wiphy
12479 * @dev: Pointer to network device
12480 * @req: Pointer to cfg80211 connect request
12481 *
12482 * Return: 0 for success, non-zero for failure
12483 */
12484static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12485 struct net_device *ndev,
12486 struct cfg80211_connect_params *req)
12487{
12488 int ret;
12489 cds_ssr_protect(__func__);
12490 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12491 cds_ssr_unprotect(__func__);
12492
12493 return ret;
12494}
12495
12496/**
12497 * wlan_hdd_disconnect() - hdd disconnect api
12498 * @pAdapter: Pointer to adapter
12499 * @reason: Disconnect reason code
12500 *
12501 * This function is used to issue a disconnect request to SME
12502 *
12503 * Return: 0 for success, non-zero for failure
12504 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012505static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506{
12507 int status, result = 0;
12508 unsigned long rc;
12509 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12510 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12511
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012512 ENTER();
12513
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012514 status = wlan_hdd_validate_context(pHddCtx);
12515
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012516 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012517 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012518
12519 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012520 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012521 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12522 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012523 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12525 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12526
12527 /*issue disconnect */
12528
12529 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12530 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012531 /*
12532 * Wait here instead of returning directly, this will block the next
12533 * connect command and allow processing of the scan for ssid and
12534 * the previous connect command in CSR. Else we might hit some
12535 * race conditions leading to SME and HDD out of sync.
12536 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012537 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012538 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012539 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012540 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012541 (int)status);
12542 pHddStaCtx->staDebugState = status;
12543 result = -EINVAL;
12544 goto disconnected;
12545 }
12546 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12547 msecs_to_jiffies
12548 (WLAN_WAIT_TIME_DISCONNECT));
12549
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012550 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012551 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552 result = -ETIMEDOUT;
12553 }
12554disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12556#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12557 /* Sending disconnect event to userspace for kernel version < 3.11
12558 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12559 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012560 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012561 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12562 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563#endif
12564
12565 return result;
12566}
12567
12568/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012569 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12570 * @reason: ieee80211 reason code.
12571 *
12572 * This utility function helps log string conversion of reason code.
12573 *
12574 * Return: string conversion of reason code, if match found;
12575 * "Unknown" otherwise.
12576 */
12577static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12578{
12579 switch (reason) {
12580 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12581 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12582 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12583 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12584 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12585 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12586 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12587 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12588 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12589 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12590 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12591 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12592 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12593 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12594 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12595 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12596 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12597 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12598 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12599 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12600 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12601 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12602 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12603 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12604 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12605 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12606 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12607 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12608 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12609 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12610 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12611 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12612 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12613 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12614 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12615 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12616 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12617 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12618 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12619 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12620 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12621 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12622 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12623 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12624 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12625 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12626 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12627 default:
12628 return "Unknown";
12629 }
12630}
12631
12632/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12634 * @wiphy: Pointer to wiphy
12635 * @dev: Pointer to network device
12636 * @reason: Disconnect reason code
12637 *
12638 * This function is used to issue a disconnect request to SME
12639 *
12640 * Return: 0 for success, non-zero for failure
12641 */
12642static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12643 struct net_device *dev, u16 reason)
12644{
12645 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12646 int status;
12647 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12648 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12649#ifdef FEATURE_WLAN_TDLS
12650 uint8_t staIdx;
12651#endif
12652
12653 ENTER();
12654
Anurag Chouhan6d760662016-02-20 16:05:43 +053012655 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012656 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012657 return -EINVAL;
12658 }
12659
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012660 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012661 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12662 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012663 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664 hdd_device_mode_to_string(pAdapter->device_mode),
12665 pAdapter->device_mode, reason);
12666
12667 status = wlan_hdd_validate_context(pHddCtx);
12668
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012669 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012670 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671
12672 /* Issue disconnect request to SME, if station is in connected state */
12673 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12674 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12675 eCsrRoamDisconnectReason reasonCode =
12676 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12677 hdd_scaninfo_t *pScanInfo;
12678
12679 switch (reason) {
12680 case WLAN_REASON_MIC_FAILURE:
12681 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12682 break;
12683
12684 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12685 case WLAN_REASON_DISASSOC_AP_BUSY:
12686 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12687 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12688 break;
12689
12690 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12691 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12692 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12693 break;
12694
12695 case WLAN_REASON_DEAUTH_LEAVING:
12696 reasonCode =
12697 pHddCtx->config->
12698 gEnableDeauthToDisassocMap ?
12699 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12700 eCSR_DISCONNECT_REASON_DEAUTH;
12701 break;
12702 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12703 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12704 break;
12705 default:
12706 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12707 break;
12708 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012709 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711 pScanInfo = &pAdapter->scan_info;
12712 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012713 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012714 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12715 eCSR_SCAN_ABORT_DEFAULT);
12716 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012717 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718#ifdef FEATURE_WLAN_TDLS
12719 /* First clean up the tdls peers if any */
12720 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12721 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12722 pAdapter->sessionId)
12723 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12724 uint8_t *mac;
12725 mac =
12726 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012727 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12728 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012729 pHddCtx->tdlsConnInfo[staIdx].staId,
12730 pAdapter->sessionId,
12731 MAC_ADDR_ARRAY(mac));
12732 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12733 (pAdapter),
12734 pAdapter->sessionId, mac);
12735 }
12736 }
12737#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012738 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012740 hdd_info("Disconnect request from user space with reason: %s",
12741 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012742 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12743 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012744 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012745 return -EINVAL;
12746 }
12747 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012748 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012749 pHddStaCtx->conn_info.connState);
12750 }
12751
12752 return status;
12753}
12754
12755/**
12756 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12757 * @wiphy: Pointer to wiphy
12758 * @dev: Pointer to network device
12759 * @reason: Disconnect reason code
12760 *
12761 * Return: 0 for success, non-zero for failure
12762 */
12763static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12764 struct net_device *dev, u16 reason)
12765{
12766 int ret;
12767 cds_ssr_protect(__func__);
12768 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12769 cds_ssr_unprotect(__func__);
12770
12771 return ret;
12772}
12773
12774/**
12775 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12776 * @pAdapter: Pointer to adapter
12777 * @param: Pointer to IBSS parameters
12778 *
12779 * This function is used to initialize the security settings in IBSS mode
12780 *
12781 * Return: 0 for success, non-zero for failure
12782 */
12783static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12784 struct cfg80211_ibss_params
12785 *params)
12786{
12787 int status = 0;
12788 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12789 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12790 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12791
12792 ENTER();
12793
12794 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012795 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012796 pHddStaCtx->ibss_enc_key_installed = 0;
12797
12798 if (params->ie_len && (NULL != params->ie)) {
12799 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12800 params->ie_len, WLAN_EID_RSN)) {
12801 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12802 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12803 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12804 tDot11fIEWPA dot11WPAIE;
12805 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12806 u8 *ie;
12807
12808 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12809 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12810 params->ie_len,
12811 DOT11F_EID_WPA);
12812 if (NULL != ie) {
12813 pWextState->wpaVersion =
12814 IW_AUTH_WPA_VERSION_WPA;
12815 /* Unpack the WPA IE */
12816 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12817 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12818 &ie[2 + 4],
12819 ie[1] - 4, &dot11WPAIE);
12820 /*Extract the multicast cipher, the encType for unicast
12821 cipher for wpa-none is none */
12822 encryptionType =
12823 hdd_translate_wpa_to_csr_encryption_type
12824 (dot11WPAIE.multicast_cipher);
12825 }
12826 }
12827
12828 status =
12829 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12830 params->ie_len);
12831
12832 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012833 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 return status;
12835 }
12836 }
12837
12838 pWextState->roamProfile.AuthType.authType[0] =
12839 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12840
12841 if (params->privacy) {
12842 /* Security enabled IBSS, At this time there is no information
12843 * available about the security paramters, so initialise the
12844 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12845 * The correct security parameters will be updated later in
12846 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12847 * set inorder enable privacy bit in beacons
12848 */
12849
12850 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12851 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012852 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012853 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12854 pWextState->roamProfile.EncryptionType.numEntries = 1;
12855 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12856 encryptionType;
12857 return status;
12858}
12859
12860/**
12861 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12862 * @wiphy: Pointer to wiphy
12863 * @dev: Pointer to network device
12864 * @param: Pointer to IBSS join parameters
12865 *
12866 * This function is used to create/join an IBSS network
12867 *
12868 * Return: 0 for success, non-zero for failure
12869 */
12870static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12871 struct net_device *dev,
12872 struct cfg80211_ibss_params *params)
12873{
12874 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12875 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12876 tCsrRoamProfile *pRoamProfile;
12877 int status;
12878 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12879 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012880 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012881 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012882
12883 ENTER();
12884
Anurag Chouhan6d760662016-02-20 16:05:43 +053012885 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012886 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012887 return -EINVAL;
12888 }
12889
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012890 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012891 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12892 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012893 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012894 hdd_device_mode_to_string(pAdapter->device_mode),
12895 pAdapter->device_mode);
12896
12897 status = wlan_hdd_validate_context(pHddCtx);
12898
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012899 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012901
12902 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012903 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12905 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12906 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12907 int indx;
12908
12909 /* Get channel number */
12910 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 params->
12912 chandef.
12913 chan->
12914 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915
12916 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12917 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012918 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012919 return -EOPNOTSUPP;
12920 }
12921
12922 for (indx = 0; indx < numChans; indx++) {
12923 if (channelNum == validChan[indx]) {
12924 break;
12925 }
12926 }
12927 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012928 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012929 return -EINVAL;
12930 }
12931 }
12932
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012933 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012934 HW_MODE_20_MHZ)) {
12935 hdd_err("This concurrency combination is not allowed");
12936 return -ECONNREFUSED;
12937 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012938
Krunal Soni3091bcc2016-06-23 12:28:21 -070012939 status = qdf_reset_connection_update();
12940 if (!QDF_IS_STATUS_SUCCESS(status))
12941 hdd_err("ERR: clear event failed");
12942
12943 status = cds_current_connections_update(pAdapter->sessionId,
12944 channelNum,
12945 SIR_UPDATE_REASON_JOIN_IBSS);
12946 if (QDF_STATUS_E_FAILURE == status) {
12947 hdd_err("ERROR: connections update failed!!");
12948 return -EINVAL;
12949 }
12950
12951 if (QDF_STATUS_SUCCESS == status) {
12952 status = qdf_wait_for_connection_update();
12953 if (!QDF_IS_STATUS_SUCCESS(status)) {
12954 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955 return -EINVAL;
12956 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012957 }
12958
12959 /*Try disconnecting if already in connected state */
12960 status = wlan_hdd_try_disconnect(pAdapter);
12961 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012962 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012963 return -EALREADY;
12964 }
12965
12966 pRoamProfile = &pWextState->roamProfile;
12967
12968 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012969 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 return -EINVAL;
12971 }
12972
12973 /* enable selected protection checks in IBSS mode */
12974 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12975
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012976 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12978 pHddCtx->config->
12979 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012980 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012981 }
12982
12983 /* BSSID is provided by upper layers hence no need to AUTO generate */
12984 if (NULL != params->bssid) {
12985 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012986 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012987 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012988 return -EIO;
12989 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012990 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12992 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012993 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012994 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995 return -EIO;
12996 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012997 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 }
12999 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13000 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13001 pRoamProfile->beaconInterval = params->beacon_interval;
13002 else {
13003 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013004 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013005 params->beacon_interval, pRoamProfile->beaconInterval);
13006 }
13007
13008 /* Set Channel */
13009 if (channelNum) {
13010 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013011 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013012 pRoamProfile->ChannelInfo.numOfChannels = 1;
13013 pHddStaCtx->conn_info.operationChannel = channelNum;
13014 pRoamProfile->ChannelInfo.ChannelList =
13015 &pHddStaCtx->conn_info.operationChannel;
13016 }
13017
13018 /* Initialize security parameters */
13019 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13020 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013021 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022 return status;
13023 }
13024
13025 /* Issue connect start */
13026 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13027 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013028 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013030 operationChannel,
13031 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013032
13033 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013034 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013035 return status;
13036 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013037 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013038 return 0;
13039}
13040
13041/**
13042 * wlan_hdd_cfg80211_join_ibss() - join ibss
13043 * @wiphy: Pointer to wiphy
13044 * @dev: Pointer to network device
13045 * @param: Pointer to IBSS join parameters
13046 *
13047 * This function is used to create/join an IBSS network
13048 *
13049 * Return: 0 for success, non-zero for failure
13050 */
13051static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13052 struct net_device *dev,
13053 struct cfg80211_ibss_params *params)
13054{
13055 int ret = 0;
13056
13057 cds_ssr_protect(__func__);
13058 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13059 cds_ssr_unprotect(__func__);
13060
13061 return ret;
13062}
13063
13064/**
13065 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13066 * @wiphy: Pointer to wiphy
13067 * @dev: Pointer to network device
13068 *
13069 * This function is used to leave an IBSS network
13070 *
13071 * Return: 0 for success, non-zero for failure
13072 */
13073static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13074 struct net_device *dev)
13075{
13076 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13077 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13078 tCsrRoamProfile *pRoamProfile;
13079 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13080 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013081 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013082 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013083 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084
13085 ENTER();
13086
Anurag Chouhan6d760662016-02-20 16:05:43 +053013087 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013088 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013089 return -EINVAL;
13090 }
13091
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013092 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013093 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13094 pAdapter->sessionId,
13095 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13096 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013097 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013099
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013100 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013101 hdd_device_mode_to_string(pAdapter->device_mode),
13102 pAdapter->device_mode);
13103 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013104 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 return -EIO;
13106 }
13107
13108 pRoamProfile = &pWextState->roamProfile;
13109
13110 /* Issue disconnect only if interface type is set to IBSS */
13111 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013112 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 return -EINVAL;
13114 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013115 /* Clearing add IE of beacon */
13116 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13117 sizeof(tSirMacAddr));
13118 updateIE.smeSessionId = pAdapter->sessionId;
13119 updateIE.ieBufferlength = 0;
13120 updateIE.pAdditionIEBuffer = NULL;
13121 updateIE.append = true;
13122 updateIE.notify = true;
13123 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13124 &updateIE,
13125 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013126 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013127 }
13128
13129 /* Reset WNI_CFG_PROBE_RSP Flags */
13130 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013131
13132 /* Issue Disconnect request */
13133 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13134 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13135 pAdapter->sessionId,
13136 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013137 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013138 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013139 hal_status);
13140 return -EAGAIN;
13141 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013142
13143 /* wait for mc thread to cleanup and then return to upper stack
13144 * so by the time upper layer calls the change interface, we are
13145 * all set to proceed further
13146 */
13147 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13148 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13149 if (!rc) {
13150 hdd_err("Failed to disconnect, timed out");
13151 return -ETIMEDOUT;
13152 }
13153
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013154 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013155 return 0;
13156}
13157
13158/**
13159 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13160 * @wiphy: Pointer to wiphy
13161 * @dev: Pointer to network device
13162 *
13163 * This function is used to leave an IBSS network
13164 *
13165 * Return: 0 for success, non-zero for failure
13166 */
13167static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13168 struct net_device *dev)
13169{
13170 int ret = 0;
13171
13172 cds_ssr_protect(__func__);
13173 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13174 cds_ssr_unprotect(__func__);
13175
13176 return ret;
13177}
13178
13179/**
13180 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13181 * @wiphy: Pointer to wiphy
13182 * @changed: Parameters changed
13183 *
13184 * This function is used to set the phy parameters. RTS Threshold/FRAG
13185 * Threshold/Retry Count etc.
13186 *
13187 * Return: 0 for success, non-zero for failure
13188 */
13189static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13190 u32 changed)
13191{
13192 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13193 tHalHandle hHal = pHddCtx->hHal;
13194 int status;
13195
13196 ENTER();
13197
Anurag Chouhan6d760662016-02-20 16:05:43 +053013198 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013199 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013200 return -EINVAL;
13201 }
13202
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013203 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13205 NO_SESSION, wiphy->rts_threshold));
13206 status = wlan_hdd_validate_context(pHddCtx);
13207
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013208 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013209 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013210
13211 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13212 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13213 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13214
13215 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13216 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013217 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013218 rts_threshold);
13219 return -EINVAL;
13220 }
13221
13222 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13223 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013224 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013225 rts_threshold);
13226 return -EIO;
13227 }
13228
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013229 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230 }
13231
13232 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13233 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13234 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13235 wiphy->frag_threshold;
13236
13237 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13238 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013239 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013240 frag_threshold);
13241 return -EINVAL;
13242 }
13243
13244 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13245 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013246 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247 frag_threshold);
13248 return -EIO;
13249 }
13250
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013251 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013252 }
13253
13254 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13255 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13256 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13257 wiphy->retry_short : wiphy->retry_long;
13258
13259 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13260 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013261 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013262 return -EINVAL;
13263 }
13264
13265 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13266 if (0 != sme_cfg_set_int(hHal,
13267 WNI_CFG_LONG_RETRY_LIMIT,
13268 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013269 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013270 retry_value);
13271 return -EIO;
13272 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013273 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13275 if (0 != sme_cfg_set_int(hHal,
13276 WNI_CFG_SHORT_RETRY_LIMIT,
13277 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013278 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013279 retry_value);
13280 return -EIO;
13281 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013282 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013283 }
13284 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013285 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286 return 0;
13287}
13288
13289/**
13290 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13291 * @wiphy: Pointer to wiphy
13292 * @changed: Parameters changed
13293 *
13294 * Return: 0 for success, non-zero for failure
13295 */
13296static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13297{
13298 int ret;
13299
13300 cds_ssr_protect(__func__);
13301 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13302 cds_ssr_unprotect(__func__);
13303
13304 return ret;
13305}
13306
13307/**
13308 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13309 * key
13310 * @wiphy: Pointer to wiphy
13311 * @dev: Pointer to network device
13312 * @key_index: Key index
13313 *
13314 * Return: 0
13315 */
13316static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13317 struct net_device *netdev,
13318 u8 key_index)
13319{
13320 ENTER();
13321 return 0;
13322}
13323
13324/**
13325 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13326 * wlan_hdd_set_default_mgmt_key
13327 * @wiphy: pointer to wiphy
13328 * @netdev: pointer to net_device structure
13329 * @key_index: key index
13330 *
13331 * Return: 0 on success, error number on failure
13332 */
13333static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13334 struct net_device *netdev,
13335 u8 key_index)
13336{
13337 int ret;
13338
13339 cds_ssr_protect(__func__);
13340 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13341 cds_ssr_unprotect(__func__);
13342
13343 return ret;
13344}
13345
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346/**
13347 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13348 * @wiphy: Pointer to wiphy
13349 * @dev: Pointer to network device
13350 * @params: Pointer to tx queue parameters
13351 *
13352 * Return: 0
13353 */
13354static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13355 struct net_device *dev,
13356 struct ieee80211_txq_params *params)
13357{
13358 ENTER();
13359 return 0;
13360}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013361
13362/**
13363 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13364 * @wiphy: pointer to wiphy
13365 * @netdev: pointer to net_device structure
13366 * @params: pointer to ieee80211_txq_params
13367 *
13368 * Return: 0 on success, error number on failure
13369 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13371 struct net_device *dev,
13372 struct ieee80211_txq_params *params)
13373{
13374 int ret;
13375
13376 cds_ssr_protect(__func__);
13377 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13378 cds_ssr_unprotect(__func__);
13379
13380 return ret;
13381}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013382
13383/**
13384 * __wlan_hdd_cfg80211_del_station() - delete station v2
13385 * @wiphy: Pointer to wiphy
13386 * @param: Pointer to delete station parameter
13387 *
13388 * Return: 0 for success, non-zero for failure
13389 */
13390static
13391int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13392 struct net_device *dev,
13393 struct tagCsrDelStaParams *pDelStaParams)
13394{
13395 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13396 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013397 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398 hdd_hostapd_state_t *hapd_state;
13399 int status;
13400 uint8_t staId;
13401 uint8_t *mac;
13402
13403 ENTER();
13404
Anurag Chouhan6d760662016-02-20 16:05:43 +053013405 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013406 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013407 return -EINVAL;
13408 }
13409
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013410 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411 TRACE_CODE_HDD_CFG80211_DEL_STA,
13412 pAdapter->sessionId, pAdapter->device_mode));
13413
13414 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13415 status = wlan_hdd_validate_context(pHddCtx);
13416
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013417 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013419
13420 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13421
Krunal Sonib4326f22016-03-10 13:05:51 -080013422 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13423 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424
13425 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13426 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013427 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013428 return 0;
13429 }
13430
Anurag Chouhanc5548422016-02-24 18:33:27 +053013431 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 uint16_t i;
13433 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13434 if ((pAdapter->aStaInfo[i].isUsed) &&
13435 (!pAdapter->aStaInfo[i].
13436 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013437 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013438 mac,
13439 pAdapter->aStaInfo[i].
13440 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013441 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013442 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13443 hdd_ipa_wlan_evt(pAdapter,
13444 pAdapter->
13445 aStaInfo[i].
13446 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013447 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448 mac);
13449 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013450 hdd_notice("Delete STA with MAC::"
13451 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013452 MAC_ADDR_ARRAY(mac));
13453
13454 if (pHddCtx->dev_dfs_cac_status ==
13455 DFS_CAC_IN_PROGRESS)
13456 goto fn_end;
13457
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013458 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013460 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013461 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013462 hdd_softap_sta_deauth(pAdapter,
13463 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013464 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013465 pAdapter->aStaInfo[i].
13466 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013467 qdf_status =
13468 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013469 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013470 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013471 if (!QDF_IS_STATUS_SUCCESS(
13472 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013473 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013474 }
13475 }
13476 }
13477 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013478 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013479 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013480 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013482 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013483 hdd_notice("Skip DEL STA as this is not used::"
13484 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013485 MAC_ADDR_ARRAY(mac));
13486 return -ENOENT;
13487 }
13488
13489 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13490 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013491 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 }
13493
13494 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13495 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013496 hdd_notice("Skip DEL STA as deauth is in progress::"
13497 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013498 MAC_ADDR_ARRAY(mac));
13499 return -ENOENT;
13500 }
13501
13502 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13503
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013504 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505 MAC_ADDR_ARRAY(mac));
13506
13507 /* Case: SAP in ACS selected DFS ch and client connected
13508 * Now Radar detected. Then if random channel is another
13509 * DFS ch then new CAC is initiated and no TX allowed.
13510 * So do not send any mgmt frames as it will timeout
13511 * during CAC.
13512 */
13513
13514 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13515 goto fn_end;
13516
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013517 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013518 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13519 (pAdapter), pAdapter->sessionId,
13520 (uint8_t *)&pDelStaParams->peerMacAddr,
13521 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013522 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013524 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013525 pAdapter->aStaInfo[staId].isDeauthInProgress =
13526 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013527 hdd_notice("STA removal failed for ::"
13528 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013529 MAC_ADDR_ARRAY(mac));
13530 return -ENOENT;
13531 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013532 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013533 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013535 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013536 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013537 }
13538 }
13539 }
13540
13541fn_end:
13542 EXIT();
13543 return 0;
13544}
13545
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013546#if defined(USE_CFG80211_DEL_STA_V2)
13547/**
13548 * wlan_hdd_del_station() - delete station wrapper
13549 * @adapter: pointer to the hdd adapter
13550 *
13551 * Return: None
13552 */
13553void wlan_hdd_del_station(hdd_adapter_t *adapter)
13554{
13555 struct station_del_parameters del_sta;
13556 del_sta.mac = NULL;
13557 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13558 del_sta.reason_code = eCsrForcedDeauthSta;
13559
13560 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13561 &del_sta);
13562}
13563#else
13564void wlan_hdd_del_station(hdd_adapter_t *adapter)
13565{
13566 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13567}
13568#endif
13569
13570#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571/**
13572 * wlan_hdd_cfg80211_del_station() - delete station v2
13573 * @wiphy: Pointer to wiphy
13574 * @param: Pointer to delete station parameter
13575 *
13576 * Return: 0 for success, non-zero for failure
13577 */
13578int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13579 struct net_device *dev,
13580 struct station_del_parameters *param)
13581#else
13582/**
13583 * wlan_hdd_cfg80211_del_station() - delete station
13584 * @wiphy: Pointer to wiphy
13585 * @mac: Pointer to station mac address
13586 *
13587 * Return: 0 for success, non-zero for failure
13588 */
13589#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13590int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13591 struct net_device *dev,
13592 const uint8_t *mac)
13593#else
13594int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13595 struct net_device *dev,
13596 uint8_t *mac)
13597#endif
13598#endif
13599{
13600 int ret;
13601 struct tagCsrDelStaParams delStaParams;
13602
13603 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013604#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013605 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013606 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 return -EINVAL;
13608 }
13609 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13610 param->subtype, &delStaParams);
13611#else
13612 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13613 (SIR_MAC_MGMT_DEAUTH >> 4),
13614 &delStaParams);
13615#endif
13616 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13617 cds_ssr_unprotect(__func__);
13618
13619 return ret;
13620}
13621
13622/**
13623 * __wlan_hdd_cfg80211_add_station() - add station
13624 * @wiphy: Pointer to wiphy
13625 * @mac: Pointer to station mac address
13626 * @pmksa: Pointer to add station parameter
13627 *
13628 * Return: 0 for success, non-zero for failure
13629 */
13630static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13631 struct net_device *dev,
13632 const uint8_t *mac,
13633 struct station_parameters *params)
13634{
13635 int status = -EPERM;
13636#ifdef FEATURE_WLAN_TDLS
13637 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13638 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13639 u32 mask, set;
13640
13641 ENTER();
13642
Anurag Chouhan6d760662016-02-20 16:05:43 +053013643 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013644 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013645 return -EINVAL;
13646 }
13647
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013648 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 TRACE_CODE_HDD_CFG80211_ADD_STA,
13650 pAdapter->sessionId, params->listen_interval));
13651
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013652 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654
13655 mask = params->sta_flags_mask;
13656
13657 set = params->sta_flags_set;
13658
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013659 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 MAC_ADDR_ARRAY(mac));
13661
13662 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13663 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13664 status =
13665 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13666 }
13667 }
13668#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013669 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670 return status;
13671}
13672
13673/**
13674 * wlan_hdd_cfg80211_add_station() - add station
13675 * @wiphy: Pointer to wiphy
13676 * @mac: Pointer to station mac address
13677 * @pmksa: Pointer to add station parameter
13678 *
13679 * Return: 0 for success, non-zero for failure
13680 */
13681#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13682static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13683 struct net_device *dev,
13684 const uint8_t *mac,
13685 struct station_parameters *params)
13686#else
13687static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13688 struct net_device *dev, uint8_t *mac,
13689 struct station_parameters *params)
13690#endif
13691{
13692 int ret;
13693
13694 cds_ssr_protect(__func__);
13695 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13696 cds_ssr_unprotect(__func__);
13697
13698 return ret;
13699}
13700
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013701/**
13702 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13703 * @wiphy: Pointer to wiphy
13704 * @dev: Pointer to network device
13705 * @pmksa: Pointer to set pmksa parameter
13706 *
13707 * Return: 0 for success, non-zero for failure
13708 */
13709static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13710 struct net_device *dev,
13711 struct cfg80211_pmksa *pmksa)
13712{
13713 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13714 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13715 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013716 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717 int status;
13718 tPmkidCacheInfo pmk_id;
13719
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013720 ENTER();
13721
Anurag Chouhan6d760662016-02-20 16:05:43 +053013722 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013723 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013724 return -EINVAL;
13725 }
13726
13727 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013728 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 return -EINVAL;
13730 }
13731
13732 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013733 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013734 pmksa->bssid, pmksa->pmkid);
13735 return -EINVAL;
13736 }
13737
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013738 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013739 MAC_ADDR_ARRAY(pmksa->bssid));
13740
13741 status = wlan_hdd_validate_context(pHddCtx);
13742
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013743 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013745
13746 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13747
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013748 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13749 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750
13751 /* Add to the PMKSA ID Cache in CSR */
13752 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13753 &pmk_id, 1, false);
13754
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013755 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013756 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13757 pAdapter->sessionId, result));
13758
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013759 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013760 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761}
13762
13763/**
13764 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13765 * @wiphy: Pointer to wiphy
13766 * @dev: Pointer to network device
13767 * @pmksa: Pointer to set pmksa parameter
13768 *
13769 * Return: 0 for success, non-zero for failure
13770 */
13771static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13772 struct net_device *dev,
13773 struct cfg80211_pmksa *pmksa)
13774{
13775 int ret;
13776
13777 cds_ssr_protect(__func__);
13778 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13779 cds_ssr_unprotect(__func__);
13780
13781 return ret;
13782}
13783
13784/**
13785 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13786 * @wiphy: Pointer to wiphy
13787 * @dev: Pointer to network device
13788 * @pmksa: Pointer to pmksa parameter
13789 *
13790 * Return: 0 for success, non-zero for failure
13791 */
13792static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13793 struct net_device *dev,
13794 struct cfg80211_pmksa *pmksa)
13795{
13796 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13797 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13798 tHalHandle halHandle;
13799 int status = 0;
13800
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013801 ENTER();
13802
Anurag Chouhan6d760662016-02-20 16:05:43 +053013803 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013804 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013805 return -EINVAL;
13806 }
13807
13808 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013809 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013810 return -EINVAL;
13811 }
13812
13813 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013814 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013815 return -EINVAL;
13816 }
13817
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013818 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013819 MAC_ADDR_ARRAY(pmksa->bssid));
13820
13821 status = wlan_hdd_validate_context(pHddCtx);
13822
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013823 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013824 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013825
13826 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13827
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013828 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013829 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13830 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013832 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 sme_roam_del_pmkid_from_cache(halHandle,
13834 pAdapter->sessionId, pmksa->bssid,
13835 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013836 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013837 MAC_ADDR_ARRAY(pmksa->bssid));
13838 status = -EINVAL;
13839 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013840 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013841 return status;
13842}
13843
13844/**
13845 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13846 * @wiphy: Pointer to wiphy
13847 * @dev: Pointer to network device
13848 * @pmksa: Pointer to pmksa parameter
13849 *
13850 * Return: 0 for success, non-zero for failure
13851 */
13852static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13853 struct net_device *dev,
13854 struct cfg80211_pmksa *pmksa)
13855{
13856 int ret;
13857
13858 cds_ssr_protect(__func__);
13859 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13860 cds_ssr_unprotect(__func__);
13861
13862 return ret;
13863
13864}
13865
13866/**
13867 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13868 * @wiphy: Pointer to wiphy
13869 * @dev: Pointer to network device
13870 *
13871 * Return: 0 for success, non-zero for failure
13872 */
13873static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13874 struct net_device *dev)
13875{
13876 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13877 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13878 tHalHandle halHandle;
13879 int status = 0;
13880
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013881 ENTER();
13882
Anurag Chouhan6d760662016-02-20 16:05:43 +053013883 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013884 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 return -EINVAL;
13886 }
13887
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013888 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013889
13890 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13891 status = wlan_hdd_validate_context(pHddCtx);
13892
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013893 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013894 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013895
13896 /* Retrieve halHandle */
13897 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13898
13899 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013900 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013901 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13902 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013903 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013904 status = -EINVAL;
13905 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013906 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013907 return status;
13908}
13909
13910/**
13911 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13912 * @wiphy: Pointer to wiphy
13913 * @dev: Pointer to network device
13914 *
13915 * Return: 0 for success, non-zero for failure
13916 */
13917static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13918 struct net_device *dev)
13919{
13920 int ret;
13921
13922 cds_ssr_protect(__func__);
13923 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13924 cds_ssr_unprotect(__func__);
13925
13926 return ret;
13927}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013929#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013930/**
13931 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13932 * @wiphy: Pointer to wiphy
13933 * @dev: Pointer to network device
13934 * @ftie: Pointer to fast transition ie parameter
13935 *
13936 * Return: 0 for success, non-zero for failure
13937 */
13938static int
13939__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13940 struct net_device *dev,
13941 struct cfg80211_update_ft_ies_params *ftie)
13942{
13943 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13944 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13945 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13946 int status;
13947
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013948 ENTER();
13949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950 status = wlan_hdd_validate_context(hdd_ctx);
13951 if (status)
13952 return status;
13953
Anurag Chouhan6d760662016-02-20 16:05:43 +053013954 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013955 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956 return -EINVAL;
13957 }
13958
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013959 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13961 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13962 /* Added for debug on reception of Re-assoc Req. */
13963 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013964 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013965 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013966 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013968 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013969 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013970
13971 /* Pass the received FT IEs to SME */
13972 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13973 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013974 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 return 0;
13976}
13977
13978/**
13979 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13980 * @wiphy: Pointer to wiphy
13981 * @dev: Pointer to network device
13982 * @ftie: Pointer to fast transition ie parameter
13983 *
13984 * Return: 0 for success, non-zero for failure
13985 */
13986static int
13987wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13988 struct net_device *dev,
13989 struct cfg80211_update_ft_ies_params *ftie)
13990{
13991 int ret;
13992
13993 cds_ssr_protect(__func__);
13994 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13995 cds_ssr_unprotect(__func__);
13996
13997 return ret;
13998}
13999#endif
14000
14001#ifdef WLAN_FEATURE_GTK_OFFLOAD
14002/**
14003 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14004 * @callbackContext: Callback context
14005 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14006 *
14007 * Callback rountine called upon receiving response for get offload info
14008 *
14009 * Return: none
14010 */
14011void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14012 tpSirGtkOffloadGetInfoRspParams
14013 pGtkOffloadGetInfoRsp)
14014{
14015 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14016 uint8_t tempReplayCounter[8];
14017 hdd_station_ctx_t *pHddStaCtx;
14018
14019 ENTER();
14020
14021 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014022 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014023 return;
14024 }
14025
14026 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014027 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 return;
14029 }
14030
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014031 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014032 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 return;
14034 }
14035
14036 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14037 /* Update replay counter */
14038 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14039 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14040
14041 {
14042 /* changing from little to big endian since supplicant
14043 * works on big endian format
14044 */
14045 int i;
14046 uint8_t *p =
14047 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14048
14049 for (i = 0; i < 8; i++) {
14050 tempReplayCounter[7 - i] = (uint8_t) p[i];
14051 }
14052 }
14053
14054 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014055 cfg80211_gtk_rekey_notify(pAdapter->dev,
14056 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014057 tempReplayCounter, GFP_KERNEL);
14058}
14059
14060/**
14061 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14062 * @wiphy: Pointer to wiphy
14063 * @dev: Pointer to network device
14064 * @data: Pointer to rekey data
14065 *
14066 * This function is used to offload GTK rekeying job to the firmware.
14067 *
14068 * Return: 0 for success, non-zero for failure
14069 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014070static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14072 struct net_device *dev,
14073 struct cfg80211_gtk_rekey_data *data)
14074{
14075 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14076 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14077 hdd_station_ctx_t *pHddStaCtx;
14078 tHalHandle hHal;
14079 int result;
14080 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014081 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014082
14083 ENTER();
14084
Anurag Chouhan6d760662016-02-20 16:05:43 +053014085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014086 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087 return -EINVAL;
14088 }
14089
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014090 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014091 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14092 pAdapter->sessionId, pAdapter->device_mode));
14093
14094 result = wlan_hdd_validate_context(pHddCtx);
14095
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014096 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014097 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098
14099 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14100 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14101 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014102 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014103 return -EAGAIN;
14104 }
14105
14106 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14107 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14108 NL80211_KCK_LEN);
14109 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14110 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014111 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014112 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014113 {
14114 /* changing from big to little endian since driver
14115 * works on little endian format
14116 */
14117 uint8_t *p =
14118 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14119 ullKeyReplayCounter;
14120 int i;
14121
14122 for (i = 0; i < 8; i++) {
14123 p[7 - i] = data->replay_ctr[i];
14124 }
14125 }
14126
14127 if (true == pHddCtx->hdd_wlan_suspended) {
14128 /* if wlan is suspended, enable GTK offload directly from here */
14129 memcpy(&hddGtkOffloadReqParams,
14130 &pHddStaCtx->gtkOffloadReqParams,
14131 sizeof(tSirGtkOffloadParams));
14132 status =
14133 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14134 pAdapter->sessionId);
14135
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014136 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014137 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138 status);
14139 return -EINVAL;
14140 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014141 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014143 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014144 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014145 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 return result;
14147}
14148
14149/**
14150 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14151 * @wiphy: Pointer to wiphy
14152 * @dev: Pointer to network device
14153 * @data: Pointer to rekey data
14154 *
14155 * This function is used to offload GTK rekeying job to the firmware.
14156 *
14157 * Return: 0 for success, non-zero for failure
14158 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014159static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014160int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14161 struct net_device *dev,
14162 struct cfg80211_gtk_rekey_data *data)
14163{
14164 int ret;
14165
14166 cds_ssr_protect(__func__);
14167 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14168 cds_ssr_unprotect(__func__);
14169
14170 return ret;
14171}
14172#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14173
14174/**
14175 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14176 * @wiphy: Pointer to wiphy
14177 * @dev: Pointer to network device
14178 * @param: Pointer to access control parameter
14179 *
14180 * Return: 0 for success, non-zero for failure
14181 */
14182static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14183 struct net_device *dev,
14184 const struct cfg80211_acl_data *params)
14185{
14186 int i;
14187 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14188 hdd_hostapd_state_t *pHostapdState;
14189 tsap_Config_t *pConfig;
14190 v_CONTEXT_t p_cds_context = NULL;
14191 hdd_context_t *pHddCtx;
14192 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014193 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194
14195 ENTER();
14196
Anurag Chouhan6d760662016-02-20 16:05:43 +053014197 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014198 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014199 return -EINVAL;
14200 }
14201
14202 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014203 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014204 return -EINVAL;
14205 }
14206
14207 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14208 status = wlan_hdd_validate_context(pHddCtx);
14209
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014210 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014212
14213 p_cds_context = pHddCtx->pcds_context;
14214 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14215
14216 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014217 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014218 return -EINVAL;
14219 }
14220
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014221 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 params->n_acl_entries);
14223
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014224 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014225 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14226 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014227 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14229
14230 /* default value */
14231 pConfig->num_accept_mac = 0;
14232 pConfig->num_deny_mac = 0;
14233
14234 /**
14235 * access control policy
14236 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14237 * listed in hostapd.deny file.
14238 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14239 * listed in hostapd.accept file.
14240 */
14241 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14242 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14243 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14244 params->acl_policy) {
14245 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14246 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014247 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014248 params->acl_policy);
14249 return -ENOTSUPP;
14250 }
14251
14252 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14253 pConfig->num_accept_mac = params->n_acl_entries;
14254 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014255 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14256 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014257 MAC_ADDR_ARRAY(
14258 params->mac_addrs[i].addr));
14259
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014260 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 params->mac_addrs[i].addr,
14262 sizeof(qcmacaddr));
14263 }
14264 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14265 pConfig->num_deny_mac = params->n_acl_entries;
14266 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014267 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14268 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014269 MAC_ADDR_ARRAY(
14270 params->mac_addrs[i].addr));
14271
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014272 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014273 params->mac_addrs[i].addr,
14274 sizeof(qcmacaddr));
14275 }
14276 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014277 qdf_status = wlansap_set_mac_acl(
14278 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014279 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014280 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014281 return -EINVAL;
14282 }
14283 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014284 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014285 hdd_device_mode_to_string(pAdapter->device_mode),
14286 pAdapter->device_mode);
14287 return -EINVAL;
14288 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014289 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014290 return 0;
14291}
14292
14293/**
14294 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14295 * __wlan_hdd_cfg80211_set_mac_acl
14296 * @wiphy: pointer to wiphy structure
14297 * @dev: pointer to net_device
14298 * @params: pointer to cfg80211_acl_data
14299 *
14300 * Return; 0 on success, error number otherwise
14301 */
14302static int
14303wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14304 struct net_device *dev,
14305 const struct cfg80211_acl_data *params)
14306{
14307 int ret;
14308
14309 cds_ssr_protect(__func__);
14310 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14311 cds_ssr_unprotect(__func__);
14312
14313 return ret;
14314}
14315
14316#ifdef WLAN_NL80211_TESTMODE
14317#ifdef FEATURE_WLAN_LPHB
14318/**
14319 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14320 * @pHddCtx: Pointer to hdd context
14321 * @lphbInd: Pointer to low power heart beat indication parameter
14322 *
14323 * Return: none
14324 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014325static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14326 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014327{
14328 struct sk_buff *skb;
14329
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014330 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014332 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334
14335 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014336 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 return;
14338 }
14339
14340 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14341 wiphy, sizeof(tSirLPHBInd),
14342 GFP_ATOMIC);
14343 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014344 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014345 return;
14346 }
14347
14348 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014349 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014350 goto nla_put_failure;
14351 }
14352 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014353 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014354 goto nla_put_failure;
14355 }
14356 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014357 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014358 goto nla_put_failure;
14359 }
14360 cfg80211_testmode_event(skb, GFP_ATOMIC);
14361 return;
14362
14363nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014364 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014365 kfree_skb(skb);
14366
14367 return;
14368}
14369#endif /* FEATURE_WLAN_LPHB */
14370
14371/**
14372 * __wlan_hdd_cfg80211_testmode() - test mode
14373 * @wiphy: Pointer to wiphy
14374 * @data: Data pointer
14375 * @len: Data length
14376 *
14377 * Return: 0 for success, non-zero for failure
14378 */
14379static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14380 void *data, int len)
14381{
14382 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14383 int err;
14384 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14385
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014386 ENTER();
14387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014388 err = wlan_hdd_validate_context(pHddCtx);
14389 if (err)
14390 return err;
14391
14392 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14393 len, wlan_hdd_tm_policy);
14394 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014395 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014396 return err;
14397 }
14398
14399 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014400 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014401 return -EINVAL;
14402 }
14403
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014404 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014405 TRACE_CODE_HDD_CFG80211_TESTMODE,
14406 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014407 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14408#ifdef FEATURE_WLAN_LPHB
14409 /* Low Power Heartbeat configuration request */
14410 case WLAN_HDD_TM_CMD_WLAN_HB:
14411 {
14412 int buf_len;
14413 void *buf;
14414 tSirLPHBReq *hb_params = NULL;
14415 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014416 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014417
14418 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014419 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014420 return -EINVAL;
14421 }
14422
14423 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14424 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14425
14426 hb_params_temp = (tSirLPHBReq *) buf;
14427 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14428 && (hb_params_temp->params.lphbTcpParamReq.
14429 timePeriodSec == 0))
14430 return -EINVAL;
14431
14432 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014433 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014434 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014435 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014436 return -ENOMEM;
14437 }
14438
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014439 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014440 smeStatus =
14441 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14442 hb_params,
14443 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014444 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014445 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014446 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014447 }
14448 return 0;
14449 }
14450#endif /* FEATURE_WLAN_LPHB */
14451
14452#if defined(QCA_WIFI_FTM)
14453 case WLAN_HDD_TM_CMD_WLAN_FTM:
14454 {
14455 int buf_len;
14456 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014457 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014458 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014459 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014460 return -EINVAL;
14461 }
14462
14463 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14464 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14465
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014466 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467
14468 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14469
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014470 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471 err = -EBUSY;
14472 break;
14473 }
14474#endif
14475
14476 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014477 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14479 return -EOPNOTSUPP;
14480 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014481 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014482 return err;
14483}
14484
14485/**
14486 * wlan_hdd_cfg80211_testmode() - test mode
14487 * @wiphy: Pointer to wiphy
14488 * @dev: Pointer to network device
14489 * @data: Data pointer
14490 * @len: Data length
14491 *
14492 * Return: 0 for success, non-zero for failure
14493 */
14494static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14495#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14496 struct wireless_dev *wdev,
14497#endif
14498 void *data, int len)
14499{
14500 int ret;
14501
14502 cds_ssr_protect(__func__);
14503 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14504 cds_ssr_unprotect(__func__);
14505
14506 return ret;
14507}
14508
14509#if defined(QCA_WIFI_FTM)
14510/**
14511 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14512 * @buf: Pointer to buffer
14513 * @buf_len: Buffer length
14514 *
14515 * Return: none
14516 */
14517void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14518{
14519 struct sk_buff *skb;
14520 hdd_context_t *hdd_ctx;
14521
14522 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014523 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 return;
14525 }
14526
Anurag Chouhan6d760662016-02-20 16:05:43 +053014527 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014528 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014529 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014530 return;
14531 }
14532
14533 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14534 buf_len, GFP_KERNEL);
14535 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014536 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014537 return;
14538 }
14539
14540 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14541 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14542 goto nla_put_failure;
14543
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014544 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014545
14546 cfg80211_testmode_event(skb, GFP_KERNEL);
14547 return;
14548
14549nla_put_failure:
14550 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014551 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552}
14553#endif
14554#endif /* CONFIG_NL80211_TESTMODE */
14555
14556#ifdef QCA_HT_2040_COEX
14557/**
14558 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14559 * @wiphy: Pointer to wiphy
14560 * @dev: Pointer to network device
14561 * @chandef: Pointer to channel definition parameter
14562 *
14563 * Return: 0 for success, non-zero for failure
14564 */
14565static int
14566__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14567 struct net_device *dev,
14568 struct cfg80211_chan_def *chandef)
14569{
14570 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14571 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014572 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014574 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014575
Anurag Chouhan6d760662016-02-20 16:05:43 +053014576 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014577 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014578 return -EINVAL;
14579 }
14580
14581 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14582 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014583 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014585
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014586 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014587 sme_get_config_param(pHddCtx->hHal, &sme_config);
14588 switch (chandef->width) {
14589 case NL80211_CHAN_WIDTH_20:
14590 if (sme_config.csrConfig.channelBondingMode24GHz !=
14591 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14592 sme_config.csrConfig.channelBondingMode24GHz =
14593 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14594 sme_update_config(pHddCtx->hHal, &sme_config);
14595 cbModeChange = true;
14596 }
14597 break;
14598
14599 case NL80211_CHAN_WIDTH_40:
14600 if (sme_config.csrConfig.channelBondingMode24GHz ==
14601 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14602 if (NL80211_CHAN_HT40MINUS ==
14603 cfg80211_get_chandef_type(chandef))
14604 sme_config.csrConfig.channelBondingMode24GHz =
14605 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14606 else
14607 sme_config.csrConfig.channelBondingMode24GHz =
14608 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14609 sme_update_config(pHddCtx->hHal, &sme_config);
14610 cbModeChange = true;
14611 }
14612 break;
14613
14614 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014615 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014616 return -EINVAL;
14617 }
14618
14619 if (!cbModeChange)
14620 return 0;
14621
Krunal Sonib4326f22016-03-10 13:05:51 -080014622 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014623 return 0;
14624
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014625 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014626 sme_config.csrConfig.channelBondingMode24GHz);
14627
14628 /* Change SAP ht2040 mode */
14629 status = hdd_set_sap_ht2040_mode(pAdapter,
14630 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014631 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014632 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014633 return -EINVAL;
14634 }
14635
14636 return 0;
14637}
14638
14639/**
14640 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14641 * @wiphy: Pointer to wiphy
14642 * @dev: Pointer to network device
14643 * @chandef: Pointer to channel definition parameter
14644 *
14645 * Return: 0 for success, non-zero for failure
14646 */
14647static int
14648wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14649 struct net_device *dev,
14650 struct cfg80211_chan_def *chandef)
14651{
14652 int ret;
14653
14654 cds_ssr_protect(__func__);
14655 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14656 cds_ssr_unprotect(__func__);
14657
14658 return ret;
14659}
14660#endif
14661
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014662#ifdef CHANNEL_SWITCH_SUPPORTED
14663/**
14664 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14665 * channel in SAP/GO
14666 * @wiphy: wiphy pointer
14667 * @dev: dev pointer.
14668 * @csa_params: Change channel params
14669 *
14670 * This function is called to switch channel in SAP/GO
14671 *
14672 * Return: 0 if success else return non zero
14673 */
14674static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14675 struct net_device *dev,
14676 struct cfg80211_csa_settings *csa_params)
14677{
14678 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14679 hdd_context_t *hdd_ctx;
14680 uint8_t channel;
14681 uint16_t freq;
14682 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014683 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014684
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014685 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014686 csa_params->chandef.chan->center_freq);
14687
14688 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14689 ret = wlan_hdd_validate_context(hdd_ctx);
14690
14691 if (0 != ret)
14692 return ret;
14693
Krunal Sonib4326f22016-03-10 13:05:51 -080014694 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14695 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014696 return -ENOTSUPP;
14697
14698 freq = csa_params->chandef.chan->center_freq;
14699 channel = cds_freq_to_chan(freq);
14700
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014701 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14702
14703 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014704 return ret;
14705}
14706
14707/**
14708 * wlan_hdd_cfg80211_channel_switch()- function to switch
14709 * channel in SAP/GO
14710 * @wiphy: wiphy pointer
14711 * @dev: dev pointer.
14712 * @csa_params: Change channel params
14713 *
14714 * This function is called to switch channel in SAP/GO
14715 *
14716 * Return: 0 if success else return non zero
14717 */
14718static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14719 struct net_device *dev,
14720 struct cfg80211_csa_settings *csa_params)
14721{
14722 int ret;
14723
14724 cds_ssr_protect(__func__);
14725 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14726 cds_ssr_unprotect(__func__);
14727 return ret;
14728}
14729#endif
14730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731/**
14732 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14733 * translation from NL to policy manager type
14734 * @type: Generic connection mode type defined in NL
14735 *
14736 *
14737 * This function provides the type translation
14738 *
14739 * Return: cds_con_mode enum
14740 */
14741enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14742 enum nl80211_iftype type)
14743{
14744 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14745 switch (type) {
14746 case NL80211_IFTYPE_STATION:
14747 mode = CDS_STA_MODE;
14748 break;
14749 case NL80211_IFTYPE_P2P_CLIENT:
14750 mode = CDS_P2P_CLIENT_MODE;
14751 break;
14752 case NL80211_IFTYPE_P2P_GO:
14753 mode = CDS_P2P_GO_MODE;
14754 break;
14755 case NL80211_IFTYPE_AP:
14756 mode = CDS_SAP_MODE;
14757 break;
14758 case NL80211_IFTYPE_ADHOC:
14759 mode = CDS_IBSS_MODE;
14760 break;
14761 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014762 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014763 type);
14764 }
14765 return mode;
14766}
14767
14768/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014769 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14770 * @wiphy: Handle to struct wiphy to get handle to module context.
14771 * @chandef: Contains information about the capture channel to be set.
14772 *
14773 * This interface is called if and only if monitor mode interface alone is
14774 * active.
14775 *
14776 * Return: 0 success or error code on failure.
14777 */
14778static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14779 struct cfg80211_chan_def *chandef)
14780{
14781 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14782 hdd_adapter_t *adapter;
14783 hdd_station_ctx_t *sta_ctx;
14784 struct hdd_mon_set_ch_info *ch_info;
14785 QDF_STATUS status;
14786 tHalHandle hal_hdl;
14787 struct qdf_mac_addr bssid;
14788 tCsrRoamProfile roam_profile;
14789 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014790 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014791 int ret;
14792 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14793
14794 ENTER();
14795
14796 ret = wlan_hdd_validate_context(hdd_ctx);
14797 if (ret)
14798 return ret;
14799
14800 hal_hdl = hdd_ctx->hHal;
14801
14802 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14803 if (!adapter)
14804 return -EIO;
14805
14806 hdd_info("%s: set monitor mode Channel %d and freq %d",
14807 adapter->dev->name, chan_num, chandef->chan->center_freq);
14808
14809 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14810 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014811 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14812 roam_profile.ChannelInfo.numOfChannels = 1;
14813 roam_profile.phyMode = ch_info->phy_mode;
14814 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014815 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014816
14817 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14818 QDF_MAC_ADDR_SIZE);
14819
14820 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014821 /*
14822 * CDS api expects secondary channel for calculating
14823 * the channel params
14824 */
14825 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14826 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14827 if (chan_num >= 1 && chan_num <= 5)
14828 sec_ch = chan_num + 4;
14829 else if (chan_num >= 6 && chan_num <= 13)
14830 sec_ch = chan_num - 4;
14831 }
14832 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014833 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14834 &roam_profile);
14835 if (status) {
14836 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14837 status);
14838 ret = qdf_status_to_os_return(status);
14839 return ret;
14840 }
14841 EXIT();
14842 return 0;
14843}
14844
14845/**
14846 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14847 * @wiphy: Handle to struct wiphy to get handle to module context.
14848 * @chandef: Contains information about the capture channel to be set.
14849 *
14850 * This interface is called if and only if monitor mode interface alone is
14851 * active.
14852 *
14853 * Return: 0 success or error code on failure.
14854 */
14855static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14856 struct cfg80211_chan_def *chandef)
14857{
14858 int ret;
14859
14860 cds_ssr_protect(__func__);
14861 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14862 cds_ssr_unprotect(__func__);
14863 return ret;
14864}
14865
14866/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014867 * struct cfg80211_ops - cfg80211_ops
14868 *
14869 * @add_virtual_intf: Add virtual interface
14870 * @del_virtual_intf: Delete virtual interface
14871 * @change_virtual_intf: Change virtual interface
14872 * @change_station: Change station
14873 * @add_beacon: Add beacon in sap mode
14874 * @del_beacon: Delete beacon in sap mode
14875 * @set_beacon: Set beacon in sap mode
14876 * @start_ap: Start ap
14877 * @change_beacon: Change beacon
14878 * @stop_ap: Stop ap
14879 * @change_bss: Change bss
14880 * @add_key: Add key
14881 * @get_key: Get key
14882 * @del_key: Delete key
14883 * @set_default_key: Set default key
14884 * @set_channel: Set channel
14885 * @scan: Scan
14886 * @connect: Connect
14887 * @disconnect: Disconnect
14888 * @join_ibss = Join ibss
14889 * @leave_ibss = Leave ibss
14890 * @set_wiphy_params = Set wiphy params
14891 * @set_tx_power = Set tx power
14892 * @get_tx_power = get tx power
14893 * @remain_on_channel = Remain on channel
14894 * @cancel_remain_on_channel = Cancel remain on channel
14895 * @mgmt_tx = Tx management frame
14896 * @mgmt_tx_cancel_wait = Cancel management tx wait
14897 * @set_default_mgmt_key = Set default management key
14898 * @set_txq_params = Set tx queue parameters
14899 * @get_station = Get station
14900 * @set_power_mgmt = Set power management
14901 * @del_station = Delete station
14902 * @add_station = Add station
14903 * @set_pmksa = Set pmksa
14904 * @del_pmksa = Delete pmksa
14905 * @flush_pmksa = Flush pmksa
14906 * @update_ft_ies = Update FT IEs
14907 * @tdls_mgmt = Tdls management
14908 * @tdls_oper = Tdls operation
14909 * @set_rekey_data = Set rekey data
14910 * @sched_scan_start = Scheduled scan start
14911 * @sched_scan_stop = Scheduled scan stop
14912 * @resume = Resume wlan
14913 * @suspend = Suspend wlan
14914 * @set_mac_acl = Set mac acl
14915 * @testmode_cmd = Test mode command
14916 * @set_ap_chanwidth = Set AP channel bandwidth
14917 * @dump_survey = Dump survey
14918 * @key_mgmt_set_pmk = Set pmk key management
14919 */
14920static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14921 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14922 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14923 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14924 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014925 .start_ap = wlan_hdd_cfg80211_start_ap,
14926 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14927 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014928 .change_bss = wlan_hdd_cfg80211_change_bss,
14929 .add_key = wlan_hdd_cfg80211_add_key,
14930 .get_key = wlan_hdd_cfg80211_get_key,
14931 .del_key = wlan_hdd_cfg80211_del_key,
14932 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14933 .scan = wlan_hdd_cfg80211_scan,
14934 .connect = wlan_hdd_cfg80211_connect,
14935 .disconnect = wlan_hdd_cfg80211_disconnect,
14936 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14937 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14938 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14939 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14940 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14941 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14942 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14943 .mgmt_tx = wlan_hdd_mgmt_tx,
14944 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14945 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14946 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014947 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014948 .get_station = wlan_hdd_cfg80211_get_station,
14949 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14950 .del_station = wlan_hdd_cfg80211_del_station,
14951 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014952 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14953 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14954 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014955#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014956 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14957#endif
14958#ifdef FEATURE_WLAN_TDLS
14959 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14960 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14961#endif
14962#ifdef WLAN_FEATURE_GTK_OFFLOAD
14963 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14964#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14965#ifdef FEATURE_WLAN_SCAN_PNO
14966 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14967 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14968#endif /*FEATURE_WLAN_SCAN_PNO */
14969 .resume = wlan_hdd_cfg80211_resume_wlan,
14970 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14971 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14972#ifdef WLAN_NL80211_TESTMODE
14973 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14974#endif
14975#ifdef QCA_HT_2040_COEX
14976 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14977#endif
14978 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014979#ifdef CHANNEL_SWITCH_SUPPORTED
14980 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14981#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014982 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014983#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14984 defined(CFG80211_ABORT_SCAN)
14985 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14986#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014987};