blob: e2e97b276f3dc9a2df5f85af3df18e097b6bda56 [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 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303917 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003918};
3919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303921 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3922 *
3923 * @adapter: Pointer to HDD adapter
3924 * @ie_data: Pointer to Scan IEs buffer
3925 * @ie_len: Length of Scan IEs
3926 *
3927 * Return: 0 on success; error number otherwise
3928 */
3929static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3930 uint8_t *ie_data, uint8_t ie_len)
3931{
3932 hdd_scaninfo_t *scan_info = NULL;
3933 scan_info = &adapter->scan_info;
3934
3935 if (scan_info->default_scan_ies) {
3936 qdf_mem_free(scan_info->default_scan_ies);
3937 scan_info->default_scan_ies = NULL;
3938 }
3939
3940 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3941 if (!scan_info->default_scan_ies)
3942 return -ENOMEM;
3943
3944 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3945 scan_info->default_scan_ies_len = ie_len;
3946 return 0;
3947}
3948
3949/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3951 * vendor command
3952 *
3953 * @wiphy: wiphy device pointer
3954 * @wdev: wireless device pointer
3955 * @data: Vendor command data buffer
3956 * @data_len: Buffer length
3957 *
3958 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3959 *
3960 * Return: Error code.
3961 */
3962static int
3963__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3964 struct wireless_dev *wdev,
3965 const void *data,
3966 int data_len)
3967{
3968 struct net_device *dev = wdev->netdev;
3969 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3970 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3971 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3972 int ret_val = 0;
3973 u32 modulated_dtim;
3974 u16 stats_avg_factor;
3975 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303976 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003977 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003978 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303979 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303980 int attr_len;
3981 int access_policy = 0;
3982 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3983 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303984 uint16_t scan_ie_len = 0;
3985 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303986 struct sir_set_tx_rx_aggregation_size request;
3987 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003988 uint8_t retry, delay;
3989 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303990 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303991
Jeff Johnson1f61b612016-02-12 16:28:33 -08003992 ENTER_DEV(dev);
3993
Anurag Chouhan6d760662016-02-20 16:05:43 +05303994 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 hdd_err("Command not allowed in FTM mode");
3996 return -EPERM;
3997 }
3998
3999 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304000 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002
4003 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4004 data, data_len,
4005 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004006 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007 return -EINVAL;
4008 }
4009
Krunal Sonie3531942016-04-12 17:43:53 -07004010 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4011 ftm_capab = nla_get_u32(tb[
4012 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4013 hdd_ctx->config->fine_time_meas_cap =
4014 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4015 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304016 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004017 hdd_ctx->config->fine_time_meas_cap);
4018 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4019 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4020 hdd_ctx->config->fine_time_meas_cap);
4021 }
4022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4024 modulated_dtim = nla_get_u32(
4025 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4026
4027 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4028 adapter->sessionId,
4029 modulated_dtim);
4030
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304031 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032 ret_val = -EPERM;
4033 }
4034
Kapil Gupta6213c012016-09-02 19:39:09 +05304035 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4036 qpower = nla_get_u8(
4037 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4038 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4039 ret_val = -EINVAL;
4040 }
4041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4043 stats_avg_factor = nla_get_u16(
4044 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4045 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4046 adapter->sessionId,
4047 stats_avg_factor);
4048
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304049 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004050 ret_val = -EPERM;
4051 }
4052
4053
4054 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4055 guard_time = nla_get_u32(
4056 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4057 status = sme_configure_guard_time(hdd_ctx->hHal,
4058 adapter->sessionId,
4059 guard_time);
4060
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304061 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062 ret_val = -EPERM;
4063 }
4064
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304065 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4066 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4067 attr_len = nla_len(
4068 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4069 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4070 hdd_info("Invalid value. attr_len %d",
4071 attr_len);
4072 return -EINVAL;
4073 }
4074
4075 nla_memcpy(&vendor_ie,
4076 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4077 attr_len);
4078 vendor_ie_present = true;
4079 hdd_info("Access policy vendor ie present.attr_len %d",
4080 attr_len);
4081 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4082 &vendor_ie[0], attr_len);
4083 }
4084
4085 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4086 access_policy = (int) nla_get_u32(
4087 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4088 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4089 (access_policy >
4090 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4091 hdd_info("Invalid value. access_policy %d",
4092 access_policy);
4093 return -EINVAL;
4094 }
4095 access_policy_present = true;
4096 hdd_info("Access policy present. access_policy %d",
4097 access_policy);
4098 }
4099
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004100 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4101 retry = nla_get_u8(tb[
4102 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4103 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4104 CFG_NON_AGG_RETRY_MAX : retry;
4105 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4106 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4107 retry, PDEV_CMD);
4108 }
4109
4110 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4111 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4112 retry = retry > CFG_AGG_RETRY_MAX ?
4113 CFG_AGG_RETRY_MAX : retry;
4114
4115 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4116 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4117 CFG_AGG_RETRY_MIN : retry;
4118 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4119 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4120 retry, PDEV_CMD);
4121 }
4122
4123 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4124 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4125 retry = retry > CFG_MGMT_RETRY_MAX ?
4126 CFG_MGMT_RETRY_MAX : retry;
4127 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4128 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4129 retry, PDEV_CMD);
4130 }
4131
4132 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4133 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4134 retry = retry > CFG_CTRL_RETRY_MAX ?
4135 CFG_CTRL_RETRY_MAX : retry;
4136 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4137 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4138 retry, PDEV_CMD);
4139 }
4140
4141 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4142 delay = nla_get_u8(tb[
4143 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4144 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4145 CFG_PROPAGATION_DELAY_MAX : delay;
4146 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4147 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4148 delay, PDEV_CMD);
4149 }
4150
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304151 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4152 tx_fail_count = nla_get_u32(
4153 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4154 if (tx_fail_count) {
4155 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4156 adapter->sessionId, tx_fail_count);
4157 if (QDF_STATUS_SUCCESS != status) {
4158 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4159 status);
4160 return -EINVAL;
4161 }
4162 }
4163 }
4164
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304165 if (vendor_ie_present && access_policy_present) {
4166 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4167 access_policy =
4168 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304169 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304170 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304171 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304172
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304173 hdd_info("calling sme_update_access_policy_vendor_ie");
4174 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4175 adapter->sessionId, &vendor_ie[0],
4176 access_policy);
4177 if (QDF_STATUS_SUCCESS != status) {
4178 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304179 return -EINVAL;
4180 }
4181 }
4182
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304183 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4184 set_value = nla_get_u8(
4185 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4186 hdd_info("set_value: %d", set_value);
4187 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4188 }
4189
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304190 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4191 scan_ie_len = nla_len(
4192 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4193 hdd_info("Received default scan IE of len %d session %d device mode %d",
4194 scan_ie_len, adapter->sessionId,
4195 adapter->device_mode);
4196 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4197 scan_ie = (uint8_t *) nla_data(tb
4198 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304199
4200 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4201 scan_ie_len))
4202 hdd_err("Failed to save default scan IEs");
4203
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304204 if (adapter->device_mode == QDF_STA_MODE) {
4205 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4206 adapter->sessionId, scan_ie,
4207 scan_ie_len);
4208 if (QDF_STATUS_SUCCESS != status)
4209 ret_val = -EPERM;
4210 }
4211 } else
4212 ret_val = -EPERM;
4213 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304214
4215 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4216 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4217 /* if one is specified, both must be specified */
4218 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4219 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4220 hdd_err("Both TX and RX MPDU Aggregation required");
4221 return -EINVAL;
4222 }
4223
4224 request.tx_aggregation_size = nla_get_u8(
4225 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4226 request.rx_aggregation_size = nla_get_u8(
4227 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4228 request.vdev_id = adapter->sessionId;
4229
4230 if (request.tx_aggregation_size >=
4231 CFG_TX_AGGREGATION_SIZE_MIN &&
4232 request.tx_aggregation_size <=
4233 CFG_TX_AGGREGATION_SIZE_MAX &&
4234 request.rx_aggregation_size >=
4235 CFG_RX_AGGREGATION_SIZE_MIN &&
4236 request.rx_aggregation_size <=
4237 CFG_RX_AGGREGATION_SIZE_MAX) {
4238 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4239 if (qdf_status != QDF_STATUS_SUCCESS) {
4240 hdd_err("failed to set aggr sizes err %d",
4241 qdf_status);
4242 ret_val = -EPERM;
4243 }
4244 } else {
4245 hdd_err("TX %d RX %d MPDU aggr size not in range",
4246 request.tx_aggregation_size,
4247 request.rx_aggregation_size);
4248 ret_val = -EINVAL;
4249 }
4250 }
4251
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304252 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4253 uint8_t ignore_assoc_disallowed;
4254
4255 ignore_assoc_disallowed
4256 = nla_get_u8(tb[
4257 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4258 hdd_info("Set ignore_assoc_disallowed value - %d",
4259 ignore_assoc_disallowed);
4260 if ((ignore_assoc_disallowed <
4261 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4262 (ignore_assoc_disallowed >
4263 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4264 return -EPERM;
4265
4266 sme_update_session_param(hdd_ctx->hHal,
4267 adapter->sessionId,
4268 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4269 ignore_assoc_disallowed);
4270 }
4271
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 return ret_val;
4273}
4274
4275/**
4276 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4277 * vendor command
4278 *
4279 * @wiphy: wiphy device pointer
4280 * @wdev: wireless device pointer
4281 * @data: Vendor command data buffer
4282 * @data_len: Buffer length
4283 *
4284 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4285 *
4286 * Return: EOK or other error codes.
4287 */
4288static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4289 struct wireless_dev *wdev,
4290 const void *data,
4291 int data_len)
4292{
4293 int ret;
4294
4295 cds_ssr_protect(__func__);
4296 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4297 data, data_len);
4298 cds_ssr_unprotect(__func__);
4299
4300 return ret;
4301}
4302
4303static const struct
4304nla_policy
4305qca_wlan_vendor_wifi_logger_start_policy
4306[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4307 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4308 = {.type = NLA_U32 },
4309 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4310 = {.type = NLA_U32 },
4311 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4312 = {.type = NLA_U32 },
4313};
4314
4315/**
4316 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4317 * or disable the collection of packet statistics from the firmware
4318 * @wiphy: WIPHY structure pointer
4319 * @wdev: Wireless device structure pointer
4320 * @data: Pointer to the data received
4321 * @data_len: Length of the data received
4322 *
4323 * This function enables or disables the collection of packet statistics from
4324 * the firmware
4325 *
4326 * Return: 0 on success and errno on failure
4327 */
4328static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4329 struct wireless_dev *wdev,
4330 const void *data,
4331 int data_len)
4332{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304333 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4335 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4336 struct sir_wifi_start_log start_log;
4337
Jeff Johnson1f61b612016-02-12 16:28:33 -08004338 ENTER_DEV(wdev->netdev);
4339
Anurag Chouhan6d760662016-02-20 16:05:43 +05304340 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 hdd_err("Command not allowed in FTM mode");
4342 return -EPERM;
4343 }
4344
4345 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304346 if (status)
4347 return status;
4348
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349
4350 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4351 data, data_len,
4352 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004353 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 return -EINVAL;
4355 }
4356
4357 /* Parse and fetch ring id */
4358 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004359 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 return -EINVAL;
4361 }
4362 start_log.ring_id = nla_get_u32(
4363 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004364 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365
4366 /* Parse and fetch verbose level */
4367 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004368 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 return -EINVAL;
4370 }
4371 start_log.verbose_level = nla_get_u32(
4372 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004373 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374
4375 /* Parse and fetch flag */
4376 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004377 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 return -EINVAL;
4379 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304380 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304382 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304384 /* size is buff size which can be set using iwpriv command*/
4385 start_log.size = 0;
4386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004387 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4388
4389 if (start_log.ring_id == RING_ID_WAKELOCK) {
4390 /* Start/stop wakelock events */
4391 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4392 cds_set_wakelock_logging(true);
4393 else
4394 cds_set_wakelock_logging(false);
4395 return 0;
4396 }
4397
4398 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304399 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004400 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 status);
4402 return -EINVAL;
4403 }
4404 return 0;
4405}
4406
4407/**
4408 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4409 * or disable the collection of packet statistics from the firmware
4410 * @wiphy: WIPHY structure pointer
4411 * @wdev: Wireless device structure pointer
4412 * @data: Pointer to the data received
4413 * @data_len: Length of the data received
4414 *
4415 * This function is used to enable or disable the collection of packet
4416 * statistics from the firmware
4417 *
4418 * Return: 0 on success and errno on failure
4419 */
4420static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4421 struct wireless_dev *wdev,
4422 const void *data,
4423 int data_len)
4424{
4425 int ret = 0;
4426
4427 cds_ssr_protect(__func__);
4428 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4429 wdev, data, data_len);
4430 cds_ssr_unprotect(__func__);
4431
4432 return ret;
4433}
4434
4435static const struct
4436nla_policy
4437qca_wlan_vendor_wifi_logger_get_ring_data_policy
4438[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4439 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4440 = {.type = NLA_U32 },
4441};
4442
4443/**
4444 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4445 * @wiphy: WIPHY structure pointer
4446 * @wdev: Wireless device structure pointer
4447 * @data: Pointer to the data received
4448 * @data_len: Length of the data received
4449 *
4450 * This function is used to flush or retrieve the per packet statistics from
4451 * the driver
4452 *
4453 * Return: 0 on success and errno on failure
4454 */
4455static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4456 struct wireless_dev *wdev,
4457 const void *data,
4458 int data_len)
4459{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304460 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004461 uint32_t ring_id;
4462 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4463 struct nlattr *tb
4464 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4465
Jeff Johnson1f61b612016-02-12 16:28:33 -08004466 ENTER_DEV(wdev->netdev);
4467
Anurag Chouhan6d760662016-02-20 16:05:43 +05304468 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004469 hdd_err("Command not allowed in FTM mode");
4470 return -EPERM;
4471 }
4472
4473 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304474 if (status)
4475 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476
4477 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4478 data, data_len,
4479 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004480 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004481 return -EINVAL;
4482 }
4483
4484 /* Parse and fetch ring id */
4485 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004486 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004487 return -EINVAL;
4488 }
4489
4490 ring_id = nla_get_u32(
4491 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4492
4493 if (ring_id == RING_ID_PER_PACKET_STATS) {
4494 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004495 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304496 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4497 /*
4498 * As part of DRIVER ring ID, flush both driver and fw logs.
4499 * For other Ring ID's driver doesn't have any rings to flush
4500 */
4501 hdd_notice("Bug report triggered by framework");
4502
4503 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4504 WLAN_LOG_INDICATOR_FRAMEWORK,
4505 WLAN_LOG_REASON_CODE_UNUSED,
4506 true, false);
4507 if (QDF_STATUS_SUCCESS != status) {
4508 hdd_err("Failed to trigger bug report");
4509 return -EINVAL;
4510 }
4511 } else {
4512 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4513 WLAN_LOG_INDICATOR_FRAMEWORK,
4514 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004515 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004516 return 0;
4517}
4518
4519/**
4520 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4521 * @wiphy: WIPHY structure pointer
4522 * @wdev: Wireless device structure pointer
4523 * @data: Pointer to the data received
4524 * @data_len: Length of the data received
4525 *
4526 * This function is used to flush or retrieve the per packet statistics from
4527 * the driver
4528 *
4529 * Return: 0 on success and errno on failure
4530 */
4531static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4532 struct wireless_dev *wdev,
4533 const void *data,
4534 int data_len)
4535{
4536 int ret = 0;
4537
4538 cds_ssr_protect(__func__);
4539 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4540 wdev, data, data_len);
4541 cds_ssr_unprotect(__func__);
4542
4543 return ret;
4544}
4545
4546#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4547/**
4548 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4549 * @hdd_ctx: HDD context
4550 * @request_id: [input] request id
4551 * @pattern_id: [output] pattern id
4552 *
4553 * This function loops through request id to pattern id array
4554 * if the slot is available, store the request id and return pattern id
4555 * if entry exists, return the pattern id
4556 *
4557 * Return: 0 on success and errno on failure
4558 */
4559static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4560 uint32_t request_id,
4561 uint8_t *pattern_id)
4562{
4563 uint32_t i;
4564
4565 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4566 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4567 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4568 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4569 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4570 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4571 return 0;
4572 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4573 request_id) {
4574 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4575 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4576 return 0;
4577 }
4578 }
4579 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4580 return -EINVAL;
4581}
4582
4583/**
4584 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4585 * @hdd_ctx: HDD context
4586 * @request_id: [input] request id
4587 * @pattern_id: [output] pattern id
4588 *
4589 * This function loops through request id to pattern id array
4590 * reset request id to 0 (slot available again) and
4591 * return pattern id
4592 *
4593 * Return: 0 on success and errno on failure
4594 */
4595static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4596 uint32_t request_id,
4597 uint8_t *pattern_id)
4598{
4599 uint32_t i;
4600
4601 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4602 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4603 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4604 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4605 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4606 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4607 return 0;
4608 }
4609 }
4610 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4611 return -EINVAL;
4612}
4613
4614
4615/*
4616 * define short names for the global vendor params
4617 * used by __wlan_hdd_cfg80211_offloaded_packets()
4618 */
4619#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4620#define PARAM_REQUEST_ID \
4621 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4622#define PARAM_CONTROL \
4623 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4624#define PARAM_IP_PACKET \
4625 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4626#define PARAM_SRC_MAC_ADDR \
4627 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4628#define PARAM_DST_MAC_ADDR \
4629 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4630#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4631
4632/**
4633 * wlan_hdd_add_tx_ptrn() - add tx pattern
4634 * @adapter: adapter pointer
4635 * @hdd_ctx: hdd context
4636 * @tb: nl attributes
4637 *
4638 * This function reads the NL attributes and forms a AddTxPtrn message
4639 * posts it to SME.
4640 *
4641 */
4642static int
4643wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4644 struct nlattr **tb)
4645{
4646 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304647 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004648 uint32_t request_id, ret, len;
4649 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304650 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 uint16_t eth_type = htons(ETH_P_IP);
4652
4653 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004654 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 return -ENOTSUPP;
4656 }
4657
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304658 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004660 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661 return -ENOMEM;
4662 }
4663
4664 /* Parse and fetch request Id */
4665 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004666 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667 goto fail;
4668 }
4669
4670 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4671 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004672 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 return -EINVAL;
4674 }
Jeff Johnson77848112016-06-29 14:52:06 -07004675 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676
4677 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004678 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679 goto fail;
4680 }
4681 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004682 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004684 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685 goto fail;
4686 }
4687
4688 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004689 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 goto fail;
4691 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004692 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304693 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004694 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004695 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696
Anurag Chouhanc5548422016-02-24 18:33:27 +05304697 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004698 &adapter->macAddressCurrent)) {
4699 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700 goto fail;
4701 }
4702
4703 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004704 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004705 goto fail;
4706 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304707 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004708 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004709 MAC_ADDR_ARRAY(dst_addr.bytes));
4710
4711 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004712 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 goto fail;
4714 }
4715 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004716 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717
4718 if (add_req->ucPtrnSize < 0 ||
4719 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4720 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004721 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722 add_req->ucPtrnSize);
4723 goto fail;
4724 }
4725
4726 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304727 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304728 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304729 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304730 QDF_MAC_ADDR_SIZE);
4731 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304732 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004733 len += 2;
4734
4735 /*
4736 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4737 * ------------------------------------------------------------
4738 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4739 * ------------------------------------------------------------
4740 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304741 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 nla_data(tb[PARAM_IP_PACKET]),
4743 add_req->ucPtrnSize);
4744 add_req->ucPtrnSize += len;
4745
4746 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4747 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004748 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749 goto fail;
4750 }
4751 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004752 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753
4754 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304755 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004756 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004757 goto fail;
4758 }
4759
4760 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304761 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 return 0;
4763
4764fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304765 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004766 return -EINVAL;
4767}
4768
4769/**
4770 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4771 * @adapter: adapter pointer
4772 * @hdd_ctx: hdd context
4773 * @tb: nl attributes
4774 *
4775 * This function reads the NL attributes and forms a DelTxPtrn message
4776 * posts it to SME.
4777 *
4778 */
4779static int
4780wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4781 struct nlattr **tb)
4782{
4783 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304784 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004785 uint32_t request_id, ret;
4786 uint8_t pattern_id = 0;
4787
4788 /* Parse and fetch request Id */
4789 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004790 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004791 return -EINVAL;
4792 }
4793 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4794 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004795 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004796 return -EINVAL;
4797 }
4798
4799 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4800 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004801 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004802 return -EINVAL;
4803 }
4804
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304805 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004806 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004807 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808 return -ENOMEM;
4809 }
4810
Anurag Chouhanc5548422016-02-24 18:33:27 +05304811 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004812 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004813 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004814 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 request_id, del_req->ucPtrnId);
4816
4817 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304818 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004819 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 goto fail;
4821 }
4822
4823 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304824 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825 return 0;
4826
4827fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304828 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004829 return -EINVAL;
4830}
4831
4832
4833/**
4834 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4835 * @wiphy: Pointer to wireless phy
4836 * @wdev: Pointer to wireless device
4837 * @data: Pointer to data
4838 * @data_len: Data length
4839 *
4840 * Return: 0 on success, negative errno on failure
4841 */
4842static int
4843__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4844 struct wireless_dev *wdev,
4845 const void *data,
4846 int data_len)
4847{
4848 struct net_device *dev = wdev->netdev;
4849 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4850 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4851 struct nlattr *tb[PARAM_MAX + 1];
4852 uint8_t control;
4853 int ret;
4854 static const struct nla_policy policy[PARAM_MAX + 1] = {
4855 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4856 [PARAM_CONTROL] = { .type = NLA_U32 },
4857 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304858 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304860 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861 [PARAM_PERIOD] = { .type = NLA_U32 },
4862 };
4863
Jeff Johnson1f61b612016-02-12 16:28:33 -08004864 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865
Anurag Chouhan6d760662016-02-20 16:05:43 +05304866 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 hdd_err("Command not allowed in FTM mode");
4868 return -EPERM;
4869 }
4870
4871 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304872 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874
4875 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004876 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 return -ENOTSUPP;
4878 }
4879
4880 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004881 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004882 return -EINVAL;
4883 }
4884
4885 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004886 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 return -EINVAL;
4888 }
4889 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004890 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891
4892 if (control == WLAN_START_OFFLOADED_PACKETS)
4893 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4894 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4895 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4896 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004897 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004898 return -EINVAL;
4899 }
4900}
4901
4902/*
4903 * done with short names for the global vendor params
4904 * used by __wlan_hdd_cfg80211_offloaded_packets()
4905 */
4906#undef PARAM_MAX
4907#undef PARAM_REQUEST_ID
4908#undef PARAM_CONTROL
4909#undef PARAM_IP_PACKET
4910#undef PARAM_SRC_MAC_ADDR
4911#undef PARAM_DST_MAC_ADDR
4912#undef PARAM_PERIOD
4913
4914/**
4915 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4916 * @wiphy: wiphy structure pointer
4917 * @wdev: Wireless device structure pointer
4918 * @data: Pointer to the data received
4919 * @data_len: Length of @data
4920 *
4921 * Return: 0 on success; errno on failure
4922 */
4923static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4924 struct wireless_dev *wdev,
4925 const void *data,
4926 int data_len)
4927{
4928 int ret = 0;
4929
4930 cds_ssr_protect(__func__);
4931 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4932 wdev, data, data_len);
4933 cds_ssr_unprotect(__func__);
4934
4935 return ret;
4936}
4937#endif
4938
4939/*
4940 * define short names for the global vendor params
4941 * used by __wlan_hdd_cfg80211_monitor_rssi()
4942 */
4943#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4944#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4945#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4946#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4947#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4948
4949/**
4950 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4951 * @wiphy: Pointer to wireless phy
4952 * @wdev: Pointer to wireless device
4953 * @data: Pointer to data
4954 * @data_len: Data length
4955 *
4956 * Return: 0 on success, negative errno on failure
4957 */
4958static int
4959__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4960 struct wireless_dev *wdev,
4961 const void *data,
4962 int data_len)
4963{
4964 struct net_device *dev = wdev->netdev;
4965 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4966 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4967 struct nlattr *tb[PARAM_MAX + 1];
4968 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304969 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970 int ret;
4971 uint32_t control;
4972 static const struct nla_policy policy[PARAM_MAX + 1] = {
4973 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4974 [PARAM_CONTROL] = { .type = NLA_U32 },
4975 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4976 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4977 };
4978
Jeff Johnson1f61b612016-02-12 16:28:33 -08004979 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004980
4981 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304982 if (ret)
4983 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984
4985 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004986 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987 return -ENOTSUPP;
4988 }
4989
4990 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004991 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004992 return -EINVAL;
4993 }
4994
4995 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004996 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997 return -EINVAL;
4998 }
4999
5000 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005001 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002 return -EINVAL;
5003 }
5004
5005 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5006 req.session_id = adapter->sessionId;
5007 control = nla_get_u32(tb[PARAM_CONTROL]);
5008
5009 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5010 req.control = true;
5011 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005012 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013 return -EINVAL;
5014 }
5015
5016 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005017 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 return -EINVAL;
5019 }
5020
5021 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5022 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5023
5024 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005025 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005026 req.min_rssi, req.max_rssi);
5027 return -EINVAL;
5028 }
Jeff Johnson77848112016-06-29 14:52:06 -07005029 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030 req.min_rssi, req.max_rssi);
5031
5032 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5033 req.control = false;
5034 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005035 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 return -EINVAL;
5037 }
Jeff Johnson77848112016-06-29 14:52:06 -07005038 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039 req.request_id, req.session_id, req.control);
5040
5041 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305042 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005043 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005044 return -EINVAL;
5045 }
5046
5047 return 0;
5048}
5049
5050/*
5051 * done with short names for the global vendor params
5052 * used by __wlan_hdd_cfg80211_monitor_rssi()
5053 */
5054#undef PARAM_MAX
5055#undef PARAM_CONTROL
5056#undef PARAM_REQUEST_ID
5057#undef PARAM_MAX_RSSI
5058#undef PARAM_MIN_RSSI
5059
5060/**
5061 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5062 * @wiphy: wiphy structure pointer
5063 * @wdev: Wireless device structure pointer
5064 * @data: Pointer to the data received
5065 * @data_len: Length of @data
5066 *
5067 * Return: 0 on success; errno on failure
5068 */
5069static int
5070wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5071 const void *data, int data_len)
5072{
5073 int ret;
5074
5075 cds_ssr_protect(__func__);
5076 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5077 cds_ssr_unprotect(__func__);
5078
5079 return ret;
5080}
5081
5082/**
5083 * hdd_rssi_threshold_breached() - rssi breached NL event
5084 * @hddctx: HDD context
5085 * @data: rssi breached event data
5086 *
5087 * This function reads the rssi breached event %data and fill in the skb with
5088 * NL attributes and send up the NL event.
5089 *
5090 * Return: none
5091 */
5092void hdd_rssi_threshold_breached(void *hddctx,
5093 struct rssi_breach_event *data)
5094{
5095 hdd_context_t *hdd_ctx = hddctx;
5096 struct sk_buff *skb;
5097
5098 ENTER();
5099
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305100 if (wlan_hdd_validate_context(hdd_ctx))
5101 return;
5102 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005103 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005104 return;
5105 }
5106
5107 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5108 NULL,
5109 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5110 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5111 GFP_KERNEL);
5112
5113 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005114 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005115 return;
5116 }
5117
Jeff Johnson77848112016-06-29 14:52:06 -07005118 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005119 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005120 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5122
5123 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5124 data->request_id) ||
5125 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5126 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5127 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5128 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005129 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005130 goto fail;
5131 }
5132
5133 cfg80211_vendor_event(skb, GFP_KERNEL);
5134 return;
5135
5136fail:
5137 kfree_skb(skb);
5138 return;
5139}
5140
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305141static const struct nla_policy
5142ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5143 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5144};
5145
5146/**
5147 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5148 * @wiphy: Pointer to wireless phy
5149 * @wdev: Pointer to wireless device
5150 * @data: Pointer to data
5151 * @data_len: Length of @data
5152 *
5153 * Return: 0 on success, negative errno on failure
5154 */
5155static int
5156__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5157 struct wireless_dev *wdev,
5158 const void *data, int data_len)
5159{
5160 int status;
5161 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5162 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005163 struct net_device *dev = wdev->netdev;
5164 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305165
5166 ENTER_DEV(wdev->netdev);
5167
5168 status = wlan_hdd_validate_context(pHddCtx);
5169 if (0 != status)
5170 return status;
5171 if (!pHddCtx->config->fhostNSOffload) {
5172 hdd_err("ND Offload not supported");
5173 return -EINVAL;
5174 }
5175
5176 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5177 (struct nlattr *)data,
5178 data_len, ns_offload_set_policy)) {
5179 hdd_err("nla_parse failed");
5180 return -EINVAL;
5181 }
5182
5183 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5184 hdd_err("ND Offload flag attribute not present");
5185 return -EINVAL;
5186 }
5187
5188 pHddCtx->ns_offload_enable =
5189 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5190
Dustin Brownd8279d22016-09-07 14:52:57 -07005191 /* update ns offload in case it is already enabled/disabled */
5192 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5193
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305194 return 0;
5195}
5196
5197/**
5198 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5199 * @wiphy: pointer to wireless wiphy structure.
5200 * @wdev: pointer to wireless_dev structure.
5201 * @data: Pointer to the data to be passed via vendor interface
5202 * @data_len:Length of the data to be passed
5203 *
5204 * Return: Return the Success or Failure code.
5205 */
5206static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5207 struct wireless_dev *wdev,
5208 const void *data, int data_len)
5209{
5210 int ret;
5211
5212 cds_ssr_protect(__func__);
5213 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5214 cds_ssr_unprotect(__func__);
5215
5216 return ret;
5217}
5218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5220 * @wiphy: Pointer to wireless phy
5221 * @wdev: Pointer to wireless device
5222 * @data: Pointer to data
5223 * @data_len: Data length
5224 *
5225 * This function return the preferred frequency list generated by the policy
5226 * manager.
5227 *
5228 * Return: success or failure code
5229 */
5230static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5231 struct wireless_dev
5232 *wdev, const void *data,
5233 int data_len)
5234{
5235 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5236 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305237 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305238 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305240 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 enum cds_con_mode intf_mode;
5242 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5243 struct sk_buff *reply_skb;
5244
Jeff Johnson1f61b612016-02-12 16:28:33 -08005245 ENTER_DEV(wdev->netdev);
5246
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 ret = wlan_hdd_validate_context(hdd_ctx);
5248 if (ret)
5249 return -EINVAL;
5250
5251 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5252 data, data_len, NULL)) {
5253 hdd_err("Invalid ATTR");
5254 return -EINVAL;
5255 }
5256
5257 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5258 hdd_err("attr interface type failed");
5259 return -EINVAL;
5260 }
5261
5262 intf_mode = nla_get_u32(tb
5263 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5264
5265 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5266 hdd_err("Invalid interface type");
5267 return -EINVAL;
5268 }
5269
5270 hdd_debug("Userspace requested pref freq list");
5271
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305272 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5273 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305274 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 hdd_err("Get pcl failed");
5276 return -EINVAL;
5277 }
5278
5279 /* convert channel number to frequency */
5280 for (i = 0; i < pcl_len; i++) {
5281 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5282 freq_list[i] =
5283 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005284 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 else
5286 freq_list[i] =
5287 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005288 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005289 }
5290
5291 /* send the freq_list back to supplicant */
5292 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5293 sizeof(u32) *
5294 pcl_len +
5295 NLMSG_HDRLEN);
5296
5297 if (!reply_skb) {
5298 hdd_err("Allocate reply_skb failed");
5299 return -EINVAL;
5300 }
5301
5302 if (nla_put_u32(reply_skb,
5303 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5304 intf_mode) ||
5305 nla_put(reply_skb,
5306 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5307 sizeof(uint32_t) * pcl_len,
5308 freq_list)) {
5309 hdd_err("nla put fail");
5310 kfree_skb(reply_skb);
5311 return -EINVAL;
5312 }
5313
5314 return cfg80211_vendor_cmd_reply(reply_skb);
5315}
5316
5317/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5318 * @wiphy: Pointer to wireless phy
5319 * @wdev: Pointer to wireless device
5320 * @data: Pointer to data
5321 * @data_len: Data length
5322 *
5323 * This function return the preferred frequency list generated by the policy
5324 * manager.
5325 *
5326 * Return: success or failure code
5327 */
5328static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5329 struct wireless_dev
5330 *wdev, const void *data,
5331 int data_len)
5332{
5333 int ret = 0;
5334
5335 cds_ssr_protect(__func__);
5336 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5337 data, data_len);
5338 cds_ssr_unprotect(__func__);
5339
5340 return ret;
5341}
5342
5343/**
5344 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5345 * @wiphy: Pointer to wireless phy
5346 * @wdev: Pointer to wireless device
5347 * @data: Pointer to data
5348 * @data_len: Data length
5349 *
5350 * Return: 0 on success, negative errno on failure
5351 */
5352static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5353 struct wireless_dev *wdev,
5354 const void *data,
5355 int data_len)
5356{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305357 struct net_device *ndev = wdev->netdev;
5358 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5360 int ret = 0;
5361 enum cds_con_mode intf_mode;
5362 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5363 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364
Jeff Johnson1f61b612016-02-12 16:28:33 -08005365 ENTER_DEV(ndev);
5366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 ret = wlan_hdd_validate_context(hdd_ctx);
5368 if (ret)
5369 return ret;
5370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5372 data, data_len, NULL)) {
5373 hdd_err("Invalid ATTR");
5374 return -EINVAL;
5375 }
5376
5377 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5378 hdd_err("attr interface type failed");
5379 return -EINVAL;
5380 }
5381
5382 intf_mode = nla_get_u32(tb
5383 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5384
5385 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5386 hdd_err("Invalid interface type");
5387 return -EINVAL;
5388 }
5389
5390 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5391 hdd_err("attr probable freq failed");
5392 return -EINVAL;
5393 }
5394
5395 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5396 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5397
5398 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005399 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400 channel_hint, HW_MODE_20_MHZ)) {
5401 hdd_err("Set channel hint failed due to concurrency check");
5402 return -EINVAL;
5403 }
5404
Krunal Soni09e55032016-06-07 10:06:55 -07005405 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5406 hdd_warn("Remain On Channel Pending");
5407
Krunal Soni3091bcc2016-06-23 12:28:21 -07005408 ret = qdf_reset_connection_update();
5409 if (!QDF_IS_STATUS_SUCCESS(ret))
5410 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411
Krunal Soni3091bcc2016-06-23 12:28:21 -07005412 ret = cds_current_connections_update(adapter->sessionId,
5413 channel_hint,
5414 SIR_UPDATE_REASON_SET_OPER_CHAN);
5415 if (QDF_STATUS_E_FAILURE == ret) {
5416 /* return in the failure case */
5417 hdd_err("ERROR: connections update failed!!");
5418 return -EINVAL;
5419 }
5420
5421 if (QDF_STATUS_SUCCESS == ret) {
5422 /*
5423 * Success is the only case for which we expect hw mode
5424 * change to take place, hence we need to wait.
5425 * For any other return value it should be a pass
5426 * through
5427 */
5428 ret = qdf_wait_for_connection_update();
5429 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5430 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 return -EINVAL;
5432 }
5433
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 }
5435
5436 return 0;
5437}
5438
5439/**
5440 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5441 * @wiphy: Pointer to wireless phy
5442 * @wdev: Pointer to wireless device
5443 * @data: Pointer to data
5444 * @data_len: Data length
5445 *
5446 * Return: 0 on success, negative errno on failure
5447 */
5448static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5449 struct wireless_dev *wdev,
5450 const void *data,
5451 int data_len)
5452{
5453 int ret = 0;
5454
5455 cds_ssr_protect(__func__);
5456 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5457 data, data_len);
5458 cds_ssr_unprotect(__func__);
5459
5460 return ret;
5461}
5462
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305463static const struct
5464nla_policy
5465qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5466 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5467};
5468
5469/**
5470 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5471 * @wiphy: WIPHY structure pointer
5472 * @wdev: Wireless device structure pointer
5473 * @data: Pointer to the data received
5474 * @data_len: Length of the data received
5475 *
5476 * This function is used to get link properties like nss, rate flags and
5477 * operating frequency for the active connection with the given peer.
5478 *
5479 * Return: 0 on success and errno on failure
5480 */
5481static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5482 struct wireless_dev *wdev,
5483 const void *data,
5484 int data_len)
5485{
5486 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5487 struct net_device *dev = wdev->netdev;
5488 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5489 hdd_station_ctx_t *hdd_sta_ctx;
5490 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305491 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305492 uint32_t sta_id;
5493 struct sk_buff *reply_skb;
5494 uint32_t rate_flags = 0;
5495 uint8_t nss;
5496 uint8_t final_rate_flags = 0;
5497 uint32_t freq;
5498
Jeff Johnson1f61b612016-02-12 16:28:33 -08005499 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305500
Anurag Chouhan6d760662016-02-20 16:05:43 +05305501 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305502 hdd_err("Command not allowed in FTM mode");
5503 return -EPERM;
5504 }
5505
5506 if (0 != wlan_hdd_validate_context(hdd_ctx))
5507 return -EINVAL;
5508
5509 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5510 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005511 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305512 return -EINVAL;
5513 }
5514
5515 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005516 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305517 adapter->device_mode);
5518 return -EINVAL;
5519 }
5520
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305521 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305522 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005523 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305524 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5525
Krunal Sonib4326f22016-03-10 13:05:51 -08005526 if (adapter->device_mode == QDF_STA_MODE ||
5527 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305528 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5529 if ((hdd_sta_ctx->conn_info.connState !=
5530 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305531 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305532 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005533 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305534 MAC_ADDR_ARRAY(peer_mac));
5535 return -EINVAL;
5536 }
5537
5538 nss = hdd_sta_ctx->conn_info.nss;
5539 freq = cds_chan_to_freq(
5540 hdd_sta_ctx->conn_info.operationChannel);
5541 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005542 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5543 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305544
5545 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5546 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305547 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305548 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305549 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305550 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305551 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305552 break;
5553 }
5554
5555 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005556 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305557 MAC_ADDR_ARRAY(peer_mac));
5558 return -EINVAL;
5559 }
5560
5561 nss = adapter->aStaInfo[sta_id].nss;
5562 freq = cds_chan_to_freq(
5563 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5564 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5565 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005566 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305567 MAC_ADDR_ARRAY(peer_mac));
5568 return -EINVAL;
5569 }
5570
5571 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5572 if (rate_flags & eHAL_TX_RATE_VHT80) {
5573 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005574#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305575 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005576#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305577 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5578 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005579#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305580 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005581#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305582 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5583 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5584 } else if (rate_flags &
5585 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5586 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005587#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305588 if (rate_flags & eHAL_TX_RATE_HT40)
5589 final_rate_flags |=
5590 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005591#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305592 }
5593
5594 if (rate_flags & eHAL_TX_RATE_SGI) {
5595 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5596 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5597 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5598 }
5599 }
5600
5601 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5602 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5603
5604 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005605 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305606 return -EINVAL;
5607 }
5608
5609 if (nla_put_u8(reply_skb,
5610 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5611 nss) ||
5612 nla_put_u8(reply_skb,
5613 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5614 final_rate_flags) ||
5615 nla_put_u32(reply_skb,
5616 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5617 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005618 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305619 kfree_skb(reply_skb);
5620 return -EINVAL;
5621 }
5622
5623 return cfg80211_vendor_cmd_reply(reply_skb);
5624}
5625
5626/**
5627 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5628 * properties.
5629 * @wiphy: WIPHY structure pointer
5630 * @wdev: Wireless device structure pointer
5631 * @data: Pointer to the data received
5632 * @data_len: Length of the data received
5633 *
5634 * This function is used to get link properties like nss, rate flags and
5635 * operating frequency for the active connection with the given peer.
5636 *
5637 * Return: 0 on success and errno on failure
5638 */
5639static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5640 struct wireless_dev *wdev,
5641 const void *data,
5642 int data_len)
5643{
5644 int ret = 0;
5645
5646 cds_ssr_protect(__func__);
5647 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5648 wdev, data, data_len);
5649 cds_ssr_unprotect(__func__);
5650
5651 return ret;
5652}
5653
Peng Xu278d0122015-09-24 16:34:17 -07005654static const struct
5655nla_policy
5656qca_wlan_vendor_ota_test_policy
5657[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5658 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5659};
5660
5661/**
5662 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5663 * @wiphy: Pointer to wireless phy
5664 * @wdev: Pointer to wireless device
5665 * @data: Pointer to data
5666 * @data_len: Data length
5667 *
5668 * Return: 0 on success, negative errno on failure
5669 */
5670static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5671 struct wireless_dev *wdev,
5672 const void *data,
5673 int data_len)
5674{
5675 struct net_device *dev = wdev->netdev;
5676 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5677 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5678 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5679 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5680 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305681 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005682 uint32_t current_roam_state;
5683
Jeff Johnson1f61b612016-02-12 16:28:33 -08005684 ENTER_DEV(dev);
5685
Anurag Chouhan6d760662016-02-20 16:05:43 +05305686 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005687 hdd_err("Command not allowed in FTM mode");
5688 return -EPERM;
5689 }
5690
5691 if (0 != wlan_hdd_validate_context(hdd_ctx))
5692 return -EINVAL;
5693
5694 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5695 data, data_len,
5696 qca_wlan_vendor_ota_test_policy)) {
5697 hdd_err("invalid attr");
5698 return -EINVAL;
5699 }
5700
5701 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5702 hdd_err("attr ota test failed");
5703 return -EINVAL;
5704 }
5705
5706 ota_enable = nla_get_u8(
5707 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5708
5709 hdd_info(" OTA test enable = %d", ota_enable);
5710 if (ota_enable != 1) {
5711 hdd_err("Invalid value, only enable test mode is supported!");
5712 return -EINVAL;
5713 }
5714
5715 current_roam_state =
5716 sme_get_current_roam_state(hal, adapter->sessionId);
5717 status = sme_stop_roaming(hal, adapter->sessionId,
5718 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305719 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005720 hdd_err("Enable/Disable roaming failed");
5721 return -EINVAL;
5722 }
5723
5724 status = sme_ps_enable_disable(hal, adapter->sessionId,
5725 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305726 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005727 hdd_err("Enable/Disable power save failed");
5728 /* restore previous roaming setting */
5729 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5730 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5731 status = sme_start_roaming(hal, adapter->sessionId,
5732 eCsrHddIssued);
5733 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5734 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5735 status = sme_stop_roaming(hal, adapter->sessionId,
5736 eCsrHddIssued);
5737
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305738 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005739 hdd_err("Restoring roaming state failed");
5740
5741 return -EINVAL;
5742 }
5743
5744
5745 return 0;
5746}
5747
5748/**
5749 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5750 * @wiphy: Pointer to wireless phy
5751 * @wdev: Pointer to wireless device
5752 * @data: Pointer to data
5753 * @data_len: Data length
5754 *
5755 * Return: 0 on success, negative errno on failure
5756 */
5757static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5758 struct wireless_dev *wdev,
5759 const void *data,
5760 int data_len)
5761{
5762 int ret = 0;
5763
5764 cds_ssr_protect(__func__);
5765 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5766 cds_ssr_unprotect(__func__);
5767
5768 return ret;
5769}
5770
Peng Xu4d67c8f2015-10-16 16:02:26 -07005771/**
5772 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5773 * @wiphy: Pointer to wireless phy
5774 * @wdev: Pointer to wireless device
5775 * @data: Pointer to data
5776 * @data_len: Data length
5777 *
5778 * Return: 0 on success, negative errno on failure
5779 */
5780static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5781 struct wireless_dev *wdev,
5782 const void *data,
5783 int data_len)
5784{
5785 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5786 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005787 hdd_adapter_t *adapter;
5788 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005789 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5790 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005791 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005792
Jeff Johnson1f61b612016-02-12 16:28:33 -08005793 ENTER_DEV(dev);
5794
Peng Xu4d67c8f2015-10-16 16:02:26 -07005795 ret = wlan_hdd_validate_context(hdd_ctx);
5796 if (ret)
5797 return ret;
5798
5799 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5800
5801 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5802 data, data_len, NULL)) {
5803 hdd_err("Invalid ATTR");
5804 return -EINVAL;
5805 }
5806
5807 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5808 hdd_err("attr tx power scale failed");
5809 return -EINVAL;
5810 }
5811
5812 scale_value = nla_get_u8(tb
5813 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5814
5815 if (scale_value > MAX_TXPOWER_SCALE) {
5816 hdd_err("Invalid tx power scale level");
5817 return -EINVAL;
5818 }
5819
Peng Xu62c8c432016-05-09 15:23:02 -07005820 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005821
Peng Xu62c8c432016-05-09 15:23:02 -07005822 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005823 hdd_err("Set tx power scale failed");
5824 return -EINVAL;
5825 }
5826
5827 return 0;
5828}
5829
5830/**
5831 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5832 * @wiphy: Pointer to wireless phy
5833 * @wdev: Pointer to wireless device
5834 * @data: Pointer to data
5835 * @data_len: Data length
5836 *
5837 * Return: 0 on success, negative errno on failure
5838 */
5839static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5840 struct wireless_dev *wdev,
5841 const void *data,
5842 int data_len)
5843{
Peng Xu62c8c432016-05-09 15:23:02 -07005844 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005845
5846 cds_ssr_protect(__func__);
5847 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5848 data, data_len);
5849 cds_ssr_unprotect(__func__);
5850
5851 return ret;
5852}
5853
5854/**
5855 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5856 * @wiphy: Pointer to wireless phy
5857 * @wdev: Pointer to wireless device
5858 * @data: Pointer to data
5859 * @data_len: Data length
5860 *
5861 * Return: 0 on success, negative errno on failure
5862 */
5863static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5864 struct wireless_dev *wdev,
5865 const void *data,
5866 int data_len)
5867{
5868 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5869 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005870 hdd_adapter_t *adapter;
5871 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005872 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5873 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005874 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005875
Jeff Johnson1f61b612016-02-12 16:28:33 -08005876 ENTER_DEV(dev);
5877
Peng Xu4d67c8f2015-10-16 16:02:26 -07005878 ret = wlan_hdd_validate_context(hdd_ctx);
5879 if (ret)
5880 return ret;
5881
5882 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5883
5884 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5885 data, data_len, NULL)) {
5886 hdd_err("Invalid ATTR");
5887 return -EINVAL;
5888 }
5889
5890 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5891 hdd_err("attr tx power decrease db value failed");
5892 return -EINVAL;
5893 }
5894
5895 scale_value = nla_get_u8(tb
5896 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5897
Peng Xu62c8c432016-05-09 15:23:02 -07005898 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5899 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005900
Peng Xu62c8c432016-05-09 15:23:02 -07005901 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005902 hdd_err("Set tx power decrease db failed");
5903 return -EINVAL;
5904 }
5905
5906 return 0;
5907}
5908
5909/**
5910 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5911 * @wiphy: Pointer to wireless phy
5912 * @wdev: Pointer to wireless device
5913 * @data: Pointer to data
5914 * @data_len: Data length
5915 *
5916 * Return: 0 on success, negative errno on failure
5917 */
5918static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5919 struct wireless_dev *wdev,
5920 const void *data,
5921 int data_len)
5922{
Peng Xu62c8c432016-05-09 15:23:02 -07005923 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005924
5925 cds_ssr_protect(__func__);
5926 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5927 data, data_len);
5928 cds_ssr_unprotect(__func__);
5929
5930 return ret;
5931}
Peng Xu8fdaa492016-06-22 10:20:47 -07005932
5933/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305934 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5935 * @wiphy: Pointer to wireless phy
5936 * @wdev: Pointer to wireless device
5937 * @data: Pointer to data
5938 * @data_len: Data length
5939 *
5940 * Processes the conditional channel switch request and invokes the helper
5941 * APIs to process the channel switch request.
5942 *
5943 * Return: 0 on success, negative errno on failure
5944 */
5945static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5946 struct wireless_dev *wdev,
5947 const void *data,
5948 int data_len)
5949{
5950 int ret;
5951 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5952 struct net_device *dev = wdev->netdev;
5953 hdd_adapter_t *adapter;
5954 struct nlattr
5955 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5956 uint32_t freq_len, i;
5957 uint32_t *freq;
5958 uint8_t chans[QDF_MAX_NUM_CHAN];
5959
5960 ENTER_DEV(dev);
5961
5962 ret = wlan_hdd_validate_context(hdd_ctx);
5963 if (ret)
5964 return ret;
5965
5966 if (!hdd_ctx->config->enableDFSMasterCap) {
5967 hdd_err("DFS master capability is not present in the driver");
5968 return -EINVAL;
5969 }
5970
5971 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5972 hdd_err("Command not allowed in FTM mode");
5973 return -EPERM;
5974 }
5975
5976 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5977 if (adapter->device_mode != QDF_SAP_MODE) {
5978 hdd_err("Invalid device mode %d", adapter->device_mode);
5979 return -EINVAL;
5980 }
5981
5982 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5983 data, data_len, NULL)) {
5984 hdd_err("Invalid ATTR");
5985 return -EINVAL;
5986 }
5987
5988 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5989 hdd_err("Frequency list is missing");
5990 return -EINVAL;
5991 }
5992
5993 freq_len = nla_len(
5994 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5995 sizeof(uint32_t);
5996
5997 if (freq_len > QDF_MAX_NUM_CHAN) {
5998 hdd_err("insufficient space to hold channels");
5999 return -ENOMEM;
6000 }
6001
6002 hdd_debug("freq_len=%d", freq_len);
6003
6004 freq = nla_data(
6005 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6006
6007
6008 for (i = 0; i < freq_len; i++) {
6009 if (freq[i] == 0)
6010 chans[i] = 0;
6011 else
6012 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6013
6014 hdd_debug("freq[%d]=%d", i, freq[i]);
6015 }
6016
6017 /*
6018 * The input frequency list from user space is designed to be a
6019 * priority based frequency list. This is only to accommodate any
6020 * future request. But, current requirement is only to perform CAC
6021 * on a single channel. So, the first entry from the list is picked.
6022 *
6023 * If channel is zero, any channel in the available outdoor regulatory
6024 * domain will be selected.
6025 */
6026 ret = wlan_hdd_request_pre_cac(chans[0]);
6027 if (ret) {
6028 hdd_err("pre cac request failed with reason:%d", ret);
6029 return ret;
6030 }
6031
6032 return 0;
6033}
6034
6035/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006036 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6037 * @wiphy: Pointer to wireless phy
6038 * @wdev: Pointer to wireless device
6039 * @data: Pointer to data
6040 * @data_len: Data length
6041 *
6042 * This function is to process the p2p listen offload start vendor
6043 * command. It parses the input parameters and invoke WMA API to
6044 * send the command to firmware.
6045 *
6046 * Return: 0 on success, negative errno on failure
6047 */
6048static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6049 struct wireless_dev *wdev,
6050 const void *data,
6051 int data_len)
6052{
6053 int ret;
6054 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6055 struct net_device *dev = wdev->netdev;
6056 hdd_adapter_t *adapter;
6057 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6058 struct sir_p2p_lo_start params;
6059 QDF_STATUS status;
6060
6061 ENTER_DEV(dev);
6062
6063 ret = wlan_hdd_validate_context(hdd_ctx);
6064 if (ret)
6065 return ret;
6066
6067 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6068 hdd_err("Command not allowed in FTM mode");
6069 return -EPERM;
6070 }
6071
6072 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6073 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6074 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6075 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6076 hdd_err("Invalid device mode %d", adapter->device_mode);
6077 return -EINVAL;
6078 }
6079
6080 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6081 data, data_len, NULL)) {
6082 hdd_err("Invalid ATTR");
6083 return -EINVAL;
6084 }
6085
6086 memset(&params, 0, sizeof(params));
6087
6088 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6089 params.ctl_flags = 1; /* set to default value */
6090 else
6091 params.ctl_flags = nla_get_u32(tb
6092 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6093
6094 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6095 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6096 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6097 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6098 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6099 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6100 hdd_err("Attribute parsing failed");
6101 return -EINVAL;
6102 }
6103
6104 params.vdev_id = adapter->sessionId;
6105 params.freq = nla_get_u32(tb
6106 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6107 if ((params.freq != 2412) && (params.freq != 2437) &&
6108 (params.freq != 2462)) {
6109 hdd_err("Invalid listening channel: %d", params.freq);
6110 return -EINVAL;
6111 }
6112
6113 params.period = nla_get_u32(tb
6114 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6115 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6116 hdd_err("Invalid period: %d", params.period);
6117 return -EINVAL;
6118 }
6119
6120 params.interval = nla_get_u32(tb
6121 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6122 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6123 hdd_err("Invalid interval: %d", params.interval);
6124 return -EINVAL;
6125 }
6126
6127 params.count = nla_get_u32(tb
6128 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6129 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6130 hdd_err("Invalid count: %d", params.count);
6131 return -EINVAL;
6132 }
6133
6134 params.device_types = nla_data(tb
6135 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6136 if (params.device_types == NULL) {
6137 hdd_err("Invalid device types");
6138 return -EINVAL;
6139 }
6140
6141 params.dev_types_len = nla_len(tb
6142 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6143 if (params.dev_types_len < 8) {
6144 hdd_err("Invalid device type length: %d", params.dev_types_len);
6145 return -EINVAL;
6146 }
6147
6148 params.probe_resp_tmplt = nla_data(tb
6149 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6150 if (params.probe_resp_tmplt == NULL) {
6151 hdd_err("Invalid probe response template");
6152 return -EINVAL;
6153 }
6154
6155 params.probe_resp_len = nla_len(tb
6156 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6157 if (params.probe_resp_len == 0) {
6158 hdd_err("Invalid probe resp template length: %d",
6159 params.probe_resp_len);
6160 return -EINVAL;
6161 }
6162
6163 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6164 params.freq, params.period, params.interval, params.count);
6165
6166 status = wma_p2p_lo_start(&params);
6167
6168 if (!QDF_IS_STATUS_SUCCESS(status)) {
6169 hdd_err("P2P LO start failed");
6170 return -EINVAL;
6171 }
6172
6173 return 0;
6174}
6175
6176
6177/**
6178 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6179 * @wiphy: Pointer to wireless phy
6180 * @wdev: Pointer to wireless device
6181 * @data: Pointer to data
6182 * @data_len: Data length
6183 *
6184 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6185 * to process p2p listen offload start vendor command.
6186 *
6187 * Return: 0 on success, negative errno on failure
6188 */
6189static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6190 struct wireless_dev *wdev,
6191 const void *data,
6192 int data_len)
6193{
6194 int ret = 0;
6195
6196 cds_ssr_protect(__func__);
6197 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6198 data, data_len);
6199 cds_ssr_unprotect(__func__);
6200
6201 return ret;
6202}
6203
6204/**
6205 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6206 * @wiphy: Pointer to wireless phy
6207 * @wdev: Pointer to wireless device
6208 * @data: Pointer to data
6209 * @data_len: Data length
6210 *
6211 * This function is to process the p2p listen offload stop vendor
6212 * command. It invokes WMA API to send command to firmware.
6213 *
6214 * Return: 0 on success, negative errno on failure
6215 */
6216static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6217 struct wireless_dev *wdev,
6218 const void *data,
6219 int data_len)
6220{
6221 QDF_STATUS status;
6222 hdd_adapter_t *adapter;
6223 struct net_device *dev = wdev->netdev;
6224
6225 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6226 hdd_err("Command not allowed in FTM mode");
6227 return -EPERM;
6228 }
6229
6230 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6231 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6232 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6233 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6234 hdd_err("Invalid device mode");
6235 return -EINVAL;
6236 }
6237
6238 status = wma_p2p_lo_stop(adapter->sessionId);
6239
6240 if (!QDF_IS_STATUS_SUCCESS(status)) {
6241 hdd_err("P2P LO stop failed");
6242 return -EINVAL;
6243 }
6244
6245 return 0;
6246}
6247
6248/**
6249 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6250 * @wiphy: Pointer to wireless phy
6251 * @wdev: Pointer to wireless device
6252 * @data: Pointer to data
6253 * @data_len: Data length
6254 *
6255 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6256 * to process p2p listen offload stop vendor command.
6257 *
6258 * Return: 0 on success, negative errno on failure
6259 */
6260static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6261 struct wireless_dev *wdev,
6262 const void *data,
6263 int data_len)
6264{
6265 int ret = 0;
6266
6267 cds_ssr_protect(__func__);
6268 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6269 data, data_len);
6270 cds_ssr_unprotect(__func__);
6271
6272 return ret;
6273}
6274
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306275/**
6276 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6277 * @wiphy: Pointer to wireless phy
6278 * @wdev: Pointer to wireless device
6279 * @data: Pointer to data
6280 * @data_len: Data length
6281 *
6282 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6283 * to process the conditional channel switch request.
6284 *
6285 * Return: 0 on success, negative errno on failure
6286 */
6287static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6288 struct wireless_dev *wdev,
6289 const void *data,
6290 int data_len)
6291{
6292 int ret;
6293
6294 cds_ssr_protect(__func__);
6295 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6296 data, data_len);
6297 cds_ssr_unprotect(__func__);
6298
6299 return ret;
6300}
6301
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306302/*
6303 * define short names for the global vendor params
6304 * used by __wlan_hdd_cfg80211_bpf_offload()
6305 */
6306#define BPF_INVALID \
6307 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6308#define BPF_SET_RESET \
6309 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6310#define BPF_VERSION \
6311 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6312#define BPF_FILTER_ID \
6313 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6314#define BPF_PACKET_SIZE \
6315 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6316#define BPF_CURRENT_OFFSET \
6317 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6318#define BPF_PROGRAM \
6319 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6320#define BPF_MAX \
6321 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006322
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306323static const struct nla_policy
6324wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6325 [BPF_SET_RESET] = {.type = NLA_U32},
6326 [BPF_VERSION] = {.type = NLA_U32},
6327 [BPF_FILTER_ID] = {.type = NLA_U32},
6328 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6329 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6330 [BPF_PROGRAM] = {.type = NLA_U8},
6331};
6332
6333/**
6334 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6335 * @hdd_context: hdd_context
6336 * @bpf_get_offload: struct for get offload
6337 *
6338 * This function receives the response/data from the lower layer and
6339 * checks to see if the thread is still waiting then post the results to
6340 * upper layer, if the request has timed out then ignore.
6341 *
6342 * Return: None
6343 */
6344void hdd_get_bpf_offload_cb(void *hdd_context,
6345 struct sir_bpf_get_offload *data)
6346{
6347 hdd_context_t *hdd_ctx = hdd_context;
6348 struct hdd_bpf_context *context;
6349
6350 ENTER();
6351
6352 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006353 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306354 data);
6355 return;
6356 }
6357
6358 spin_lock(&hdd_context_lock);
6359
6360 context = &bpf_context;
6361 /* The caller presumably timed out so there is nothing we can do */
6362 if (context->magic != BPF_CONTEXT_MAGIC) {
6363 spin_unlock(&hdd_context_lock);
6364 return;
6365 }
6366
6367 /* context is valid so caller is still waiting */
6368 /* paranoia: invalidate the magic */
6369 context->magic = 0;
6370
6371 context->capability_response = *data;
6372 complete(&context->completion);
6373
6374 spin_unlock(&hdd_context_lock);
6375
6376 return;
6377}
6378
6379/**
6380 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6381 * @hdd_context: hdd_context
6382 * @bpf_get_offload: struct for get offload
6383 *
6384 * Return: 0 on success, error number otherwise.
6385 */
6386static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6387 struct sir_bpf_get_offload *bpf_get_offload)
6388{
6389 struct sk_buff *skb;
6390 uint32_t nl_buf_len;
6391
6392 ENTER();
6393
6394 nl_buf_len = NLMSG_HDRLEN;
6395 nl_buf_len +=
6396 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6397 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6398
6399 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6400 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006401 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306402 return -ENOMEM;
6403 }
6404
Jeff Johnson77848112016-06-29 14:52:06 -07006405 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306406 bpf_get_offload->bpf_version,
6407 bpf_get_offload->max_bytes_for_bpf_inst);
6408
6409 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6410 bpf_get_offload->max_bytes_for_bpf_inst) ||
6411 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006412 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306413 goto nla_put_failure;
6414 }
6415
6416 cfg80211_vendor_cmd_reply(skb);
6417 EXIT();
6418 return 0;
6419
6420nla_put_failure:
6421 kfree_skb(skb);
6422 return -EINVAL;
6423}
6424
6425/**
6426 * hdd_get_bpf_offload - Get BPF offload Capabilities
6427 * @hdd_ctx: Hdd context
6428 *
6429 * Return: 0 on success, errno on failure
6430 */
6431static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6432{
6433 unsigned long rc;
6434 struct hdd_bpf_context *context;
6435 QDF_STATUS status;
6436 int ret;
6437
6438 ENTER();
6439
6440 spin_lock(&hdd_context_lock);
6441 context = &bpf_context;
6442 context->magic = BPF_CONTEXT_MAGIC;
6443 INIT_COMPLETION(context->completion);
6444 spin_unlock(&hdd_context_lock);
6445
6446 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6447 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006448 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306449 return -EINVAL;
6450 }
6451 /* request was sent -- wait for the response */
6452 rc = wait_for_completion_timeout(&context->completion,
6453 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6454 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006455 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306456 spin_lock(&hdd_context_lock);
6457 context->magic = 0;
6458 spin_unlock(&hdd_context_lock);
6459
6460 return -ETIMEDOUT;
6461 }
6462 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6463 &bpf_context.capability_response);
6464 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006465 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306466
6467 EXIT();
6468 return ret;
6469}
6470
6471/**
6472 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6473 * @hdd_ctx: Hdd context
6474 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306475 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306476 *
6477 * Return: 0 on success; errno on failure
6478 */
6479static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6480 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306481 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306482{
6483 struct sir_bpf_set_offload *bpf_set_offload;
6484 QDF_STATUS status;
6485 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306486 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306487
6488 ENTER();
6489
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306490 if (adapter->device_mode == QDF_STA_MODE ||
6491 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6492 if (!hdd_conn_is_connected(
6493 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6494 hdd_err("Not in Connected state!");
6495 return -ENOTSUPP;
6496 }
6497 }
6498
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306499 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6500 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006501 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306502 return -ENOMEM;
6503 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306504
6505 /* Parse and fetch bpf packet size */
6506 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006507 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306508 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306509 goto fail;
6510 }
6511 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6512
6513 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006514 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306515 goto post_sme;
6516 }
6517
6518 /* Parse and fetch bpf program */
6519 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006520 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306521 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306522 goto fail;
6523 }
6524
6525 prog_len = nla_len(tb[BPF_PROGRAM]);
6526 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306527
6528 if (bpf_set_offload->program == NULL) {
6529 hdd_err("qdf_mem_malloc failed for bpf offload program");
6530 ret = -ENOMEM;
6531 goto fail;
6532 }
6533
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306534 bpf_set_offload->current_length = prog_len;
6535 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306536 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306537
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306538 hdd_info("BPF set instructions");
6539 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6540 bpf_set_offload->program, prog_len);
6541
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306542 /* Parse and fetch filter Id */
6543 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006544 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306545 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306546 goto fail;
6547 }
6548 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6549
6550 /* Parse and fetch current offset */
6551 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006552 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306553 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306554 goto fail;
6555 }
6556 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6557
6558post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006559 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 +05306560 bpf_set_offload->session_id,
6561 bpf_set_offload->version,
6562 bpf_set_offload->filter_id,
6563 bpf_set_offload->total_length,
6564 bpf_set_offload->current_length,
6565 bpf_set_offload->current_offset);
6566
6567 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6568 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006569 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306570 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306571 goto fail;
6572 }
6573 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306574
6575fail:
6576 if (bpf_set_offload->current_length)
6577 qdf_mem_free(bpf_set_offload->program);
6578 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306579 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306580}
6581
6582/**
6583 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6584 * @wiphy: wiphy structure pointer
6585 * @wdev: Wireless device structure pointer
6586 * @data: Pointer to the data received
6587 * @data_len: Length of @data
6588 *
6589 * Return: 0 on success; errno on failure
6590 */
6591static int
6592__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6593 struct wireless_dev *wdev,
6594 const void *data, int data_len)
6595{
6596 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6597 struct net_device *dev = wdev->netdev;
6598 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6599 struct nlattr *tb[BPF_MAX + 1];
6600 int ret_val, packet_filter_subcmd;
6601
6602 ENTER();
6603
6604 ret_val = wlan_hdd_validate_context(hdd_ctx);
6605 if (ret_val)
6606 return ret_val;
6607
6608 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006609 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306610 return -EINVAL;
6611 }
6612
6613 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006614 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306615 return -ENOTSUPP;
6616 }
6617
6618 if (nla_parse(tb, BPF_MAX, data, data_len,
6619 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006620 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306621 return -EINVAL;
6622 }
6623
6624 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006625 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306626 return -EINVAL;
6627 }
6628
6629 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6630
6631 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6632 return hdd_get_bpf_offload(hdd_ctx);
6633 else
6634 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306635 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306636}
6637
6638/**
6639 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6640 * @wiphy: wiphy structure pointer
6641 * @wdev: Wireless device structure pointer
6642 * @data: Pointer to the data received
6643 * @data_len: Length of @data
6644 *
6645 * Return: 0 on success; errno on failure
6646 */
6647
6648static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6649 struct wireless_dev *wdev,
6650 const void *data, int data_len)
6651{
6652 int ret;
6653
6654 cds_ssr_protect(__func__);
6655 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6656 cds_ssr_unprotect(__func__);
6657
6658 return ret;
6659}
6660
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306661/**
6662 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6663 * @pre_cac_adapter: AP adapter used for pre cac
6664 * @status: Status (true or false)
6665 * @handle: Global handle
6666 *
6667 * Sets the status of pre cac i.e., whether the pre cac is active or not
6668 *
6669 * Return: Zero on success, non-zero on failure
6670 */
6671static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6672 bool status, tHalHandle handle)
6673{
6674 QDF_STATUS ret;
6675
6676 ret = wlan_sap_set_pre_cac_status(
6677 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6678 if (QDF_IS_STATUS_ERROR(ret))
6679 return -EINVAL;
6680
6681 return 0;
6682}
6683
6684/**
6685 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6686 * @ap_adapter: AP adapter
6687 * @chan_before_pre_cac: Channel
6688 *
6689 * Saves the channel which the AP was beaconing on before moving to the pre
6690 * cac channel. If radar is detected on the pre cac channel, this saved
6691 * channel will be used for AP operations.
6692 *
6693 * Return: Zero on success, non-zero on failure
6694 */
6695static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6696 uint8_t chan_before_pre_cac)
6697{
6698 QDF_STATUS ret;
6699
6700 ret = wlan_sap_set_chan_before_pre_cac(
6701 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6702 if (QDF_IS_STATUS_ERROR(ret))
6703 return -EINVAL;
6704
6705 return 0;
6706}
6707
6708/**
6709 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6710 * @ap_adapter: AP adapter
6711 * @nol: Non-occupancy list
6712 * @nol_len: Length of NOL
6713 *
6714 * Get the NOL for SAP
6715 *
6716 * Return: Zero on success, non-zero on failure
6717 */
6718static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6719 uint32_t *nol_len)
6720{
6721 QDF_STATUS ret;
6722
6723 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6724 nol, nol_len);
6725 if (QDF_IS_STATUS_ERROR(ret))
6726 return -EINVAL;
6727
6728 return 0;
6729}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306730
6731/**
6732 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6733 * @hdd_ctx: HDD context
6734 * @ap_adapter: AP adapter
6735 * @channel: Channel requested by userspace
6736 * @pre_cac_chan: Pointer to the pre CAC channel
6737 *
6738 * Validates the channel provided by userspace. If user provided channel 0,
6739 * a valid outdoor channel must be selected from the regulatory channel.
6740 *
6741 * Return: Zero on success and non zero value on error
6742 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006743static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6744 hdd_adapter_t *ap_adapter,
6745 uint8_t channel,
6746 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306747{
6748 uint32_t i, j;
6749 QDF_STATUS status;
6750 int ret;
6751 uint8_t nol[QDF_MAX_NUM_CHAN];
6752 uint32_t nol_len = 0, weight_len = 0;
6753 bool found;
6754 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6755 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6756 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6757
6758 if (0 == channel) {
6759 /* Channel is not obtained from PCL because PCL may not have
6760 * the entire channel list. For example: if SAP is up on
6761 * channel 6 and PCL is queried for the next SAP interface,
6762 * if SCC is preferred, the PCL will contain only the channel
6763 * 6. But, we are in need of a DFS channel. So, going with the
6764 * first channel from the valid channel list.
6765 */
6766 status = cds_get_valid_chans(channel_list, &len);
6767 if (QDF_IS_STATUS_ERROR(status)) {
6768 hdd_err("Failed to get channel list");
6769 return -EINVAL;
6770 }
6771 cds_update_with_safe_channel_list(channel_list, &len,
6772 pcl_weights, weight_len);
6773 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6774 for (i = 0; i < len; i++) {
6775 found = false;
6776 for (j = 0; j < nol_len; j++) {
6777 if (channel_list[i] == nol[j]) {
6778 found = true;
6779 break;
6780 }
6781 }
6782 if (found)
6783 continue;
6784 if (CDS_IS_DFS_CH(channel_list[i])) {
6785 *pre_cac_chan = channel_list[i];
6786 break;
6787 }
6788 }
6789 if (*pre_cac_chan == 0) {
6790 hdd_err("unable to find outdoor channel");
6791 return -EINVAL;
6792 }
6793 } else {
6794 /* Only when driver selects a channel, check is done for
6795 * unnsafe and NOL channels. When user provides a fixed channel
6796 * the user is expected to take care of this.
6797 */
6798 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6799 !CDS_IS_DFS_CH(channel)) {
6800 hdd_err("Invalid channel for pre cac:%d", channel);
6801 return -EINVAL;
6802 } else {
6803 *pre_cac_chan = channel;
6804 }
6805 }
6806 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6807 return 0;
6808}
6809
6810/**
6811 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6812 * @channel: Channel option provided by userspace
6813 *
6814 * Sets the driver to the required hardware mode and start an adapater for
6815 * pre CAC which will mimic an AP.
6816 *
6817 * Return: Zero on success, non-zero value on error
6818 */
6819int wlan_hdd_request_pre_cac(uint8_t channel)
6820{
6821 uint8_t pre_cac_chan = 0;
6822 hdd_context_t *hdd_ctx;
6823 int ret;
6824 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6825 hdd_ap_ctx_t *hdd_ap_ctx;
6826 QDF_STATUS status;
6827 struct wiphy *wiphy;
6828 struct net_device *dev;
6829 struct cfg80211_chan_def chandef;
6830 enum nl80211_channel_type channel_type;
6831 uint32_t freq;
6832 struct ieee80211_channel *chan;
6833 tHalHandle handle;
6834 bool val;
6835
6836 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6837 if (0 != wlan_hdd_validate_context(hdd_ctx))
6838 return -EINVAL;
6839
6840 if (cds_get_connection_count() > 1) {
6841 hdd_err("pre cac not allowed in concurrency");
6842 return -EINVAL;
6843 }
6844
6845 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6846 if (!ap_adapter) {
6847 hdd_err("unable to get SAP adapter");
6848 return -EINVAL;
6849 }
6850
6851 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6852 if (!handle) {
6853 hdd_err("Invalid handle");
6854 return -EINVAL;
6855 }
6856
6857 val = wlan_sap_is_pre_cac_active(handle);
6858 if (val) {
6859 hdd_err("pre cac is already in progress");
6860 return -EINVAL;
6861 }
6862
6863 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6864 if (!hdd_ap_ctx) {
6865 hdd_err("SAP context is NULL");
6866 return -EINVAL;
6867 }
6868
6869 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6870 hdd_err("SAP is already on DFS channel:%d",
6871 hdd_ap_ctx->operatingChannel);
6872 return -EINVAL;
6873 }
6874
6875 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6876 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6877 hdd_ap_ctx->operatingChannel);
6878 return -EINVAL;
6879 }
6880
6881 hdd_info("channel:%d", channel);
6882
6883 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6884 &pre_cac_chan);
6885 if (ret != 0)
6886 return ret;
6887
6888 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6889 * connection update should result in DBS mode
6890 */
6891 status = cds_update_and_wait_for_connection_update(
6892 ap_adapter->sessionId,
6893 pre_cac_chan,
6894 SIR_UPDATE_REASON_PRE_CAC);
6895 if (QDF_IS_STATUS_ERROR(status)) {
6896 hdd_err("error in moving to DBS mode");
6897 return -EINVAL;
6898 }
6899
6900 hdd_debug("starting pre cac SAP adapter");
6901
6902 /* Starting a SAP adapter:
6903 * Instead of opening an adapter, we could just do a SME open session
6904 * for AP type. But, start BSS would still need an adapter.
6905 * So, this option is not taken.
6906 *
6907 * hdd open adapter is going to register this precac interface with
6908 * user space. This interface though exposed to user space will be in
6909 * DOWN state. Consideration was done to avoid this registration to the
6910 * user space. But, as part of SAP operations multiple events are sent
6911 * to user space. Some of these events received from unregistered
6912 * interface was causing crashes. So, retaining the registration.
6913 *
6914 * So, this interface would remain registered and will remain in DOWN
6915 * state for the CAC duration. We will add notes in the feature
6916 * announcement to not use this temporary interface for any activity
6917 * from user space.
6918 */
6919 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6920 wlan_hdd_get_intf_addr(hdd_ctx),
6921 NET_NAME_UNKNOWN, true);
6922 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306923 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306924 return -EINVAL;
6925 }
6926
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306927 /*
6928 * This interface is internally created by the driver. So, no interface
6929 * up comes for this interface from user space and hence starting
6930 * the adapter internally.
6931 */
6932 if (hdd_start_adapter(pre_cac_adapter)) {
6933 hdd_err("error starting the pre cac adapter");
6934 goto close_pre_cac_adapter;
6935 }
6936
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306937 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6938
6939 wiphy = hdd_ctx->wiphy;
6940 dev = pre_cac_adapter->dev;
6941
6942 /* Since this is only a dummy interface lets us use the IEs from the
6943 * other active SAP interface. In regular scenarios, these IEs would
6944 * come from the user space entity
6945 */
6946 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6947 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6948 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6949 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306950 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306951 }
6952 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6953 ap_adapter->sessionCtx.ap.beacon,
6954 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6955 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6956 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6957 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6958 ap_adapter->sessionCtx.ap.sapConfig.authType;
6959
6960 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6961 * to operate on the same bandwidth as that of the 2.4GHz operations.
6962 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6963 */
6964 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6965 case CH_WIDTH_20MHZ:
6966 channel_type = NL80211_CHAN_HT20;
6967 break;
6968 case CH_WIDTH_40MHZ:
6969 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6970 ap_adapter->sessionCtx.ap.sapConfig.channel)
6971 channel_type = NL80211_CHAN_HT40PLUS;
6972 else
6973 channel_type = NL80211_CHAN_HT40MINUS;
6974 break;
6975 default:
6976 channel_type = NL80211_CHAN_NO_HT;
6977 break;
6978 }
6979
6980 freq = cds_chan_to_freq(pre_cac_chan);
6981 chan = __ieee80211_get_channel(wiphy, freq);
6982 if (!chan) {
6983 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306984 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306985 }
6986
6987 cfg80211_chandef_create(&chandef, chan, channel_type);
6988
6989 hdd_debug("orig width:%d channel_type:%d freq:%d",
6990 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6991 channel_type, freq);
6992
6993 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6994 if (0 != ret) {
6995 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306996 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306997 }
6998
6999 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7000 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
7001 eHIDDEN_SSID_NOT_IN_USE, false);
7002 if (QDF_IS_STATUS_ERROR(status)) {
7003 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307004 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307005 }
7006
7007 /*
7008 * The pre cac status is set here. But, it would not be reset explicitly
7009 * anywhere, since after the pre cac success/failure, the pre cac
7010 * adapter itself would be removed.
7011 */
7012 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7013 if (0 != ret) {
7014 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307015 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307016 }
7017
7018 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7019 hdd_ap_ctx->operatingChannel);
7020 if (0 != ret) {
7021 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307022 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307023 }
7024
7025 ap_adapter->pre_cac_chan = pre_cac_chan;
7026
7027 return 0;
7028
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307029stop_close_pre_cac_adapter:
7030 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307031 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7032 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307033close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307034 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
7035 return -EINVAL;
7036}
7037
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307038/**
7039 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7040 *
7041 * Return: None
7042 */
7043void hdd_init_bpf_completion(void)
7044{
7045 init_completion(&bpf_context.completion);
7046}
7047
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307048static const struct nla_policy
7049wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7050 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7051};
7052
Agrawal Ashish65634612016-08-18 13:24:32 +05307053static const struct nla_policy
7054wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7055 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7056 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7057};
7058
7059/**
7060 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7061 * @wiphy: Pointer to wireless phy
7062 * @wdev: Pointer to wireless device
7063 * @data: Pointer to data
7064 * @data_len: Length of @data
7065 *
7066 * This function parses the incoming NL vendor command data attributes and
7067 * updates the SAP context about channel_hint and DFS mode.
7068 * If channel_hint is set, SAP will choose that channel
7069 * as operating channel.
7070 *
7071 * If DFS mode is enabled, driver will include DFS channels
7072 * in ACS else driver will skip DFS channels.
7073 *
7074 * Return: 0 on success, negative errno on failure
7075 */
7076static int
7077__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7078 struct wireless_dev *wdev,
7079 const void *data, int data_len)
7080{
7081 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7082 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7083 int ret;
7084 struct acs_dfs_policy *acs_policy;
7085 int mode = DFS_MODE_NONE;
7086 int channel_hint = 0;
7087
7088 ENTER_DEV(wdev->netdev);
7089
7090 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7091 hdd_err("Command not allowed in FTM mode");
7092 return -EINVAL;
7093 }
7094
7095 ret = wlan_hdd_validate_context(hdd_ctx);
7096 if (0 != ret)
7097 return ret;
7098
7099 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7100 data, data_len,
7101 wlan_hdd_set_acs_dfs_config_policy)) {
7102 hdd_err("invalid attr");
7103 return -EINVAL;
7104 }
7105
7106 acs_policy = &hdd_ctx->acs_policy;
7107 /*
7108 * SCM sends this attribute to restrict SAP from choosing
7109 * DFS channels from ACS.
7110 */
7111 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7112 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7113
7114 if (!IS_DFS_MODE_VALID(mode)) {
7115 hdd_err("attr acs dfs mode is not valid");
7116 return -EINVAL;
7117 }
7118 acs_policy->acs_dfs_mode = mode;
7119
7120 /*
7121 * SCM sends this attribute to provide an active channel,
7122 * to skip redundant ACS between drivers, and save driver start up time
7123 */
7124 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7125 channel_hint = nla_get_u8(
7126 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7127
7128 if (!IS_CHANNEL_VALID(channel_hint)) {
7129 hdd_err("acs channel is not valid");
7130 return -EINVAL;
7131 }
7132 acs_policy->acs_channel = channel_hint;
7133
7134 return 0;
7135}
7136
7137/**
7138 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7139 * @wiphy: wiphy structure pointer
7140 * @wdev: Wireless device structure pointer
7141 * @data: Pointer to the data received
7142 * @data_len: Length of @data
7143 *
7144 * This function parses the incoming NL vendor command data attributes and
7145 * updates the SAP context about channel_hint and DFS mode.
7146 *
7147 * Return: 0 on success; errno on failure
7148 */
7149static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7150 struct wireless_dev *wdev,
7151 const void *data, int data_len)
7152{
7153 int ret;
7154
7155 cds_ssr_protect(__func__);
7156 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7157 cds_ssr_unprotect(__func__);
7158
7159 return ret;
7160}
7161
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307162/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307163 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7164 * @mode : cfg80211 dfs mode
7165 *
7166 * Return: return csr sta roam dfs mode else return NONE
7167 */
7168static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7169 enum dfs_mode mode)
7170{
7171 switch (mode) {
7172 case DFS_MODE_ENABLE:
7173 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7174 break;
7175 case DFS_MODE_DISABLE:
7176 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7177 break;
7178 case DFS_MODE_DEPRIORITIZE:
7179 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7180 break;
7181 default:
7182 hdd_err("STA Roam policy dfs mode is NONE");
7183 return CSR_STA_ROAM_POLICY_NONE;
7184 }
7185}
7186
7187static const struct nla_policy
7188wlan_hdd_set_sta_roam_config_policy[
7189QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7190 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7191 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7192};
7193
7194/**
7195 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7196 * for station connection or roaming.
7197 * @wiphy: Pointer to wireless phy
7198 * @wdev: Pointer to wireless device
7199 * @data: Pointer to data
7200 * @data_len: Length of @data
7201 *
7202 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7203 * channels needs to be skipped in scanning or not.
7204 * If dfs_mode is disabled, driver will not scan DFS channels.
7205 * If skip_unsafe_channels is set, driver will skip unsafe channels
7206 * in Scanning.
7207 *
7208 * Return: 0 on success, negative errno on failure
7209 */
7210static int
7211__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7212 struct wireless_dev *wdev,
7213 const void *data, int data_len)
7214{
7215 struct net_device *dev = wdev->netdev;
7216 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7217 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7218 struct nlattr *tb[
7219 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7220 int ret;
7221 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7222 enum dfs_mode mode = DFS_MODE_NONE;
7223 bool skip_unsafe_channels = false;
7224 QDF_STATUS status;
7225
7226 ENTER_DEV(dev);
7227
7228 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7229 hdd_err("Command not allowed in FTM mode");
7230 return -EINVAL;
7231 }
7232
7233 ret = wlan_hdd_validate_context(hdd_ctx);
7234 if (0 != ret)
7235 return ret;
7236 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7237 data, data_len,
7238 wlan_hdd_set_sta_roam_config_policy)) {
7239 hdd_err("invalid attr");
7240 return -EINVAL;
7241 }
7242 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7243 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7244 if (!IS_DFS_MODE_VALID(mode)) {
7245 hdd_err("attr sta roam dfs mode policy is not valid");
7246 return -EINVAL;
7247 }
7248
7249 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7250
7251 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7252 skip_unsafe_channels = nla_get_u8(
7253 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7254
7255 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7256 skip_unsafe_channels, adapter->sessionId);
7257
7258 if (!QDF_IS_STATUS_SUCCESS(status)) {
7259 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7260 return -EINVAL;
7261 }
7262 return 0;
7263}
7264
7265/**
7266 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7267 * connection and roaming for station.
7268 * @wiphy: wiphy structure pointer
7269 * @wdev: Wireless device structure pointer
7270 * @data: Pointer to the data received
7271 * @data_len: Length of @data
7272 *
7273 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7274 * channels needs to be skipped in scanning or not.
7275 * If dfs_mode is disabled, driver will not scan DFS channels.
7276 * If skip_unsafe_channels is set, driver will skip unsafe channels
7277 * in Scanning.
7278 * Return: 0 on success; errno on failure
7279 */
7280static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7281 struct wireless_dev *wdev,
7282 const void *data, int data_len)
7283{
7284 int ret;
7285
7286 cds_ssr_protect(__func__);
7287 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7288 cds_ssr_unprotect(__func__);
7289
7290 return ret;
7291}
7292
Agrawal Ashish467dde42016-09-08 18:44:22 +05307293#ifdef FEATURE_WLAN_CH_AVOID
7294/**
7295 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7296 * is on unsafe channel.
7297 * @wiphy: wiphy structure pointer
7298 * @wdev: Wireless device structure pointer
7299 * @data: Pointer to the data received
7300 * @data_len: Length of @data
7301 *
7302 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7303 * on any of unsafe channels.
7304 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7305 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7306 *
7307 * Return: 0 on success; errno on failure
7308 */
7309static int
7310__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7311 struct wireless_dev *wdev,
7312 const void *data, int data_len)
7313{
7314 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7315 int ret;
7316 uint16_t unsafe_channel_count;
7317 int unsafe_channel_index;
7318 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7319
7320 ENTER_DEV(wdev->netdev);
7321
7322 if (!qdf_ctx) {
7323 cds_err("qdf_ctx is NULL");
7324 return -EINVAL;
7325 }
7326
7327 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7328 hdd_err("Command not allowed in FTM mode");
7329 return -EINVAL;
7330 }
7331
7332 ret = wlan_hdd_validate_context(hdd_ctx);
7333 if (0 != ret)
7334 return ret;
7335 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7336 &(hdd_ctx->unsafe_channel_count),
7337 sizeof(hdd_ctx->unsafe_channel_list));
7338
7339 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7340 (uint16_t)NUM_CHANNELS);
7341 for (unsafe_channel_index = 0;
7342 unsafe_channel_index < unsafe_channel_count;
7343 unsafe_channel_index++) {
7344 hdd_info("Channel %d is not safe",
7345 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7346 }
7347 hdd_unsafe_channel_restart_sap(hdd_ctx);
7348 return 0;
7349}
7350
7351/**
7352 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7353 * is on unsafe channel.
7354 * @wiphy: wiphy structure pointer
7355 * @wdev: Wireless device structure pointer
7356 * @data: Pointer to the data received
7357 * @data_len: Length of @data
7358 *
7359 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7360 * on any of unsafe channels.
7361 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7362 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7363 *
7364 * Return: 0 on success; errno on failure
7365 */
7366static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7367 struct wireless_dev *wdev,
7368 const void *data, int data_len)
7369{
7370 int ret;
7371
7372 cds_ssr_protect(__func__);
7373 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7374 cds_ssr_unprotect(__func__);
7375
7376 return ret;
7377}
7378
7379#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307380/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307381 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7382 * SAP is on unsafe channel.
7383 * @wiphy: wiphy structure pointer
7384 * @wdev: Wireless device structure pointer
7385 * @data: Pointer to the data received
7386 * @data_len: Length of @data
7387 *
7388 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7389 * driver.
7390 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7391 * will initiate restart of sap.
7392 *
7393 * Return: 0 on success; errno on failure
7394 */
7395static int
7396__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7397 struct wireless_dev *wdev,
7398 const void *data, int data_len)
7399{
7400 struct net_device *ndev = wdev->netdev;
7401 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7402 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7403 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7404 uint8_t config_channel = 0;
7405 hdd_ap_ctx_t *ap_ctx;
7406 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307407 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307408
7409 ENTER();
7410
7411 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007412 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307413 return -EINVAL;
7414 }
7415
7416 ret = wlan_hdd_validate_context(hdd_ctx);
7417 if (0 != ret)
7418 return -EINVAL;
7419
7420 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7421 data, data_len,
7422 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007423 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307424 return -EINVAL;
7425 }
7426
7427 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7428 if (!test_bit(SOFTAP_BSS_STARTED,
7429 &hostapd_adapter->event_flags)) {
7430 hdd_err("SAP is not started yet. Restart sap will be invalid");
7431 return -EINVAL;
7432 }
7433
7434 config_channel =
7435 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7436
7437 if (!((IS_24G_CH(config_channel)) ||
7438 (IS_5G_CH(config_channel)))) {
7439 hdd_err("Channel %d is not valid to restart SAP",
7440 config_channel);
7441 return -ENOTSUPP;
7442 }
7443
7444 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7445 ap_ctx->sapConfig.channel = config_channel;
7446 ap_ctx->sapConfig.ch_params.ch_width =
7447 ap_ctx->sapConfig.ch_width_orig;
7448
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007449 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307450 ap_ctx->sapConfig.sec_ch,
7451 &ap_ctx->sapConfig.ch_params);
7452
7453 cds_restart_sap(hostapd_adapter);
7454 }
7455
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307456 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7457 uint32_t freq_len, i;
7458 uint32_t *freq;
7459 uint8_t chans[QDF_MAX_NUM_CHAN];
7460
7461 hdd_debug("setting mandatory freq/chan list");
7462
7463 freq_len = nla_len(
7464 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7465 sizeof(uint32_t);
7466
7467 if (freq_len > QDF_MAX_NUM_CHAN) {
7468 hdd_err("insufficient space to hold channels");
7469 return -ENOMEM;
7470 }
7471
7472 freq = nla_data(
7473 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7474
7475 hdd_debug("freq_len=%d", freq_len);
7476
7477 for (i = 0; i < freq_len; i++) {
7478 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7479 hdd_debug("freq[%d]=%d", i, freq[i]);
7480 }
7481
7482 status = cds_set_sap_mandatory_channels(chans, freq_len);
7483 if (QDF_IS_STATUS_ERROR(status))
7484 return -EINVAL;
7485 }
7486
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307487 return 0;
7488}
7489
7490/**
7491 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7492 * @wiphy: wiphy structure pointer
7493 * @wdev: Wireless device structure pointer
7494 * @data: Pointer to the data received
7495 * @data_len: Length of @data
7496 *
7497 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7498 * driver.
7499 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7500 * will initiate restart of sap.
7501 *
7502 * Return: 0 on success; errno on failure
7503 */
7504static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7505 struct wireless_dev *wdev,
7506 const void *data, int data_len)
7507{
7508 int ret;
7509
7510 cds_ssr_protect(__func__);
7511 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7512 wdev, data, data_len);
7513 cds_ssr_unprotect(__func__);
7514
7515 return ret;
7516}
7517
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307518#undef BPF_INVALID
7519#undef BPF_SET_RESET
7520#undef BPF_VERSION
7521#undef BPF_ID
7522#undef BPF_PACKET_SIZE
7523#undef BPF_CURRENT_OFFSET
7524#undef BPF_PROGRAM
7525#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307526
7527/**
7528 * define short names for the global vendor params
7529 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7530 */
7531#define PARAM_TOTAL_CMD_EVENT_WAKE \
7532 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7533#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7534 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7535#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7536 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7537#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7538 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7539#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7540 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7541#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7542 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7543#define PARAM_TOTAL_RX_DATA_WAKE \
7544 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7545#define PARAM_RX_UNICAST_CNT \
7546 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7547#define PARAM_RX_MULTICAST_CNT \
7548 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7549#define PARAM_RX_BROADCAST_CNT \
7550 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7551#define PARAM_ICMP_PKT \
7552 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7553#define PARAM_ICMP6_PKT \
7554 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7555#define PARAM_ICMP6_RA \
7556 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7557#define PARAM_ICMP6_NA \
7558 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7559#define PARAM_ICMP6_NS \
7560 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7561#define PARAM_ICMP4_RX_MULTICAST_CNT \
7562 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7563#define PARAM_ICMP6_RX_MULTICAST_CNT \
7564 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7565#define PARAM_OTHER_RX_MULTICAST_CNT \
7566 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7567
7568
7569/**
7570 * hdd_send_wakelock_stats() - API to send wakelock stats
7571 * @ctx: context to be passed to callback
7572 * @data: data passed to callback
7573 *
7574 * This function is used to send wake lock stats to HAL layer
7575 *
7576 * Return: 0 on success, error number otherwise.
7577 */
7578static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7579 const struct sir_wake_lock_stats *data)
7580{
7581 struct sk_buff *skb;
7582 uint32_t nl_buf_len;
7583 uint32_t total_rx_data_wake, rx_multicast_cnt;
7584 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307585 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307586
7587 ENTER();
7588
7589 nl_buf_len = NLMSG_HDRLEN;
7590 nl_buf_len +=
7591 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7592 (NLMSG_HDRLEN + sizeof(uint32_t));
7593
7594 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7595
7596 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007597 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307598 return -ENOMEM;
7599 }
7600
Jeff Johnson64943bd2016-08-23 13:14:06 -07007601 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307602 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007603 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307604 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007605 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307606 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007607 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307608 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007609 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307610 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007611 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307612 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007613 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307614 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007615 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7616 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307617 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307618
7619 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307620 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307621
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307622 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307623 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307624
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307625 rx_multicast_cnt =
7626 data->wow_ipv4_mcast_wake_up_count +
7627 ipv6_rx_multicast_addr_cnt;
7628
7629 total_rx_data_wake =
7630 data->wow_ucast_wake_up_count +
7631 data->wow_bcast_wake_up_count +
7632 rx_multicast_cnt;
7633
7634 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7635 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7636 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7637 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7638 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7639 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7640 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7641 total_rx_data_wake) ||
7642 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7643 data->wow_ucast_wake_up_count) ||
7644 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7645 rx_multicast_cnt) ||
7646 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7647 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307648 nla_put_u32(skb, PARAM_ICMP_PKT,
7649 data->wow_icmpv4_count) ||
7650 nla_put_u32(skb, PARAM_ICMP6_PKT,
7651 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307652 nla_put_u32(skb, PARAM_ICMP6_RA,
7653 data->wow_ipv6_mcast_ra_stats) ||
7654 nla_put_u32(skb, PARAM_ICMP6_NA,
7655 data->wow_ipv6_mcast_na_stats) ||
7656 nla_put_u32(skb, PARAM_ICMP6_NS,
7657 data->wow_ipv6_mcast_ns_stats) ||
7658 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7659 data->wow_ipv4_mcast_wake_up_count) ||
7660 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7661 ipv6_rx_multicast_addr_cnt) ||
7662 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007663 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307664 goto nla_put_failure;
7665 }
7666
7667 cfg80211_vendor_cmd_reply(skb);
7668
7669 EXIT();
7670 return 0;
7671
7672nla_put_failure:
7673 kfree_skb(skb);
7674 return -EINVAL;
7675}
7676
7677/**
7678 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7679 * @wiphy: wiphy pointer
7680 * @wdev: pointer to struct wireless_dev
7681 * @data: pointer to incoming NL vendor data
7682 * @data_len: length of @data
7683 *
7684 * This function parses the incoming NL vendor command data attributes and
7685 * invokes the SME Api and blocks on a completion variable.
7686 * WMA copies required data and invokes callback
7687 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7688 *
7689 * Return: 0 on success; error number otherwise.
7690 */
7691static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7692 struct wireless_dev *wdev,
7693 const void *data,
7694 int data_len)
7695{
7696 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7697 int status, ret;
7698 struct sir_wake_lock_stats wake_lock_stats;
7699 QDF_STATUS qdf_status;
7700
7701 ENTER();
7702
7703 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007704 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307705 return -EINVAL;
7706 }
7707
7708 status = wlan_hdd_validate_context(hdd_ctx);
7709 if (0 != status)
7710 return -EINVAL;
7711
7712 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7713 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007714 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307715 return -EINVAL;
7716 }
7717
7718 ret = hdd_send_wakelock_stats(hdd_ctx,
7719 &wake_lock_stats);
7720 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007721 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307722
7723 EXIT();
7724 return ret;
7725}
7726
7727/**
7728 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7729 * @wiphy: wiphy pointer
7730 * @wdev: pointer to struct wireless_dev
7731 * @data: pointer to incoming NL vendor data
7732 * @data_len: length of @data
7733 *
7734 * This function parses the incoming NL vendor command data attributes and
7735 * invokes the SME Api and blocks on a completion variable.
7736 * WMA copies required data and invokes callback
7737 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7738 *
7739 * Return: 0 on success; error number otherwise.
7740 */
7741static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7742 struct wireless_dev *wdev,
7743 const void *data, int data_len)
7744{
7745 int ret;
7746
7747 cds_ssr_protect(__func__);
7748 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7749 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007750 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307751
7752 return ret;
7753}
7754
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307755/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307756 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7757 * @wiphy: wiphy structure pointer
7758 * @wdev: Wireless device structure pointer
7759 * @data: Pointer to the data received
7760 * @data_len: Length of @data
7761 *
7762 * This function reads wmi max bus size and fill in the skb with
7763 * NL attributes and send up the NL event.
7764 * Return: 0 on success; errno on failure
7765 */
7766static int
7767__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7768 struct wireless_dev *wdev,
7769 const void *data, int data_len)
7770{
7771 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7772 int ret_val;
7773 struct sk_buff *skb;
7774 uint32_t nl_buf_len;
7775
7776 ENTER();
7777
7778 ret_val = wlan_hdd_validate_context(hdd_ctx);
7779 if (ret_val)
7780 return ret_val;
7781
7782 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7783 hdd_err("Command not allowed in FTM mode");
7784 return -EINVAL;
7785 }
7786
7787 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7788
7789 nl_buf_len = NLMSG_HDRLEN;
7790 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7791
7792 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7793 if (!skb) {
7794 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7795 return -ENOMEM;
7796 }
7797
7798 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7799 hdd_ctx->wmi_max_len)) {
7800 hdd_err("nla put failure");
7801 goto nla_put_failure;
7802 }
7803
7804 cfg80211_vendor_cmd_reply(skb);
7805
7806 EXIT();
7807
7808 return 0;
7809
7810nla_put_failure:
7811 kfree_skb(skb);
7812 return -EINVAL;
7813}
7814
7815/**
7816 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7817 * @wiphy: wiphy structure pointer
7818 * @wdev: Wireless device structure pointer
7819 * @data: Pointer to the data received
7820 * @data_len: Length of @data
7821 *
7822 * Return: 0 on success; errno on failure
7823 */
7824static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7825 struct wireless_dev *wdev,
7826 const void *data, int data_len)
7827{
7828 int ret;
7829
7830 cds_ssr_protect(__func__);
7831 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7832 cds_ssr_unprotect(__func__);
7833
7834 return ret;
7835}
7836
7837/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307838 *__wlan_hdd_cfg80211_setband() - set band
7839 * @wiphy: Pointer to wireless phy
7840 * @wdev: Pointer to wireless device
7841 * @data: Pointer to data
7842 * @data_len: Length of @data
7843 *
7844 * Return: 0 on success, negative errno on failure
7845 */
7846static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7847 struct wireless_dev *wdev,
7848 const void *data, int data_len)
7849{
7850 struct net_device *dev = wdev->netdev;
7851 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7852 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7853 int ret;
7854 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7855 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7856
7857 ENTER();
7858
7859 ret = wlan_hdd_validate_context(hdd_ctx);
7860 if (ret)
7861 return ret;
7862
7863 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7864 hdd_err(FL("Invalid ATTR"));
7865 return -EINVAL;
7866 }
7867
7868 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7869 hdd_err(FL("attr SETBAND_VALUE failed"));
7870 return -EINVAL;
7871 }
7872
7873 ret = hdd_set_band(dev,
7874 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7875
7876 EXIT();
7877 return ret;
7878}
7879
7880/**
7881 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7882 * @wiphy: wiphy structure pointer
7883 * @wdev: Wireless device structure pointer
7884 * @data: Pointer to the data received
7885 * @data_len: Length of @data
7886 *
7887 * Return: 0 on success; errno on failure
7888 */
7889static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7890 struct wireless_dev *wdev,
7891 const void *data, int data_len)
7892{
7893 int ret;
7894
7895 cds_ssr_protect(__func__);
7896 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7897 cds_ssr_unprotect(__func__);
7898
7899 return ret;
7900}
7901
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307902static const struct
7903nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7904 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7905 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7906 .len = QDF_MAC_ADDR_SIZE},
7907};
7908
7909/**
7910 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7911 * @wiphy: Pointer to wireless phy
7912 * @wdev: Pointer to wireless device
7913 * @data: Pointer to data
7914 * @data_len: Length of @data
7915 *
7916 * This function is used to enable/disable roaming using vendor commands
7917 *
7918 * Return: 0 on success, negative errno on failure
7919 */
7920static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7921 struct wireless_dev *wdev,
7922 const void *data, int data_len)
7923{
7924 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7925 struct net_device *dev = wdev->netdev;
7926 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7927 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7928 uint32_t is_fast_roam_enabled;
7929 int ret;
7930
7931 ENTER_DEV(dev);
7932
7933 ret = wlan_hdd_validate_context(hdd_ctx);
7934 if (0 != ret)
7935 return ret;
7936
7937 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7938 hdd_err("Command not allowed in FTM mode");
7939 return -EINVAL;
7940 }
7941
7942 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7943 qca_wlan_vendor_attr);
7944 if (ret) {
7945 hdd_err("Invalid ATTR");
7946 return -EINVAL;
7947 }
7948
7949 /* Parse and fetch Enable flag */
7950 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7951 hdd_err("attr enable failed");
7952 return -EINVAL;
7953 }
7954
7955 is_fast_roam_enabled = nla_get_u32(
7956 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7957 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7958
7959 /* Update roaming */
7960 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7961 is_fast_roam_enabled);
7962 if (ret)
7963 hdd_err("sme_config_fast_roaming failed");
7964 EXIT();
7965 return ret;
7966}
7967
7968/**
7969 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7970 * @wiphy: Pointer to wireless phy
7971 * @wdev: Pointer to wireless device
7972 * @data: Pointer to data
7973 * @data_len: Length of @data
7974 *
7975 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7976 *
7977 * Return: 0 on success, negative errno on failure
7978 */
7979static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7980 struct wireless_dev *wdev,
7981 const void *data, int data_len)
7982{
7983 int ret;
7984
7985 cds_ssr_protect(__func__);
7986 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7987 cds_ssr_unprotect(__func__);
7988
7989 return ret;
7990}
7991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007992const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7993 {
7994 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7995 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307997 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007998 .doit = is_driver_dfs_capable
7999 },
8000
8001#ifdef WLAN_FEATURE_NAN
8002 {
8003 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8004 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8006 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8007 .doit = wlan_hdd_cfg80211_nan_request
8008 },
8009#endif
8010
8011#ifdef WLAN_FEATURE_STATS_EXT
8012 {
8013 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8014 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8015 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8016 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8017 .doit = wlan_hdd_cfg80211_stats_ext_request
8018 },
8019#endif
8020#ifdef FEATURE_WLAN_EXTSCAN
8021 {
8022 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8023 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8024 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8025 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8026 .doit = wlan_hdd_cfg80211_extscan_start
8027 },
8028 {
8029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8030 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8032 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8033 .doit = wlan_hdd_cfg80211_extscan_stop
8034 },
8035 {
8036 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8037 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8039 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8040 },
8041 {
8042 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8043 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8044 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8045 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8046 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8047 },
8048 {
8049 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8050 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8051 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8052 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8053 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8054 },
8055 {
8056 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8057 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8058 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8059 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8060 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8061 },
8062 {
8063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8064 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8066 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8067 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8068 },
8069 {
8070 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8071 .info.subcmd =
8072 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8073 .flags =
8074 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8075 WIPHY_VENDOR_CMD_NEED_RUNNING,
8076 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8077 },
8078 {
8079 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8080 .info.subcmd =
8081 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8082 .flags =
8083 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8084 WIPHY_VENDOR_CMD_NEED_RUNNING,
8085 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8086 },
8087 {
8088 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8089 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8090 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8091 WIPHY_VENDOR_CMD_NEED_NETDEV |
8092 WIPHY_VENDOR_CMD_NEED_RUNNING,
8093 .doit = wlan_hdd_cfg80211_set_epno_list
8094 },
8095#endif /* FEATURE_WLAN_EXTSCAN */
8096
8097#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8098 {
8099 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8100 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
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_clear
8104 },
8105
8106 {
8107 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8108 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8109 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8110 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8111 .doit = wlan_hdd_cfg80211_ll_stats_set
8112 },
8113
8114 {
8115 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8116 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8117 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8118 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8119 .doit = wlan_hdd_cfg80211_ll_stats_get
8120 },
8121#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8122#ifdef FEATURE_WLAN_TDLS
8123 {
8124 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8125 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8126 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8127 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8128 .doit = wlan_hdd_cfg80211_exttdls_enable
8129 },
8130 {
8131 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8132 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8133 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8134 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8135 .doit = wlan_hdd_cfg80211_exttdls_disable
8136 },
8137 {
8138 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8139 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8140 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8141 .doit = wlan_hdd_cfg80211_exttdls_get_status
8142 },
8143#endif
8144 {
8145 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8146 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8147 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8148 .doit = wlan_hdd_cfg80211_get_supported_features
8149 },
8150 {
8151 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8152 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8153 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8154 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8155 },
8156 {
8157 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8158 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8159 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308160 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008161 },
8162 {
8163 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8164 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8165 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8166 WIPHY_VENDOR_CMD_NEED_NETDEV,
8167 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8168 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008169 {
8170 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8171 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8172 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8173 WIPHY_VENDOR_CMD_NEED_NETDEV,
8174 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8175 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008176 {
8177 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308178 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8179 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8180 WIPHY_VENDOR_CMD_NEED_NETDEV |
8181 WIPHY_VENDOR_CMD_NEED_RUNNING,
8182 .doit = hdd_cfg80211_get_station_cmd
8183 },
8184 {
8185 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008186 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8187 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8188 WIPHY_VENDOR_CMD_NEED_NETDEV |
8189 WIPHY_VENDOR_CMD_NEED_RUNNING,
8190 .doit = wlan_hdd_cfg80211_do_acs
8191 },
8192
8193 {
8194 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8195 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8196 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8197 WIPHY_VENDOR_CMD_NEED_NETDEV,
8198 .doit = wlan_hdd_cfg80211_get_features
8199 },
8200#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8201 {
8202 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8203 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8204 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8205 WIPHY_VENDOR_CMD_NEED_NETDEV |
8206 WIPHY_VENDOR_CMD_NEED_RUNNING,
8207 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8208 },
8209#endif
8210#ifdef FEATURE_WLAN_EXTSCAN
8211 {
8212 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8213 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8214 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8215 WIPHY_VENDOR_CMD_NEED_NETDEV |
8216 WIPHY_VENDOR_CMD_NEED_RUNNING,
8217 .doit = wlan_hdd_cfg80211_set_passpoint_list
8218 },
8219 {
8220 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8221 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8222 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8223 WIPHY_VENDOR_CMD_NEED_NETDEV |
8224 WIPHY_VENDOR_CMD_NEED_RUNNING,
8225 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8226 },
8227 {
8228 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8229 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8230 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8231 WIPHY_VENDOR_CMD_NEED_NETDEV |
8232 WIPHY_VENDOR_CMD_NEED_RUNNING,
8233 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8234 },
8235 {
8236 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8237 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8238 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8239 WIPHY_VENDOR_CMD_NEED_NETDEV |
8240 WIPHY_VENDOR_CMD_NEED_RUNNING,
8241 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8242 },
8243#endif /* FEATURE_WLAN_EXTSCAN */
8244 {
8245 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8246 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8247 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8248 WIPHY_VENDOR_CMD_NEED_NETDEV,
8249 .doit = wlan_hdd_cfg80211_get_wifi_info
8250 },
8251 {
8252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8253 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8254 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8255 WIPHY_VENDOR_CMD_NEED_NETDEV |
8256 WIPHY_VENDOR_CMD_NEED_RUNNING,
8257 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8258 },
8259 {
8260 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8261 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8262 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8263 WIPHY_VENDOR_CMD_NEED_NETDEV,
8264 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8265 },
8266 {
8267 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8268 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8269 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8270 WIPHY_VENDOR_CMD_NEED_NETDEV,
8271 .doit = wlan_hdd_cfg80211_wifi_logger_start
8272 },
8273 {
8274 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8275 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8276 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8277 WIPHY_VENDOR_CMD_NEED_NETDEV,
8278 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8279 },
8280 {
8281 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8282 .info.subcmd =
8283 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8284 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8285 WIPHY_VENDOR_CMD_NEED_NETDEV |
8286 WIPHY_VENDOR_CMD_NEED_RUNNING,
8287 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8288 },
8289 {
8290 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8291 .info.subcmd =
8292 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8293 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8294 WIPHY_VENDOR_CMD_NEED_NETDEV |
8295 WIPHY_VENDOR_CMD_NEED_RUNNING,
8296 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8297 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008298#ifdef WLAN_FEATURE_TSF
8299 {
8300 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8301 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8302 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8303 WIPHY_VENDOR_CMD_NEED_NETDEV |
8304 WIPHY_VENDOR_CMD_NEED_RUNNING,
8305 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8306 },
8307#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008308#ifdef FEATURE_WLAN_TDLS
8309 {
8310 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8311 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8312 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8313 WIPHY_VENDOR_CMD_NEED_NETDEV |
8314 WIPHY_VENDOR_CMD_NEED_RUNNING,
8315 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8316 },
8317#endif
8318#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8319 {
8320 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8321 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8322 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8323 WIPHY_VENDOR_CMD_NEED_NETDEV |
8324 WIPHY_VENDOR_CMD_NEED_RUNNING,
8325 .doit = wlan_hdd_cfg80211_offloaded_packets
8326 },
8327#endif
8328 {
8329 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8330 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8331 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8332 WIPHY_VENDOR_CMD_NEED_NETDEV |
8333 WIPHY_VENDOR_CMD_NEED_RUNNING,
8334 .doit = wlan_hdd_cfg80211_monitor_rssi
8335 },
8336 {
8337 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308338 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8339 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8340 WIPHY_VENDOR_CMD_NEED_NETDEV |
8341 WIPHY_VENDOR_CMD_NEED_RUNNING,
8342 .doit = wlan_hdd_cfg80211_set_ns_offload
8343 },
8344 {
8345 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008346 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8347 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8348 WIPHY_VENDOR_CMD_NEED_NETDEV |
8349 WIPHY_VENDOR_CMD_NEED_RUNNING,
8350 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8351 },
8352#ifdef WLAN_FEATURE_MEMDUMP
8353 {
8354 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8355 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8356 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8357 WIPHY_VENDOR_CMD_NEED_NETDEV |
8358 WIPHY_VENDOR_CMD_NEED_RUNNING,
8359 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8360 },
8361#endif /* WLAN_FEATURE_MEMDUMP */
8362 {
8363 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8364 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8365 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8366 WIPHY_VENDOR_CMD_NEED_NETDEV |
8367 WIPHY_VENDOR_CMD_NEED_RUNNING,
8368 .doit = wlan_hdd_cfg80211_vendor_scan
8369 },
8370
8371 /* OCB commands */
8372 {
8373 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8374 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8375 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8376 WIPHY_VENDOR_CMD_NEED_NETDEV |
8377 WIPHY_VENDOR_CMD_NEED_RUNNING,
8378 .doit = wlan_hdd_cfg80211_ocb_set_config
8379 },
8380 {
8381 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8382 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8383 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8384 WIPHY_VENDOR_CMD_NEED_NETDEV |
8385 WIPHY_VENDOR_CMD_NEED_RUNNING,
8386 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8387 },
8388 {
8389 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8390 .info.subcmd =
8391 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
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_start_timing_advert
8396 },
8397 {
8398 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8399 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8400 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8401 WIPHY_VENDOR_CMD_NEED_NETDEV |
8402 WIPHY_VENDOR_CMD_NEED_RUNNING,
8403 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8404 },
8405 {
8406 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8407 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8408 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8409 WIPHY_VENDOR_CMD_NEED_NETDEV |
8410 WIPHY_VENDOR_CMD_NEED_RUNNING,
8411 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8412 },
8413 {
8414 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8415 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
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_get_stats
8420 },
8421 {
8422 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8423 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8425 WIPHY_VENDOR_CMD_NEED_NETDEV |
8426 WIPHY_VENDOR_CMD_NEED_RUNNING,
8427 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8428 },
8429 {
8430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8431 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8432 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8433 WIPHY_VENDOR_CMD_NEED_NETDEV |
8434 WIPHY_VENDOR_CMD_NEED_RUNNING,
8435 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8436 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308437 {
8438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8441 WIPHY_VENDOR_CMD_NEED_NETDEV |
8442 WIPHY_VENDOR_CMD_NEED_RUNNING,
8443 .doit = wlan_hdd_cfg80211_get_link_properties
8444 },
Peng Xu278d0122015-09-24 16:34:17 -07008445 {
Peng Xud2220962016-07-11 17:59:17 -07008446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008447 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8449 WIPHY_VENDOR_CMD_NEED_NETDEV |
8450 WIPHY_VENDOR_CMD_NEED_RUNNING,
8451 .doit = wlan_hdd_cfg80211_set_ota_test
8452 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008453#ifdef FEATURE_LFR_SUBNET_DETECTION
8454 {
8455 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8456 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8457 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8458 WIPHY_VENDOR_CMD_NEED_NETDEV |
8459 WIPHY_VENDOR_CMD_NEED_RUNNING,
8460 .doit = wlan_hdd_cfg80211_set_gateway_params
8461 },
8462#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008463 {
Peng Xud2220962016-07-11 17:59:17 -07008464 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008465 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8466 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8467 WIPHY_VENDOR_CMD_NEED_NETDEV |
8468 WIPHY_VENDOR_CMD_NEED_RUNNING,
8469 .doit = wlan_hdd_cfg80211_txpower_scale
8470 },
8471 {
8472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8473 .info.subcmd =
8474 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8475 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8476 WIPHY_VENDOR_CMD_NEED_NETDEV |
8477 WIPHY_VENDOR_CMD_NEED_RUNNING,
8478 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8479 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308480 {
8481 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8482 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8483 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8484 WIPHY_VENDOR_CMD_NEED_NETDEV |
8485 WIPHY_VENDOR_CMD_NEED_RUNNING,
8486 .doit = wlan_hdd_cfg80211_bpf_offload
8487 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308488 {
8489 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308490 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8491 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8492 WIPHY_VENDOR_CMD_NEED_NETDEV |
8493 WIPHY_VENDOR_CMD_NEED_RUNNING,
8494 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8495 },
8496 {
8497 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308498 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8499 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8500 WIPHY_VENDOR_CMD_NEED_NETDEV |
8501 WIPHY_VENDOR_CMD_NEED_RUNNING,
8502 .doit = wlan_hdd_cfg80211_sta_roam_policy
8503 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308504#ifdef FEATURE_WLAN_CH_AVOID
8505 {
8506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8507 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8508 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8509 WIPHY_VENDOR_CMD_NEED_NETDEV |
8510 WIPHY_VENDOR_CMD_NEED_RUNNING,
8511 .doit = wlan_hdd_cfg80211_avoid_freq
8512 },
8513#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308514 {
8515 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308516 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8517 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8518 WIPHY_VENDOR_CMD_NEED_NETDEV |
8519 WIPHY_VENDOR_CMD_NEED_RUNNING,
8520 .doit = wlan_hdd_cfg80211_sap_configuration_set
8521 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008522 {
Peng Xu4225c152016-07-14 21:18:14 -07008523 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008524 .info.subcmd =
8525 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8526 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8527 WIPHY_VENDOR_CMD_NEED_NETDEV |
8528 WIPHY_VENDOR_CMD_NEED_RUNNING,
8529 .doit = wlan_hdd_cfg80211_p2p_lo_start
8530 },
8531 {
8532 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8533 .info.subcmd =
8534 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8536 WIPHY_VENDOR_CMD_NEED_NETDEV |
8537 WIPHY_VENDOR_CMD_NEED_RUNNING,
8538 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8539 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308540 {
8541 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8542 .info.subcmd =
8543 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8544 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8545 WIPHY_VENDOR_CMD_NEED_NETDEV |
8546 WIPHY_VENDOR_CMD_NEED_RUNNING,
8547 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8548 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008549#ifdef WLAN_FEATURE_NAN_DATAPATH
8550 {
8551 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8552 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8553 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8554 WIPHY_VENDOR_CMD_NEED_NETDEV |
8555 WIPHY_VENDOR_CMD_NEED_RUNNING,
8556 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8557 },
8558#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308559 {
8560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8563 WIPHY_VENDOR_CMD_NEED_NETDEV |
8564 WIPHY_VENDOR_CMD_NEED_RUNNING,
8565 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8566 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308567 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308568 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8569 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8570 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8571 WIPHY_VENDOR_CMD_NEED_NETDEV |
8572 WIPHY_VENDOR_CMD_NEED_RUNNING,
8573 .doit = wlan_hdd_cfg80211_get_bus_size
8574 },
8575 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308576 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8577 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8578 WIPHY_VENDOR_CMD_NEED_NETDEV |
8579 WIPHY_VENDOR_CMD_NEED_RUNNING,
8580 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308581 },
8582 {
8583 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8584 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8585 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8586 WIPHY_VENDOR_CMD_NEED_NETDEV |
8587 WIPHY_VENDOR_CMD_NEED_RUNNING,
8588 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308589 },
8590#ifdef WLAN_FEATURE_DISA
8591 {
8592 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8593 .info.subcmd =
8594 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8595 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8596 WIPHY_VENDOR_CMD_NEED_NETDEV |
8597 WIPHY_VENDOR_CMD_NEED_RUNNING,
8598 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8599 },
8600#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008601};
8602
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008603/**
8604 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8605 * @priv_size: Size of the hdd context.
8606 *
8607 * Allocate wiphy context and hdd context.
8608 *
8609 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008610 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008611hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008612{
8613 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008614 hdd_context_t *hdd_ctx;
8615
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008616 ENTER();
8617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008618 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8619
8620 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008621 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008622 return NULL;
8623 }
8624
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008625 hdd_ctx = wiphy_priv(wiphy);
8626
8627 hdd_ctx->wiphy = wiphy;
8628
8629 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008630}
8631
8632/*
8633 * FUNCTION: wlan_hdd_cfg80211_update_band
8634 * This function is called from the supplicant through a
8635 * private ioctl to change the band value
8636 */
8637int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8638{
8639 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008640 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008641
8642 ENTER();
8643
Dustin Browna30892e2016-10-12 17:28:36 -07008644 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008645
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008646 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008647 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008648
8649 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8650 struct ieee80211_supported_band *band = wiphy->bands[i];
8651
8652 channelEnabledState =
8653 cds_get_channel_state(band->channels[j].
8654 hw_value);
8655
Dustin Browna30892e2016-10-12 17:28:36 -07008656 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008657 /* 5G only */
8658#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8659 /* Enable Social channels for P2P */
8660 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8661 (band->channels[j].center_freq)
8662 && CHANNEL_STATE_ENABLE ==
8663 channelEnabledState)
8664 band->channels[j].flags &=
8665 ~IEEE80211_CHAN_DISABLED;
8666 else
8667#endif
8668 band->channels[j].flags |=
8669 IEEE80211_CHAN_DISABLED;
8670 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008671 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008672 eCSR_BAND_24 == eBand) {
8673 /* 2G only */
8674 band->channels[j].flags |=
8675 IEEE80211_CHAN_DISABLED;
8676 continue;
8677 }
8678
Amar Singhal6842e8f2016-02-23 16:30:32 -08008679 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008680 band->channels[j].flags &=
8681 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008682 }
8683 }
8684 return 0;
8685}
8686
8687/*
8688 * FUNCTION: wlan_hdd_cfg80211_init
8689 * This function is called by hdd_wlan_startup()
8690 * during initialization.
8691 * This function is used to initialize and register wiphy structure.
8692 */
8693int wlan_hdd_cfg80211_init(struct device *dev,
8694 struct wiphy *wiphy, struct hdd_config *pCfg)
8695{
8696 int i, j;
8697 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8698
8699 ENTER();
8700
8701 /* Now bind the underlying wlan device with wiphy */
8702 set_wiphy_dev(wiphy, dev);
8703
8704 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8705
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8707 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008708 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008709#else
8710 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008711 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008712#endif
8713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008714 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8715 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8716 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8717#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8718 | WIPHY_FLAG_4ADDR_STATION
8719#endif
8720 | WIPHY_FLAG_OFFCHAN_TX;
8721
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008722#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8723 wiphy->wowlan = &wowlan_support_cfg80211_init;
8724#else
8725 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8726 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8727 wiphy->wowlan.pattern_min_len = 1;
8728 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8729#endif
8730
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008731 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008732#ifdef FEATURE_WLAN_ESE
8733 || pCfg->isEseIniFeatureEnabled
8734#endif
8735 ) {
8736 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8737 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008738#ifdef FEATURE_WLAN_TDLS
8739 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8740 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8741#endif
8742
8743 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8744
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008745#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8746 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8747#endif
8748
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008749#ifdef FEATURE_WLAN_SCAN_PNO
8750 if (pCfg->configPNOScanSupport) {
8751 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8752 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8753 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8754 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008755#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8756 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8757#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008758 }
8759#endif /*FEATURE_WLAN_SCAN_PNO */
8760
8761#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308762 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008763#endif
8764
8765 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8766 driver can still register regulatory callback and
8767 it will get regulatory settings in wiphy->band[], but
8768 driver need to determine what to do with both
8769 regulatory settings */
8770
8771 wiphy->reg_notifier = hdd_reg_notifier;
8772
8773#if defined QCA_WIFI_FTM
8774}
8775#endif
8776
8777 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8778
8779 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8780
8781 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8782
Arun Khandavallifae92942016-08-01 13:31:08 +05308783 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8784 | BIT(NL80211_IFTYPE_ADHOC)
8785 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8786 | BIT(NL80211_IFTYPE_P2P_GO)
8787 | BIT(NL80211_IFTYPE_AP)
8788 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008789
Arun Khandavallifae92942016-08-01 13:31:08 +05308790 if (pCfg->advertiseConcurrentOperation) {
8791 if (pCfg->enableMCC) {
8792 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008793
Arun Khandavallifae92942016-08-01 13:31:08 +05308794 for (i = 0;
8795 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8796 i++) {
8797 if (!pCfg->allowMCCGODiffBI)
8798 wlan_hdd_iface_combination[i].
8799 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008800 }
8801 }
8802 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308803 ARRAY_SIZE(wlan_hdd_iface_combination);
8804 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008805 }
8806
8807 /* Before registering we need to update the ht capabilitied based
8808 * on ini values*/
8809 if (!pCfg->ShortGI20MhzEnable) {
8810 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8811 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008812 }
8813
8814 if (!pCfg->ShortGI40MhzEnable) {
8815 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8816 }
8817
8818 if (!pCfg->nChannelBondingMode5GHz) {
8819 wlan_hdd_band_5_ghz.ht_cap.cap &=
8820 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8821 }
8822
Abhishek Singhf512bf32016-05-04 16:47:46 +05308823 /*
8824 * In case of static linked driver at the time of driver unload,
8825 * module exit doesn't happens. Module cleanup helps in cleaning
8826 * of static memory.
8827 * If driver load happens statically, at the time of driver unload,
8828 * wiphy flags don't get reset because of static memory.
8829 * It's better not to store channel in static memory.
8830 */
Dustin Browna30892e2016-10-12 17:28:36 -07008831 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8832 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308833 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008834 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308835 hdd_err("Not enough memory to allocate channels");
8836 return -ENOMEM;
8837 }
Dustin Browna30892e2016-10-12 17:28:36 -07008838 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308839 &hdd_channels_2_4_ghz[0],
8840 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308841 if ((hdd_is_5g_supported(pHddCtx)) &&
8842 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8843 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8844 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8845 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008846 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8847 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308848 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008849 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308850 hdd_err("Not enough memory to allocate channels");
8851 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008852 bands[NL80211_BAND_2GHZ]->channels);
8853 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308854 return -ENOMEM;
8855 }
Dustin Browna30892e2016-10-12 17:28:36 -07008856 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308857 &hdd_channels_5_ghz[0],
8858 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008859 }
8860
Dustin Browna30892e2016-10-12 17:28:36 -07008861 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008862
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008863 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008864 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008865
8866 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8867 struct ieee80211_supported_band *band = wiphy->bands[i];
8868
Dustin Browna30892e2016-10-12 17:28:36 -07008869 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008870 eCSR_BAND_5G == pCfg->nBandCapability) {
8871 /* 5G only */
8872#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8873 /* Enable social channels for P2P */
8874 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8875 (band->channels[j].center_freq))
8876 band->channels[j].flags &=
8877 ~IEEE80211_CHAN_DISABLED;
8878 else
8879#endif
8880 band->channels[j].flags |=
8881 IEEE80211_CHAN_DISABLED;
8882 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008883 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008884 eCSR_BAND_24 == pCfg->nBandCapability) {
8885 /* 2G only */
8886 band->channels[j].flags |=
8887 IEEE80211_CHAN_DISABLED;
8888 continue;
8889 }
8890 }
8891 }
8892 /*Initialise the supported cipher suite details */
8893 wiphy->cipher_suites = hdd_cipher_suites;
8894 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8895
8896 /*signal strength in mBm (100*dBm) */
8897 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8898 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8899
Anurag Chouhan6d760662016-02-20 16:05:43 +05308900 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008901 wiphy->n_vendor_commands =
8902 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8903 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8904
8905 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8906 wiphy->n_vendor_events =
8907 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8908 }
8909
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008910 if (pCfg->enableDFSMasterCap) {
8911 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8912 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008913
8914 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8915
8916#ifdef QCA_HT_2040_COEX
8917 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8918#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05308919 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308920 hdd_add_channel_switch_support(&wiphy->flags);
8921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008922 EXIT();
8923 return 0;
8924}
8925
Abhishek Singhf512bf32016-05-04 16:47:46 +05308926/**
8927 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8928 * @ wiphy: the wiphy to validate against
8929 *
8930 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308931 * memory allocated in wlan_hdd_cfg80211_init also
8932 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308933 *
8934 * Return: void
8935 */
8936void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8937{
8938 int i;
8939
Dustin Browna30892e2016-10-12 17:28:36 -07008940 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308941 if (NULL != wiphy->bands[i] &&
8942 (NULL != wiphy->bands[i]->channels)) {
8943 qdf_mem_free(wiphy->bands[i]->channels);
8944 wiphy->bands[i]->channels = NULL;
8945 }
8946 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308947 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308948}
8949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008950/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308951 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008952 * initialization. In wlan_hdd_cfg80211_init, only the
8953 * default values will be initialized. The final initialization
8954 * of all required members can be done here.
8955 */
8956void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8957{
8958 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8959}
8960
8961/* In this function we are registering wiphy. */
8962int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8963{
8964 ENTER();
8965 /* Register our wiphy dev with cfg80211 */
8966 if (0 > wiphy_register(wiphy)) {
8967 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008968 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008969 return -EIO;
8970 }
8971
8972 EXIT();
8973 return 0;
8974}
8975
8976/*
8977 HDD function to update wiphy capability based on target offload status.
8978
8979 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8980 capability even before downloading firmware to the target. In discrete
8981 case, host will get know certain offload capability (say sched_scan
8982 caps) only after downloading firmware to the target and target boots up.
8983 This function is used to override setting done in wlan_hdd_cfg80211_init()
8984 based on target capability.
8985 */
8986void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8987{
8988#ifdef FEATURE_WLAN_SCAN_PNO
8989 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8990 struct hdd_config *pCfg = pHddCtx->config;
8991
8992 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8993 * control comes here. Here just we need to clear it if firmware doesn't
8994 * have PNO support. */
8995 if (!pCfg->PnoOffload) {
8996 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8997 wiphy->max_sched_scan_ssids = 0;
8998 wiphy->max_match_sets = 0;
8999 wiphy->max_sched_scan_ie_len = 0;
9000 }
9001#endif
9002}
9003
9004/* This function registers for all frame which supplicant is interested in */
9005void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9006{
9007 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9008 /* Register for all P2P action, public action etc frames */
9009 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9010
9011 ENTER();
9012
Abhishek Singh7996eb72015-12-30 17:24:02 +05309013 /* Register frame indication call back */
9014 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9015
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309016 /* Register for p2p ack indication */
9017 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009019 /* Right now we are registering these frame when driver is getting
9020 initialized. Once we will move to 2.6.37 kernel, in which we have
9021 frame register ops, we will move this code as a part of that */
9022 /* GAS Initial Request */
9023 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9024 (uint8_t *) GAS_INITIAL_REQ,
9025 GAS_INITIAL_REQ_SIZE);
9026
9027 /* GAS Initial Response */
9028 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9029 (uint8_t *) GAS_INITIAL_RSP,
9030 GAS_INITIAL_RSP_SIZE);
9031
9032 /* GAS Comeback Request */
9033 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9034 (uint8_t *) GAS_COMEBACK_REQ,
9035 GAS_COMEBACK_REQ_SIZE);
9036
9037 /* GAS Comeback Response */
9038 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9039 (uint8_t *) GAS_COMEBACK_RSP,
9040 GAS_COMEBACK_RSP_SIZE);
9041
9042 /* P2P Public Action */
9043 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9044 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9045 P2P_PUBLIC_ACTION_FRAME_SIZE);
9046
9047 /* P2P Action */
9048 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9049 (uint8_t *) P2P_ACTION_FRAME,
9050 P2P_ACTION_FRAME_SIZE);
9051
9052 /* WNM BSS Transition Request frame */
9053 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9054 (uint8_t *) WNM_BSS_ACTION_FRAME,
9055 WNM_BSS_ACTION_FRAME_SIZE);
9056
9057 /* WNM-Notification */
9058 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9059 (uint8_t *) WNM_NOTIFICATION_FRAME,
9060 WNM_NOTIFICATION_FRAME_SIZE);
9061}
9062
9063void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9064{
9065 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9066 /* Register for all P2P action, public action etc frames */
9067 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9068
9069 ENTER();
9070
9071 /* Right now we are registering these frame when driver is getting
9072 initialized. Once we will move to 2.6.37 kernel, in which we have
9073 frame register ops, we will move this code as a part of that */
9074 /* GAS Initial Request */
9075
9076 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9077 (uint8_t *) GAS_INITIAL_REQ,
9078 GAS_INITIAL_REQ_SIZE);
9079
9080 /* GAS Initial Response */
9081 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9082 (uint8_t *) GAS_INITIAL_RSP,
9083 GAS_INITIAL_RSP_SIZE);
9084
9085 /* GAS Comeback Request */
9086 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9087 (uint8_t *) GAS_COMEBACK_REQ,
9088 GAS_COMEBACK_REQ_SIZE);
9089
9090 /* GAS Comeback Response */
9091 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9092 (uint8_t *) GAS_COMEBACK_RSP,
9093 GAS_COMEBACK_RSP_SIZE);
9094
9095 /* P2P Public Action */
9096 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9097 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9098 P2P_PUBLIC_ACTION_FRAME_SIZE);
9099
9100 /* P2P Action */
9101 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9102 (uint8_t *) P2P_ACTION_FRAME,
9103 P2P_ACTION_FRAME_SIZE);
9104
9105 /* WNM-Notification */
9106 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9107 (uint8_t *) WNM_NOTIFICATION_FRAME,
9108 WNM_NOTIFICATION_FRAME_SIZE);
9109}
9110
9111#ifdef FEATURE_WLAN_WAPI
9112void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9113 const uint8_t *mac_addr, const uint8_t *key,
9114 int key_Len)
9115{
9116 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9117 tCsrRoamSetKey setKey;
9118 bool isConnected = true;
9119 int status = 0;
9120 uint32_t roamId = 0xFF;
9121 uint8_t *pKeyPtr = NULL;
9122 int n = 0;
9123
Jeff Johnson46b40792016-06-29 14:03:14 -07009124 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009125 hdd_device_mode_to_string(pAdapter->device_mode),
9126 pAdapter->device_mode);
9127
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309128 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009129 setKey.keyId = key_index; /* Store Key ID */
9130 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9131 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9132 setKey.paeRole = 0; /* the PAE role */
9133 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309134 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009135 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309136 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009137 }
9138 setKey.keyLength = key_Len;
9139 pKeyPtr = setKey.Key;
9140 memcpy(pKeyPtr, key, key_Len);
9141
Jeff Johnson46b40792016-06-29 14:03:14 -07009142 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009143 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009144 hdd_notice("WAPI KEY Data[%d]:%02x ",
9145 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009146
9147 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9148 if (isConnected) {
9149 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9150 pAdapter->sessionId, &setKey, &roamId);
9151 }
9152 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009153 hdd_err("sme_roam_set_key returned ERROR status= %d",
9154 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009155 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9156 }
9157}
9158#endif /* FEATURE_WLAN_WAPI */
9159
9160uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9161 uint8_t eid)
9162{
9163 int left = length;
9164 uint8_t *ptr = (uint8_t *)ies_ptr;
9165 uint8_t elem_id, elem_len;
9166
9167 while (left >= 2) {
9168 elem_id = ptr[0];
9169 elem_len = ptr[1];
9170 left -= 2;
9171 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009172 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009173 eid, elem_len, left);
9174 return NULL;
9175 }
9176 if (elem_id == eid) {
9177 return ptr;
9178 }
9179
9180 left -= elem_len;
9181 ptr += (elem_len + 2);
9182 }
9183 return NULL;
9184}
9185
9186/*
9187 * FUNCTION: wlan_hdd_validate_operation_channel
9188 * called by wlan_hdd_cfg80211_start_bss() and
9189 * wlan_hdd_set_channel()
9190 * This function validates whether given channel is part of valid
9191 * channel list.
9192 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309193QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009194 int channel)
9195{
9196
9197 uint32_t num_ch = 0;
9198 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9199 u32 indx = 0;
9200 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9201 uint8_t fValidChannel = false, count = 0;
9202 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9203
9204 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9205
9206 if (hdd_pConfig_ini->sapAllowAllChannel) {
9207 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009208 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009209 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009210 fValidChannel = true;
9211 break;
9212 }
9213 }
9214 if (fValidChannel != true) {
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 } else {
9219 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9220 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009221 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309222 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009223 }
9224 for (indx = 0; indx < num_ch; indx++) {
9225 if (channel == valid_ch[indx]) {
9226 break;
9227 }
9228 }
9229
9230 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009231 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309232 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009233 }
9234 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309235 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009236
9237}
9238
9239#ifdef DHCP_SERVER_OFFLOAD
9240static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9241{
9242 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9243 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9244 uint8_t numEntries = 0;
9245 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9246 uint8_t num;
9247 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309248 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009249 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009250 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009251 return;
9252 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009253 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9254 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9255 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9256 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9257 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9258 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009259 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009260 goto end;
9261 }
9262 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009263 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009264 goto end;
9265 }
9266 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009267 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009268 goto end;
9269 }
9270 for (num = 0; num < numEntries; num++) {
9271 temp = srv_ip[num];
9272 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9273 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309274 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009275 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009276 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009277 goto end;
9278 }
Jeff Johnson77848112016-06-29 14:52:06 -07009279 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009280end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309281 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009282 return;
9283}
9284#endif /* DHCP_SERVER_OFFLOAD */
9285
9286static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9287 struct net_device *dev,
9288 struct bss_parameters *params)
9289{
9290 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9291 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9292 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309293 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009294
9295 ENTER();
9296
Anurag Chouhan6d760662016-02-20 16:05:43 +05309297 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009298 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 return -EINVAL;
9300 }
9301
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309302 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009303 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9304 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009305 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009306 hdd_device_mode_to_string(pAdapter->device_mode),
9307 pAdapter->device_mode, params->ap_isolate);
9308
9309 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9310 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309311 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009312 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009313
Krunal Sonib4326f22016-03-10 13:05:51 -08009314 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9315 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009316 return -EOPNOTSUPP;
9317 }
9318
9319 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9320 * want to update this parameter */
9321 if (-1 != params->ap_isolate) {
9322 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9323 !!params->ap_isolate;
9324
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309325 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009326 pAdapter->sessionId,
9327 pAdapter->sessionCtx.
9328 ap.
9329 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309330 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009331 ret = -EINVAL;
9332 }
9333 }
9334
9335 EXIT();
9336 return ret;
9337}
9338
Krunal Soni8c37e322016-02-03 16:08:37 -08009339/**
9340 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9341 * @ndev: pointer to net device provided by supplicant
9342 * @type: type of the interface, upper layer wanted to change
9343 *
9344 * Upper layer provides the new interface mode that needs to be changed
9345 * for given net device
9346 *
9347 * Return: success or failure in terms of integer value
9348 */
9349static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009350 enum nl80211_iftype type)
9351{
Krunal Soni8c37e322016-02-03 16:08:37 -08009352 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9353 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9354 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009355 hdd_wext_state_t *wext;
9356 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309357 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009358
9359 ENTER();
9360
Krunal Soni8c37e322016-02-03 16:08:37 -08009361 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009362 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009363 return 0;
9364 }
9365
9366 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009367 hdd_stop_adapter(hdd_ctx, adapter, true);
9368 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009369 wdev->iftype = type;
9370 /*Check for sub-string p2p to confirm its a p2p interface */
9371 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009372 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009373 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009374 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009375 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009376 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009378 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009379 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009380 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009381 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009382 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9383 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009384 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9385 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009386 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009387 adapter->scan_info.scanAddIE.length;
9388 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309389 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009390 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9391 wext->roamProfile.phyMode =
9392 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9393 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009394 EXIT();
9395 return status;
9396}
9397
9398static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9399 struct net_device *dev,
9400 struct bss_parameters *params)
9401{
9402 int ret;
9403
9404 cds_ssr_protect(__func__);
9405 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9406 cds_ssr_unprotect(__func__);
9407
9408 return ret;
9409}
9410
9411/* FUNCTION: wlan_hdd_change_country_code_cd
9412 * to wait for contry code completion
9413 */
9414void *wlan_hdd_change_country_code_cb(void *pAdapter)
9415{
9416 hdd_adapter_t *call_back_pAdapter = pAdapter;
9417 complete(&call_back_pAdapter->change_country_code);
9418 return NULL;
9419}
9420
Rajeev Kumar98edb772016-01-19 12:42:19 -08009421/**
9422 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9423 * @wiphy: Pointer to the wiphy structure
9424 * @ndev: Pointer to the net device
9425 * @type: Interface type
9426 * @flags: Flags for change interface
9427 * @params: Pointer to change interface parameters
9428 *
9429 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009430 */
9431static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9432 struct net_device *ndev,
9433 enum nl80211_iftype type,
9434 u32 *flags,
9435 struct vif_params *params)
9436{
9437 struct wireless_dev *wdev;
9438 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9439 hdd_context_t *pHddCtx;
9440 tCsrRoamProfile *pRoamProfile = NULL;
9441 eCsrRoamBssType LastBSSType;
9442 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309443 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009444 int status;
9445
9446 ENTER();
9447
Anurag Chouhan6d760662016-02-20 16:05:43 +05309448 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009449 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009450 return -EINVAL;
9451 }
9452
9453 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9454 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309455 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009456 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009457
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309458 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009459 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9460 pAdapter->sessionId, type));
9461
Jeff Johnson77848112016-06-29 14:52:06 -07009462 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009463 pAdapter->device_mode, type);
9464
Arun Khandavallifae92942016-08-01 13:31:08 +05309465 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9466 if (status) {
9467 hdd_err("Failed to start modules");
9468 return -EINVAL;
9469 }
9470
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009471 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009472 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9473 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009474 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009475 return -EINVAL;
9476 }
9477
9478 pConfig = pHddCtx->config;
9479 wdev = ndev->ieee80211_ptr;
9480
9481 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009482 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009483
9484 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9485
Krunal Sonib4326f22016-03-10 13:05:51 -08009486 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9487 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9488 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9489 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009490 hdd_wext_state_t *pWextState =
9491 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9492
9493 pRoamProfile = &pWextState->roamProfile;
9494 LastBSSType = pRoamProfile->BSSType;
9495
9496 switch (type) {
9497 case NL80211_IFTYPE_STATION:
9498 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009499 case NL80211_IFTYPE_ADHOC:
9500 if (type == NL80211_IFTYPE_ADHOC) {
9501 wlan_hdd_tdls_exit(pAdapter);
9502 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009503 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009504 }
9505 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9506 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309507 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009508 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309509 if (hdd_start_adapter(pAdapter)) {
9510 hdd_err("Failed to start adapter :%d",
9511 pAdapter->device_mode);
9512 return -EINVAL;
9513 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009514 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009515 case NL80211_IFTYPE_AP:
9516 case NL80211_IFTYPE_P2P_GO:
9517 {
Jeff Johnson77848112016-06-29 14:52:06 -07009518 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009519 (type ==
9520 NL80211_IFTYPE_AP) ? "SoftAP" :
9521 "P2pGo");
9522
9523 /* Cancel any remain on channel for GO mode */
9524 if (NL80211_IFTYPE_P2P_GO == type) {
9525 wlan_hdd_cancel_existing_remain_on_channel
9526 (pAdapter);
9527 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009528
Arun Khandavallifae92942016-08-01 13:31:08 +05309529 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009530 /* De-init the adapter */
9531 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9532 memset(&pAdapter->sessionCtx, 0,
9533 sizeof(pAdapter->sessionCtx));
9534 pAdapter->device_mode =
9535 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009536 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9537 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009538
9539 /*
9540 * Fw will take care incase of concurrency
9541 */
9542
Krunal Sonib4326f22016-03-10 13:05:51 -08009543 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009544 && (pConfig->apRandomBssidEnabled)) {
9545 /* To meet Android requirements create a randomized
9546 MAC address of the form 02:1A:11:Fx:xx:xx */
9547 get_random_bytes(&ndev->dev_addr[3], 3);
9548 ndev->dev_addr[0] = 0x02;
9549 ndev->dev_addr[1] = 0x1A;
9550 ndev->dev_addr[2] = 0x11;
9551 ndev->dev_addr[3] |= 0xF0;
9552 memcpy(pAdapter->macAddressCurrent.
9553 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309554 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009555 pr_info("wlan: Generated HotSpot BSSID "
9556 MAC_ADDRESS_STR "\n",
9557 MAC_ADDR_ARRAY(ndev->dev_addr));
9558 }
9559
9560 hdd_set_ap_ops(pAdapter->dev);
9561
Arun Khandavallifae92942016-08-01 13:31:08 +05309562 if (hdd_start_adapter(pAdapter)) {
9563 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009564 return -EINVAL;
9565 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009566 /* Interface type changed update in wiphy structure */
9567 if (wdev) {
9568 wdev->iftype = type;
9569 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009570 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009571 return -EINVAL;
9572 }
9573 goto done;
9574 }
9575
9576 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009577 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009578 type);
9579 return -EOPNOTSUPP;
9580 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009581 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9582 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009583 switch (type) {
9584 case NL80211_IFTYPE_STATION:
9585 case NL80211_IFTYPE_P2P_CLIENT:
9586 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009587 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9588 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309589 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009590 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309591 if (hdd_start_adapter(pAdapter)) {
9592 hdd_err("Failed to start adapter :%d",
9593 pAdapter->device_mode);
9594 return -EINVAL;
9595 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009596 goto done;
9597
9598 case NL80211_IFTYPE_AP:
9599 case NL80211_IFTYPE_P2P_GO:
9600 wdev->iftype = type;
9601 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009602 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603 goto done;
9604
9605 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009606 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009607 type);
9608 return -EOPNOTSUPP;
9609 }
9610 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009611 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009612 pAdapter->device_mode);
9613 return -EOPNOTSUPP;
9614 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009615done:
9616 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009617 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009618
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009619 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009620
9621 EXIT();
9622 return 0;
9623}
9624
Rajeev Kumar98edb772016-01-19 12:42:19 -08009625/**
9626 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9627 * @wiphy: Pointer to the wiphy structure
9628 * @ndev: Pointer to the net device
9629 * @type: Interface type
9630 * @flags: Flags for change interface
9631 * @params: Pointer to change interface parameters
9632 *
9633 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634 */
9635static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9636 struct net_device *ndev,
9637 enum nl80211_iftype type,
9638 u32 *flags,
9639 struct vif_params *params)
9640{
9641 int ret;
9642
9643 cds_ssr_protect(__func__);
9644 ret =
9645 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9646 cds_ssr_unprotect(__func__);
9647
9648 return ret;
9649}
9650
9651#ifdef FEATURE_WLAN_TDLS
9652static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9653 int index, uint8_t match)
9654{
9655 int i;
9656 for (i = 0; i < index; i++) {
9657 if (arr[i] == match)
9658 return true;
9659 }
9660 return false;
9661}
9662#endif
9663
9664/**
9665 * __wlan_hdd_change_station() - change station
9666 * @wiphy: Pointer to the wiphy structure
9667 * @dev: Pointer to the net device.
9668 * @mac: bssid
9669 * @params: Pointer to station parameters
9670 *
9671 * Return: 0 for success, error number on failure.
9672 */
9673#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9674static int __wlan_hdd_change_station(struct wiphy *wiphy,
9675 struct net_device *dev,
9676 const uint8_t *mac,
9677 struct station_parameters *params)
9678#else
9679static int __wlan_hdd_change_station(struct wiphy *wiphy,
9680 struct net_device *dev,
9681 uint8_t *mac,
9682 struct station_parameters *params)
9683#endif
9684{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309685 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9687 hdd_context_t *pHddCtx;
9688 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309689 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009690#ifdef FEATURE_WLAN_TDLS
9691 tCsrStaParams StaParams = { 0 };
9692 uint8_t isBufSta = 0;
9693 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309694 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695#endif
9696 int ret;
9697
9698 ENTER();
9699
Anurag Chouhan6d760662016-02-20 16:05:43 +05309700 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009701 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009702 return -EINVAL;
9703 }
9704
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309705 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009706 TRACE_CODE_HDD_CHANGE_STATION,
9707 pAdapter->sessionId, params->listen_interval));
9708
9709 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9710 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309711 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009712 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009713
9714 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9715
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309716 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717
Krunal Sonib4326f22016-03-10 13:05:51 -08009718 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9719 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009720 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9721 status =
9722 hdd_softap_change_sta_state(pAdapter,
9723 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009724 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309726 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009727 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009728 return -EINVAL;
9729 }
9730 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009731 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9732 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009733#ifdef FEATURE_WLAN_TDLS
9734 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009735
9736 if (cds_is_sub_20_mhz_enabled()) {
9737 hdd_err("TDLS not allowed with sub 20 MHz");
9738 return -EINVAL;
9739 }
9740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009741 StaParams.capability = params->capability;
9742 StaParams.uapsd_queues = params->uapsd_queues;
9743 StaParams.max_sp = params->max_sp;
9744
9745 /* Convert (first channel , number of channels) tuple to
9746 * the total list of channels. This goes with the assumption
9747 * that if the first channel is < 14, then the next channels
9748 * are an incremental of 1 else an incremental of 4 till the number
9749 * of channels.
9750 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009751 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009752 if (0 != params->supported_channels_len) {
9753 int i = 0, j = 0, k = 0, no_of_channels = 0;
9754 int num_unique_channels;
9755 int next;
9756 for (i = 0;
9757 i < params->supported_channels_len
9758 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9759 int wifi_chan_index;
9760 if (!wlan_hdd_is_duplicate_channel
9761 (StaParams.supported_channels, j,
9762 params->supported_channels[i])) {
9763 StaParams.
9764 supported_channels[j] =
9765 params->
9766 supported_channels[i];
9767 } else {
9768 continue;
9769 }
9770 wifi_chan_index =
9771 ((StaParams.supported_channels[j] <=
9772 HDD_CHANNEL_14) ? 1 : 4);
9773 no_of_channels =
9774 params->supported_channels[i + 1];
9775
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009776 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 -08009777 StaParams.
9778 supported_channels[j],
9779 wifi_chan_index,
9780 no_of_channels);
9781 for (k = 1; k <= no_of_channels &&
9782 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9783 k++) {
9784 next =
9785 StaParams.
9786 supported_channels[j] +
9787 wifi_chan_index;
9788 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9789 StaParams.
9790 supported_channels[j
9791 +
9792 1]
9793 = next;
9794 } else {
9795 continue;
9796 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009797 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009798 j + 1,
9799 StaParams.
9800 supported_channels[j +
9801 1]);
9802 j += 1;
9803 }
9804 }
9805 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009806 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009807 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009808 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009809 StaParams.
9810 supported_channels[i]);
9811 }
9812 if (MAX_CHANNEL < num_unique_channels)
9813 num_unique_channels = MAX_CHANNEL;
9814 StaParams.supported_channels_len =
9815 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009816 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009817 StaParams.supported_channels_len);
9818 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309819 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009820 params->supported_oper_classes,
9821 params->supported_oper_classes_len);
9822 StaParams.supported_oper_classes_len =
9823 params->supported_oper_classes_len;
9824
9825 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309826 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009827 params->ext_capab,
9828 sizeof(StaParams.extn_capability));
9829
9830 if (NULL != params->ht_capa) {
9831 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309832 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009833 sizeof(tSirHTCap));
9834 }
9835
9836 StaParams.supported_rates_len =
9837 params->supported_rates_len;
9838
9839 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9840 * The supported_rates array , for all the structures propogating till Add Sta
9841 * to the firmware has to be modified , if the supplicant (ieee80211) is
9842 * modified to send more rates.
9843 */
9844
9845 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9846 */
9847 if (StaParams.supported_rates_len >
9848 SIR_MAC_MAX_SUPP_RATES)
9849 StaParams.supported_rates_len =
9850 SIR_MAC_MAX_SUPP_RATES;
9851
9852 if (0 != StaParams.supported_rates_len) {
9853 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309854 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009855 params->supported_rates,
9856 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009857 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009858 StaParams.supported_rates_len);
9859 for (i = 0; i < StaParams.supported_rates_len;
9860 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009861 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009862 StaParams.supported_rates[i]);
9863 }
9864
9865 if (NULL != params->vht_capa) {
9866 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309867 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009868 params->vht_capa,
9869 sizeof(tSirVHTCap));
9870 }
9871
9872 if (0 != params->ext_capab_len) {
9873 /*Define A Macro : TODO Sunil */
9874 if ((1 << 4) & StaParams.extn_capability[3]) {
9875 isBufSta = 1;
9876 }
9877 /* TDLS Channel Switching Support */
9878 if ((1 << 6) & StaParams.extn_capability[3]) {
9879 isOffChannelSupported = 1;
9880 }
9881 }
9882
Nitesh Shah99934ac2016-09-05 15:54:08 +05309883 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309884 (params->ht_capa || params->vht_capa ||
9885 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309886 is_qos_wmm_sta = true;
9887
9888 hdd_notice("%s: TDLS Peer is QOS capable"
9889 " is_qos_wmm_sta= %d HTcapPresent = %d",
9890 __func__, is_qos_wmm_sta,
9891 StaParams.htcap_present);
9892
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009893 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309894 &StaParams,
9895 isBufSta,
9896 isOffChannelSupported,
9897 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309898 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009899 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009900 return -EINVAL;
9901 }
9902
9903 status =
9904 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9905 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309906 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009907 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009908 return -EINVAL;
9909 }
9910 }
9911#endif
9912 }
9913 EXIT();
9914 return ret;
9915}
9916
9917/**
9918 * wlan_hdd_change_station() - cfg80211 change station handler function
9919 * @wiphy: Pointer to the wiphy structure
9920 * @dev: Pointer to the net device.
9921 * @mac: bssid
9922 * @params: Pointer to station parameters
9923 *
9924 * This is the cfg80211 change station handler function which invokes
9925 * the internal function @__wlan_hdd_change_station with
9926 * SSR protection.
9927 *
9928 * Return: 0 for success, error number on failure.
9929 */
9930#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9931static int wlan_hdd_change_station(struct wiphy *wiphy,
9932 struct net_device *dev,
9933 const u8 *mac,
9934 struct station_parameters *params)
9935#else
9936static int wlan_hdd_change_station(struct wiphy *wiphy,
9937 struct net_device *dev,
9938 u8 *mac,
9939 struct station_parameters *params)
9940#endif
9941{
9942 int ret;
9943
9944 cds_ssr_protect(__func__);
9945 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9946 cds_ssr_unprotect(__func__);
9947
9948 return ret;
9949}
9950
9951/*
9952 * FUNCTION: __wlan_hdd_cfg80211_add_key
9953 * This function is used to initialize the key information
9954 */
9955static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9956 struct net_device *ndev,
9957 u8 key_index, bool pairwise,
9958 const u8 *mac_addr,
9959 struct key_params *params)
9960{
9961 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9962 tCsrRoamSetKey setKey;
9963 int status;
9964 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009965 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309966 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009967 hdd_context_t *pHddCtx;
9968 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9969
9970 ENTER();
9971
Anurag Chouhan6d760662016-02-20 16:05:43 +05309972 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009973 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009974 return -EINVAL;
9975 }
9976
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309977 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009978 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9979 pAdapter->sessionId, params->key_len));
9980 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9981 status = wlan_hdd_validate_context(pHddCtx);
9982
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309983 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009984 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009985
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009986 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009987 hdd_device_mode_to_string(pAdapter->device_mode),
9988 pAdapter->device_mode);
9989
9990 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009991 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992
9993 return -EINVAL;
9994 }
9995
9996 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009997 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009998
9999 return -EINVAL;
10000 }
10001
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010002 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010003
10004 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010005 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010006 setKey.keyId = key_index;
10007 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010008 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010009
10010 switch (params->cipher) {
10011 case WLAN_CIPHER_SUITE_WEP40:
10012 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10013 break;
10014
10015 case WLAN_CIPHER_SUITE_WEP104:
10016 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10017 break;
10018
10019 case WLAN_CIPHER_SUITE_TKIP:
10020 {
10021 u8 *pKey = &setKey.Key[0];
10022 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10023
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010024 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010025
10026 /*Supplicant sends the 32bytes key in this order
10027
10028 |--------------|----------|----------|
10029 | Tk1 |TX-MIC | RX Mic |
10030 |||--------------|----------|----------|
10031 <---16bytes---><--8bytes--><--8bytes-->
10032
10033 */
10034 /*Sme expects the 32 bytes key to be in the below order
10035
10036 |--------------|----------|----------|
10037 | Tk1 |RX-MIC | TX Mic |
10038 |||--------------|----------|----------|
10039 <---16bytes---><--8bytes--><--8bytes-->
10040 */
10041 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010042 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010043
10044 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010045 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010046
10047 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010048 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010049
10050 break;
10051 }
10052
10053 case WLAN_CIPHER_SUITE_CCMP:
10054 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10055 break;
10056
10057#ifdef FEATURE_WLAN_WAPI
10058 case WLAN_CIPHER_SUITE_SMS4:
10059 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010060 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10062 mac_addr, params->key,
10063 params->key_len);
10064 return 0;
10065 }
10066#endif
10067
10068#ifdef FEATURE_WLAN_ESE
10069 case WLAN_CIPHER_SUITE_KRK:
10070 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10071 break;
10072#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10073 case WLAN_CIPHER_SUITE_BTK:
10074 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10075 break;
10076#endif
10077#endif
10078
10079#ifdef WLAN_FEATURE_11W
10080 case WLAN_CIPHER_SUITE_AES_CMAC:
10081 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10082 break;
10083#endif
10084
10085 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010086 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010087 return -EOPNOTSUPP;
10088 }
10089
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010090 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010091
10092 if (!pairwise) {
10093 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010094 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010095 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010096 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010097 } else {
10098 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010099 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010100 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010101 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010103 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010104 /* if a key is already installed, block all subsequent ones */
10105 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010106 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010107 return 0;
10108 }
10109
10110 setKey.keyDirection = eSIR_TX_RX;
10111 /*Set the group key */
10112 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10113 pAdapter->sessionId, &setKey, &roamId);
10114
10115 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010116 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 return -EINVAL;
10118 }
10119 /*Save the keys here and call sme_roam_set_key for setting
10120 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010121 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010122 &setKey, sizeof(tCsrRoamSetKey));
10123
10124 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10125 return status;
10126 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010127 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10128 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10130 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010131 status = wlansap_set_key_sta(
10132 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010133 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010134 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 __LINE__, status);
10136 }
10137 }
10138
10139 /* Save the key in ap ctx for use on START_BASS and restart */
10140 if (pairwise ||
10141 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10142 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010143 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010144 sizeof(tCsrRoamSetKey));
10145 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010146 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147 sizeof(tCsrRoamSetKey));
10148
Krunal Sonib4326f22016-03-10 13:05:51 -080010149 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10150 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010151 hdd_wext_state_t *pWextState =
10152 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10153 hdd_station_ctx_t *pHddStaCtx =
10154 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10155
10156 if (!pairwise) {
10157 /* set group key */
10158 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010159 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010160 __func__, __LINE__);
10161 hdd_perform_roam_set_key_complete(pAdapter);
10162 }
10163 }
10164
10165 pWextState->roamProfile.Keys.KeyLength[key_index] =
10166 (u8) params->key_len;
10167
10168 pWextState->roamProfile.Keys.defaultIndex = key_index;
10169
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010170 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171 KeyMaterial[key_index][0], params->key,
10172 params->key_len);
10173
10174 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10175
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010176 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010177 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10178 setKey.keyDirection);
10179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010180 /* The supplicant may attempt to set the PTK once pre-authentication
10181 is done. Save the key in the UMAC and include it in the ADD BSS
10182 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010183 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010184 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010185 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010186 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010188 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010189 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010190 return -EINVAL;
10191 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010192
10193 /* issue set key request to SME */
10194 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10195 pAdapter->sessionId, &setKey, &roamId);
10196
10197 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010198 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199 pHddStaCtx->roam_info.roamingState =
10200 HDD_ROAM_STATE_NONE;
10201 return -EINVAL;
10202 }
10203
10204 /* in case of IBSS as there was no information available about WEP keys during
10205 * IBSS join, group key intialized with NULL key, so re-initialize group key
10206 * with correct value*/
10207 if ((eCSR_BSS_TYPE_START_IBSS ==
10208 pWextState->roamProfile.BSSType)
10209 &&
10210 !((IW_AUTH_KEY_MGMT_802_1X ==
10211 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10212 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10213 pHddStaCtx->conn_info.authType)
10214 )
10215 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10216 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10217 )
10218 ) {
10219 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010220 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010222 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10224 setKey.keyDirection);
10225
10226 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10227 pAdapter->sessionId, &setKey,
10228 &roamId);
10229
10230 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010231 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010232 pHddStaCtx->roam_info.roamingState =
10233 HDD_ROAM_STATE_NONE;
10234 return -EINVAL;
10235 }
10236 }
10237 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010238 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010239 return 0;
10240}
10241
10242static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10243 struct net_device *ndev,
10244 u8 key_index, bool pairwise,
10245 const u8 *mac_addr,
10246 struct key_params *params)
10247{
10248 int ret;
10249 cds_ssr_protect(__func__);
10250 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10251 mac_addr, params);
10252 cds_ssr_unprotect(__func__);
10253
10254 return ret;
10255}
10256
10257/*
10258 * FUNCTION: __wlan_hdd_cfg80211_get_key
10259 * This function is used to get the key information
10260 */
10261static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10262 struct net_device *ndev,
10263 u8 key_index, bool pairwise,
10264 const u8 *mac_addr, void *cookie,
10265 void (*callback)(void *cookie,
10266 struct key_params *)
10267 )
10268{
10269 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10270 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10271 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10272 struct key_params params;
10273
10274 ENTER();
10275
Anurag Chouhan6d760662016-02-20 16:05:43 +053010276 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010277 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010278 return -EINVAL;
10279 }
10280
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010281 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010282 hdd_device_mode_to_string(pAdapter->device_mode),
10283 pAdapter->device_mode);
10284
10285 memset(&params, 0, sizeof(params));
10286
10287 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010288 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010289 key_index);
10290 return -EINVAL;
10291 }
10292
10293 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10294 case eCSR_ENCRYPT_TYPE_NONE:
10295 params.cipher = IW_AUTH_CIPHER_NONE;
10296 break;
10297
10298 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10299 case eCSR_ENCRYPT_TYPE_WEP40:
10300 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10301 break;
10302
10303 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10304 case eCSR_ENCRYPT_TYPE_WEP104:
10305 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10306 break;
10307
10308 case eCSR_ENCRYPT_TYPE_TKIP:
10309 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10310 break;
10311
10312 case eCSR_ENCRYPT_TYPE_AES:
10313 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10314 break;
10315
10316 default:
10317 params.cipher = IW_AUTH_CIPHER_NONE;
10318 break;
10319 }
10320
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010321 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010322 TRACE_CODE_HDD_CFG80211_GET_KEY,
10323 pAdapter->sessionId, params.cipher));
10324
10325 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10326 params.seq_len = 0;
10327 params.seq = NULL;
10328 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10329 callback(cookie, &params);
10330
10331 EXIT();
10332 return 0;
10333}
10334
10335static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10336 struct net_device *ndev,
10337 u8 key_index, bool pairwise,
10338 const u8 *mac_addr, void *cookie,
10339 void (*callback)(void *cookie,
10340 struct key_params *)
10341 )
10342{
10343 int ret;
10344
10345 cds_ssr_protect(__func__);
10346 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10347 mac_addr, cookie, callback);
10348 cds_ssr_unprotect(__func__);
10349
10350 return ret;
10351}
10352
10353/**
10354 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10355 * @wiphy: wiphy interface context
10356 * @ndev: pointer to net device
10357 * @key_index: Key index used in 802.11 frames
10358 * @unicast: true if it is unicast key
10359 * @multicast: true if it is multicast key
10360 *
10361 * This function is required for cfg80211_ops API.
10362 * It is used to delete the key information
10363 * Underlying hardware implementation does not have API to delete the
10364 * encryption key. It is automatically deleted when the peer is
10365 * removed. Hence this function currently does nothing.
10366 * Future implementation may interprete delete key operation to
10367 * replacing the key with a random junk value, effectively making it
10368 * useless.
10369 *
10370 * Return: status code, always 0.
10371 */
10372
10373static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10374 struct net_device *ndev,
10375 u8 key_index,
10376 bool pairwise, const u8 *mac_addr)
10377{
10378 EXIT();
10379 return 0;
10380}
10381
10382/**
10383 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10384 * @wiphy: Pointer to wiphy structure.
10385 * @dev: Pointer to net_device structure.
10386 * @key_index: key index
10387 * @pairwise: pairwise
10388 * @mac_addr: mac address
10389 *
10390 * This is the cfg80211 delete key handler function which invokes
10391 * the internal function @__wlan_hdd_cfg80211_del_key with
10392 * SSR protection.
10393 *
10394 * Return: 0 for success, error number on failure.
10395 */
10396static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10397 struct net_device *dev,
10398 u8 key_index,
10399 bool pairwise, const u8 *mac_addr)
10400{
10401 int ret;
10402
10403 cds_ssr_protect(__func__);
10404 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10405 pairwise, mac_addr);
10406 cds_ssr_unprotect(__func__);
10407
10408 return ret;
10409}
10410
10411/*
10412 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10413 * This function is used to set the default tx key index
10414 */
10415static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10416 struct net_device *ndev,
10417 u8 key_index,
10418 bool unicast, bool multicast)
10419{
10420 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10421 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10422 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10423 hdd_context_t *pHddCtx;
10424 int status;
10425
10426 ENTER();
10427
Anurag Chouhan6d760662016-02-20 16:05:43 +053010428 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010429 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010430 return -EINVAL;
10431 }
10432
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010433 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010434 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10435 pAdapter->sessionId, key_index));
10436
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010437 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010438 hdd_device_mode_to_string(pAdapter->device_mode),
10439 pAdapter->device_mode, key_index);
10440
10441 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010442 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010443 return -EINVAL;
10444 }
10445
10446 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10447 status = wlan_hdd_validate_context(pHddCtx);
10448
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010449 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010450 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010451
Krunal Sonib4326f22016-03-10 13:05:51 -080010452 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10453 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010454 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10455 pHddStaCtx->conn_info.ucEncryptionType) &&
10456 (eCSR_ENCRYPT_TYPE_AES !=
10457 pHddStaCtx->conn_info.ucEncryptionType)) {
10458 /* If default key index is not same as previous one,
10459 * then update the default key index */
10460
10461 tCsrRoamSetKey setKey;
10462 uint32_t roamId = 0xFF;
10463 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10464
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010465 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010466
10467 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010468 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010469 setKey.keyId = key_index;
10470 setKey.keyLength = Keys->KeyLength[key_index];
10471
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010472 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010473 &Keys->KeyMaterial[key_index][0],
10474 Keys->KeyLength[key_index]);
10475
10476 setKey.keyDirection = eSIR_TX_RX;
10477
Anurag Chouhanc5548422016-02-24 18:33:27 +053010478 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010479 &pHddStaCtx->conn_info.bssId);
10480
10481 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10482 pWextState->roamProfile.EncryptionType.
10483 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10484 /* In the case of dynamic wep supplicant hardcodes DWEP type
10485 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10486 * WEP-40 encryption. In this canse the key length is 5 but the
10487 * encryption type is 104 hence checking the key langht(5) and
10488 * encryption type(104) and switching encryption type to 40*/
10489 pWextState->roamProfile.EncryptionType.
10490 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10491 pWextState->roamProfile.mcEncryptionType.
10492 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10493 }
10494
10495 setKey.encType =
10496 pWextState->roamProfile.EncryptionType.
10497 encryptionType[0];
10498
10499 /* Issue set key request */
10500 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10501 pAdapter->sessionId, &setKey,
10502 &roamId);
10503
10504 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010505 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010506 status);
10507 return -EINVAL;
10508 }
10509 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010510 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511 /* In SoftAp mode setting key direction for default mode */
10512 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10513 pWextState->roamProfile.EncryptionType.encryptionType[0])
10514 && (eCSR_ENCRYPT_TYPE_AES !=
10515 pWextState->roamProfile.EncryptionType.
10516 encryptionType[0])) {
10517 /* Saving key direction for default key index to TX default */
10518 hdd_ap_ctx_t *pAPCtx =
10519 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10520 pAPCtx->wepKey[key_index].keyDirection =
10521 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010522 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010523 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010524 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010525 }
10526 }
10527
10528 EXIT();
10529 return status;
10530}
10531
10532static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10533 struct net_device *ndev,
10534 u8 key_index,
10535 bool unicast, bool multicast)
10536{
10537 int ret;
10538 cds_ssr_protect(__func__);
10539 ret =
10540 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10541 multicast);
10542 cds_ssr_unprotect(__func__);
10543
10544 return ret;
10545}
10546
Abhishek Singhc9941602016-08-09 16:06:22 +053010547/*
10548 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10549 * @wiphy: wiphy pointer
10550 * @channel: channel of the BSS
10551 * @bssid: Bssid of BSS
10552 * @ssid: Ssid of the BSS
10553 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010554 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010555 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010557#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010558static
Abhishek Singhc9941602016-08-09 16:06:22 +053010559struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10560 struct ieee80211_channel *channel, const u8 *bssid,
10561 const u8 *ssid, size_t ssid_len)
10562{
10563 return cfg80211_get_bss(wiphy, channel, bssid,
10564 ssid,
10565 ssid_len,
10566 WLAN_CAPABILITY_ESS,
10567 WLAN_CAPABILITY_ESS);
10568}
10569#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010570static
Abhishek Singhc9941602016-08-09 16:06:22 +053010571struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10572 struct ieee80211_channel *channel, const u8 *bssid,
10573 const u8 *ssid, size_t ssid_len)
10574{
10575 return cfg80211_get_bss(wiphy, channel, bssid,
10576 ssid,
10577 ssid_len,
10578 IEEE80211_BSS_TYPE_ESS,
10579 IEEE80211_PRIVACY_ANY);
10580}
10581#endif
10582
10583
10584/*
10585 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10586 * interface that BSS might have been lost.
10587 * @pAdapter: adaptor
10588 * @bssid: bssid which might have been lost
10589 *
10590 * Return: bss which is unlinked from kernel cache
10591 */
10592struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10593 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010594{
10595 struct net_device *dev = pAdapter->dev;
10596 struct wireless_dev *wdev = dev->ieee80211_ptr;
10597 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010598 struct cfg80211_bss *bss = NULL;
10599
Abhishek Singhc9941602016-08-09 16:06:22 +053010600 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10601 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010602 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010603 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010604 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010605 hdd_info("cfg80211_unlink_bss called for BSSID "
10606 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010607 cfg80211_unlink_bss(wiphy, bss);
10608 }
10609 return bss;
10610}
10611
Abhishek Singhc9941602016-08-09 16:06:22 +053010612
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010613/**
10614 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10615 * @pAdapter: Pointer to adapter
10616 * @bss_desc: Pointer to bss descriptor
10617 *
10618 * This function is used to inform the BSS details to nl80211 interface.
10619 *
10620 * Return: struct cfg80211_bss pointer
10621 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010622struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10623 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010624{
10625 /*
10626 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10627 * already exists in bss data base of cfg80211 for that particular BSS
10628 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10629 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10630 * As of now there is no possibility to get the mgmt(probe response)
10631 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10632 * and passing to cfg80211_inform_bss_frame.
10633 */
10634 struct net_device *dev = pAdapter->dev;
10635 struct wireless_dev *wdev = dev->ieee80211_ptr;
10636 struct wiphy *wiphy = wdev->wiphy;
10637 int chan_no = bss_desc->channelId;
10638#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10639 qcom_ie_age *qie_age = NULL;
10640 int ie_length =
10641 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10642#else
10643 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10644#endif
10645 const char *ie =
10646 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10647 unsigned int freq;
10648 struct ieee80211_channel *chan;
10649 struct ieee80211_mgmt *mgmt = NULL;
10650 struct cfg80211_bss *bss_status = NULL;
10651 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10652 int rssi = 0;
10653 hdd_context_t *pHddCtx;
10654 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010655 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010656 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010657
10658 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10659 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010660 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010662
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010663 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10665 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010666 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010667 return NULL;
10668 }
10669
10670 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10671
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010672 /* Android does not want the timestamp from the frame.
10673 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010674 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010675 mgmt->u.probe_resp.timestamp =
10676 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010677
10678 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10679 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10680
10681#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10682 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10683 /* Assuming this is the last IE, copy at the end */
10684 ie_length -= sizeof(qcom_ie_age);
10685 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10686 qie_age->element_id = QCOM_VENDOR_IE_ID;
10687 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10688 qie_age->oui_1 = QCOM_OUI1;
10689 qie_age->oui_2 = QCOM_OUI2;
10690 qie_age->oui_3 = QCOM_OUI3;
10691 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10692 qie_age->age =
Jeff Johnsonfeb22892016-10-27 14:12:38 -070010693 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010695 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10696 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010697 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10698 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699#endif
10700
10701 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10702 if (bss_desc->fProbeRsp) {
10703 mgmt->frame_control |=
10704 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10705 } else {
10706 mgmt->frame_control |=
10707 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10708 }
10709
10710 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010711 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010712 freq =
10713 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010714 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010715 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010716 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010717 freq =
10718 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010719 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010720 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010721 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010722 kfree(mgmt);
10723 return NULL;
10724 }
10725
10726 chan = __ieee80211_get_channel(wiphy, freq);
10727 /* When the band is changed on the fly using the GUI, three things are done
10728 * 1. scan abort
10729 * 2. flush scan results from cache
10730 * 3. update the band with the new band user specified (refer to the
10731 * hdd_set_band_helper function) as part of the scan abort, message will be
10732 * queued to PE and we proceed with flushing and changinh the band.
10733 * PE will stop the scanning further and report back the results what ever
10734 * it had till now by calling the call back function.
10735 * if the time between update band and scandone call back is sufficient
10736 * enough the band change reflects in SME, SME validates the channels
10737 * and discards the channels correponding to previous band and calls back
10738 * with zero bss results. but if the time between band update and scan done
10739 * callback is very small then band change will not reflect in SME and SME
10740 * reports to HDD all the channels correponding to previous band.this is due
10741 * to race condition.but those channels are invalid to the new band and so
10742 * this function __ieee80211_get_channel will return NULL.Each time we
10743 * report scan result with this pointer null warning kernel trace is printed.
10744 * if the scan results contain large number of APs continuosly kernel
10745 * warning trace is printed and it will lead to apps watch dog bark.
10746 * So drop the bss and continue to next bss.
10747 */
10748 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010749 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10750 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751 kfree(mgmt);
10752 return NULL;
10753 }
10754
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010755 /* Based on .ini configuration, raw rssi can be reported for bss.
10756 * Raw rssi is typically used for estimating power.
10757 */
10758
10759 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10760 bss_desc->rssi;
10761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010762 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010763 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010764
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010765 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010766 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010767 (int)(rssi / 100),
10768 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010769
10770 bss_status =
10771 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10772 GFP_KERNEL);
10773 kfree(mgmt);
10774 return bss_status;
10775}
10776
10777/**
10778 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10779 * @pAdapter: Pointer to adapter
10780 * @pRoamInfo: Pointer to roam info
10781 *
10782 * This function is used to update the BSS data base of CFG8011
10783 *
10784 * Return: struct cfg80211_bss pointer
10785 */
10786struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10787 tCsrRoamInfo *pRoamInfo)
10788{
10789 tCsrRoamConnectedProfile roamProfile;
10790 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10791 struct cfg80211_bss *bss = NULL;
10792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10794 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10795
10796 if (NULL != roamProfile.pBssDesc) {
10797 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10798 roamProfile.pBssDesc);
10799
10800 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010801 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010803 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010805 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807 return bss;
10808}
10809/**
10810 * wlan_hdd_cfg80211_update_bss() - update bss
10811 * @wiphy: Pointer to wiphy
10812 * @pAdapter: Pointer to adapter
10813 * @scan_time: scan request timestamp
10814 *
10815 * Return: zero if success, non-zero otherwise
10816 */
10817int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10818 hdd_adapter_t *pAdapter,
10819 uint32_t scan_time)
10820{
10821 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10822 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010823 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010824 tScanResultHandle pResult;
10825 struct cfg80211_bss *bss_status = NULL;
10826 hdd_context_t *pHddCtx;
10827 int ret;
10828
10829 ENTER();
10830
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010831 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10833 NO_SESSION, pAdapter->sessionId));
10834
10835 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10836 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010837 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010838 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010839
10840 /* start getting scan results and populate cgf80211 BSS database */
10841 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10842
10843 /* no scan results */
10844 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010845 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010846 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847 }
10848
10849 pScanResult = sme_scan_result_get_first(hHal, pResult);
10850
10851 while (pScanResult) {
10852 /*
10853 * - cfg80211_inform_bss() is not updating ie field of bss
10854 * entry if entry already exists in bss data base of cfg80211
10855 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10856 * to update thebss entry instead of cfg80211_inform_bss,
10857 * But this call expects mgmt packet as input. As of now
10858 * there is no possibility to get the mgmt(probe response)
10859 * frame from PE, converting bss_desc to
10860 * ieee80211_mgmt(probe response) and passing to c
10861 * fg80211_inform_bss_frame.
10862 * - Update BSS only if beacon timestamp is later than
10863 * scan request timestamp.
10864 */
10865 if ((scan_time == 0) ||
10866 (scan_time <
Jeff Johnsonfeb22892016-10-27 14:12:38 -070010867 pScanResult->BssDescriptor.nReceivedTime)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010868 bss_status =
10869 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10870 &pScanResult->BssDescriptor);
10871
10872 if (NULL == bss_status) {
10873 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10874 } else {
10875 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010876 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877 bss_status);
10878 }
10879 } else {
10880 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10881 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10882 }
10883 pScanResult = sme_scan_result_get_next(hHal, pResult);
10884 }
10885
10886 sme_scan_result_purge(hHal, pResult);
10887 /*
10888 * For SAP mode, scan is invoked by hostapd during SAP start
10889 * if hostapd is restarted, we need to flush previous scan
10890 * result so that it will reflect environment change
10891 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010892 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10894 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10895#endif
10896 )
10897 sme_scan_flush_result(hHal);
10898
10899 EXIT();
10900 return 0;
10901}
10902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010903/**
10904 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10905 * @pAdapter: Pointer to adapter
10906 * @pRoamInfo: Pointer to roam info
10907 * @index: Index
10908 * @preauth: Preauth flag
10909 *
10910 * This function is used to notify the supplicant of a new PMKSA candidate.
10911 *
10912 * Return: 0 for success, non-zero for failure
10913 */
10914int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10915 tCsrRoamInfo *pRoamInfo,
10916 int index, bool preauth)
10917{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010918 struct net_device *dev = pAdapter->dev;
10919 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10920
10921 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010922 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923
10924 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010925 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010926 return -EINVAL;
10927 }
10928
10929 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010930 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10932 cfg80211_pmksa_candidate_notify(dev, index,
10933 pRoamInfo->bssid.bytes,
10934 preauth, GFP_KERNEL);
10935 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010936 return 0;
10937}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010938
10939#ifdef FEATURE_WLAN_LFR_METRICS
10940/**
10941 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10942 * @pAdapter: Pointer to adapter
10943 * @pRoamInfo: Pointer to roam info
10944 *
10945 * 802.11r/LFR metrics reporting function to report preauth initiation
10946 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010947 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948 */
10949#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010950QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951 tCsrRoamInfo *pRoamInfo)
10952{
10953 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10954 union iwreq_data wrqu;
10955
10956 ENTER();
10957
10958 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010959 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010960 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961 }
10962
10963 /* create the event */
10964 memset(&wrqu, 0, sizeof(wrqu));
10965 memset(metrics_notification, 0, sizeof(metrics_notification));
10966
10967 wrqu.data.pointer = metrics_notification;
10968 wrqu.data.length = scnprintf(metrics_notification,
10969 sizeof(metrics_notification),
10970 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10971 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10972
10973 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10974 metrics_notification);
10975
10976 EXIT();
10977
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010978 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010979}
10980
10981/**
10982 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10983 * @pAdapter: Pointer to adapter
10984 * @pRoamInfo: Pointer to roam info
10985 * @preauth_status: Preauth status
10986 *
10987 * 802.11r/LFR metrics reporting function to report handover initiation
10988 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010989 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010990 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010991QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010992wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10993 tCsrRoamInfo *pRoamInfo,
10994 bool preauth_status)
10995{
10996 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10997 union iwreq_data wrqu;
10998
10999 ENTER();
11000
11001 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011002 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011003 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011004 }
11005
11006 /* create the event */
11007 memset(&wrqu, 0, sizeof(wrqu));
11008 memset(metrics_notification, 0, sizeof(metrics_notification));
11009
11010 scnprintf(metrics_notification, sizeof(metrics_notification),
11011 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11012 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11013
11014 if (1 == preauth_status)
11015 strlcat(metrics_notification, " true",
11016 sizeof(metrics_notification));
11017 else
11018 strlcat(metrics_notification, " false",
11019 sizeof(metrics_notification));
11020
11021 wrqu.data.pointer = metrics_notification;
11022 wrqu.data.length = strlen(metrics_notification);
11023
11024 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11025 metrics_notification);
11026
11027 EXIT();
11028
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011029 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011030}
11031
11032/**
11033 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11034 * @pAdapter: Pointer to adapter
11035 * @pRoamInfo: Pointer to roam info
11036 *
11037 * 802.11r/LFR metrics reporting function to report handover initiation
11038 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011039 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011040 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011041QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011042 tCsrRoamInfo *pRoamInfo)
11043{
11044 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11045 union iwreq_data wrqu;
11046
11047 ENTER();
11048
11049 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011050 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011051 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 }
11053
11054 /* create the event */
11055 memset(&wrqu, 0, sizeof(wrqu));
11056 memset(metrics_notification, 0, sizeof(metrics_notification));
11057
11058 wrqu.data.pointer = metrics_notification;
11059 wrqu.data.length = scnprintf(metrics_notification,
11060 sizeof(metrics_notification),
11061 "QCOM: LFR_PREAUTH_HANDOVER "
11062 MAC_ADDRESS_STR,
11063 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11064
11065 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11066 metrics_notification);
11067
11068 EXIT();
11069
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011070 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011071}
11072#endif
11073
11074/**
11075 * hdd_select_cbmode() - select channel bonding mode
11076 * @pAdapter: Pointer to adapter
11077 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011078 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 *
11080 * Return: none
11081 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011082void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11083 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011085 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011086 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011087 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011088
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011089 /*
11090 * CDS api expects secondary channel for calculating
11091 * the channel params
11092 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011093 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011094 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11095 if (operationChannel >= 1 && operationChannel <= 5)
11096 sec_ch = operationChannel + 4;
11097 else if (operationChannel >= 6 && operationChannel <= 13)
11098 sec_ch = operationChannel - 4;
11099 }
11100
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011101 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011102 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011103
11104 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011105 eHddDot11Mode hdd_dot11_mode;
11106 uint8_t iniDot11Mode =
11107 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11108
11109 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11110 switch (iniDot11Mode) {
11111 case eHDD_DOT11_MODE_AUTO:
11112 case eHDD_DOT11_MODE_11ac:
11113 case eHDD_DOT11_MODE_11ac_ONLY:
11114 if (sme_is_feature_supported_by_fw(DOT11AC))
11115 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11116 else
11117 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11118 break;
11119 case eHDD_DOT11_MODE_11n:
11120 case eHDD_DOT11_MODE_11n_ONLY:
11121 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11122 break;
11123 default:
11124 hdd_dot11_mode = iniDot11Mode;
11125 break;
11126 }
11127 ch_info->channel_width = ch_params->ch_width;
11128 ch_info->phy_mode =
11129 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011130 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011131 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011132 hdd_info("ch_info width %d, phymode %d channel %d",
11133 ch_info->channel_width, ch_info->phy_mode,
11134 ch_info->channel);
11135 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011136}
11137
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011138/**
11139 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11140 * @adapter: STA adapter
11141 * @roam_profile: STA roam profile
11142 *
11143 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11144 *
11145 * Return: false if sta-sap conc is not allowed, else return true
11146 */
11147static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11148 tCsrRoamProfile *roam_profile)
11149{
11150 hdd_context_t *hdd_ctx;
11151 hdd_adapter_t *ap_adapter;
11152 hdd_ap_ctx_t *hdd_ap_ctx;
11153 hdd_hostapd_state_t *hostapd_state;
11154 uint8_t channel = 0;
11155 QDF_STATUS status;
11156
11157 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11158 if (!hdd_ctx) {
11159 hdd_err("HDD context is NULL");
11160 return true;
11161 }
11162
11163 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11164 /* probably no sap running, no handling required */
11165 if (ap_adapter == NULL)
11166 return true;
11167
11168 /*
11169 * sap is not in started state, so it is fine to go ahead with sta.
11170 * if sap is currently doing CAC then don't allow sta to go further.
11171 */
11172 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11173 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11174 return true;
11175
11176 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11177 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11178 return false;
11179 }
11180
11181 /*
11182 * log and return error, if we allow STA to go through, we don't
11183 * know what is going to happen better stop sta connection
11184 */
11185 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11186 if (NULL == hdd_ap_ctx) {
11187 hdd_err("AP context not found");
11188 return false;
11189 }
11190
11191 /* sap is on non-dfs channel, nothing to handle */
11192 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11193 hdd_info("sap is on non-dfs channel, sta is allowed");
11194 return true;
11195 }
11196 /*
11197 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011198 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011199 */
11200 status = cds_get_channel_from_scan_result(adapter,
11201 roam_profile, &channel);
11202
Nitesh Shah59774522016-09-16 15:14:21 +053011203 /*
11204 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11205 * channels for roaming case.
11206 */
11207 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11208 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11209 return true;
11210 }
11211
11212 /*
11213 * If channel is 0 or DFS then better to call pcl and find out the
11214 * best channel. If channel is non-dfs 5 GHz then better move SAP
11215 * to STA's channel to make scc, so we have room for 3port MCC
11216 * scenario.
11217 */
11218 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011219 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11220 true);
11221
11222 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11223 qdf_event_reset(&hostapd_state->qdf_event);
11224 status = wlansap_set_channel_change_with_csa(
11225 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11226 hdd_ap_ctx->sapConfig.ch_width_orig);
11227
11228 if (QDF_STATUS_SUCCESS != status) {
11229 hdd_err("Set channel with CSA IE failed, can't allow STA");
11230 return false;
11231 }
11232
11233 /*
11234 * wait here for SAP to finish the channel switch. When channel
11235 * switch happens, SAP sends few beacons with CSA_IE. After
11236 * successfully Transmission of those beacons, it will move its
11237 * state from started to disconnected and move to new channel.
11238 * once it moves to new channel, sap again moves its state
11239 * machine from disconnected to started and set this event.
11240 * wait for 10 secs to finish this.
11241 */
11242 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11243 if (!QDF_IS_STATUS_SUCCESS(status)) {
11244 hdd_err("wait for qdf_event failed, STA not allowed!!");
11245 return false;
11246 }
11247
11248 return true;
11249}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250
Krunal Soni31949422016-07-29 17:17:53 -070011251/**
11252 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011254 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011255 * @ssid_len: Length of ssid
11256 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011257 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011259 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260 *
11261 * This function is used to start the association process
11262 *
11263 * Return: 0 for success, non-zero for failure
11264 */
Krunal Soni31949422016-07-29 17:17:53 -070011265static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011266 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011267 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011268 u8 operatingChannel,
11269 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270{
11271 int status = 0;
11272 hdd_wext_state_t *pWextState;
11273 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011274 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011275 uint32_t roamId;
11276 tCsrRoamProfile *pRoamProfile;
11277 eCsrAuthType RSNAuthType;
11278 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011279 uint8_t channel = 0;
11280 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281
11282 ENTER();
11283
11284 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11285 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011286 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287
11288 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011289 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011291
11292 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011293 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294 return -EINVAL;
11295 }
11296
11297 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011298 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11299 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300
11301 if (pRoamProfile) {
11302 hdd_station_ctx_t *pHddStaCtx;
11303 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11304
11305 if (HDD_WMM_USER_MODE_NO_QOS ==
11306 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11307 /*QoS not enabled in cfg file */
11308 pRoamProfile->uapsd_mask = 0;
11309 } else {
11310 /*QoS enabled, update uapsd mask from cfg file */
11311 pRoamProfile->uapsd_mask =
11312 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11313 }
11314
11315 pRoamProfile->SSIDs.numOfSSIDs = 1;
11316 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011317 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011318 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011319 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011320 ssid, ssid_len);
11321
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011322 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011323 if (bssid) {
11324 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011325 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011326 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011327 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011328 /*
11329 * Save BSSID in seperate variable as
11330 * pRoamProfile's BSSID is getting zeroed out in the
11331 * association process. In case of join failure
11332 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011334 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011335 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011336 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011337 } else if (bssid_hint) {
11338 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011339 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011340 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011341 /*
11342 * Save BSSID in a separate variable as
11343 * pRoamProfile's BSSID is getting zeroed out in the
11344 * association process. In case of join failure
11345 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011347 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011348 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011349 hdd_info("bssid_hint is given by upper layer %pM",
11350 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011351 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011352 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011353 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011354 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011355 }
11356
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011357 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358 pRoamProfile->SSIDs.SSIDList->SSID.length,
11359 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11360 operatingChannel);
11361
11362 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11363 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011364 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011365 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11366 }
11367#ifdef FEATURE_WLAN_WAPI
11368 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011369 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 switch (pAdapter->wapi_info.wapiAuthMode) {
11371 case WAPI_AUTH_MODE_PSK:
11372 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011373 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011374 pAdapter->wapi_info.wapiAuthMode);
11375 pRoamProfile->AuthType.authType[0] =
11376 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11377 break;
11378 }
11379 case WAPI_AUTH_MODE_CERT:
11380 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011381 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 pAdapter->wapi_info.wapiAuthMode);
11383 pRoamProfile->AuthType.authType[0] =
11384 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11385 break;
11386 }
11387 } /* End of switch */
11388 if (pAdapter->wapi_info.wapiAuthMode ==
11389 WAPI_AUTH_MODE_PSK
11390 || pAdapter->wapi_info.wapiAuthMode ==
11391 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011392 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 pRoamProfile->AuthType.numEntries = 1;
11394 pRoamProfile->EncryptionType.numEntries = 1;
11395 pRoamProfile->EncryptionType.encryptionType[0] =
11396 eCSR_ENCRYPT_TYPE_WPI;
11397 pRoamProfile->mcEncryptionType.numEntries = 1;
11398 pRoamProfile->mcEncryptionType.
11399 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11400 }
11401 }
Krunal Soni31949422016-07-29 17:17:53 -070011402#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403#ifdef WLAN_FEATURE_GTK_OFFLOAD
11404 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011405 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11406 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011407 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11408 sizeof(tSirGtkOffloadParams));
11409 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11410 GTK_OFFLOAD_DISABLE;
11411 }
11412#endif
11413 pRoamProfile->csrPersona = pAdapter->device_mode;
11414
11415 if (operatingChannel) {
11416 pRoamProfile->ChannelInfo.ChannelList =
11417 &operatingChannel;
11418 pRoamProfile->ChannelInfo.numOfChannels = 1;
11419 } else {
11420 pRoamProfile->ChannelInfo.ChannelList = NULL;
11421 pRoamProfile->ChannelInfo.numOfChannels = 0;
11422 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011423 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011424 && operatingChannel) {
11425 /*
11426 * Need to post the IBSS power save parameters
11427 * to WMA. WMA will configure this parameters
11428 * to firmware if power save is enabled by the
11429 * firmware.
11430 */
11431 status = hdd_set_ibss_power_save_params(pAdapter);
11432
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011433 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011434 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 return -EINVAL;
11436 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011437 pRoamProfile->ch_params.ch_width =
11438 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011439 /*
11440 * In IBSS mode while operating in 2.4 GHz,
11441 * the device supports only 20 MHz.
11442 */
11443 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11444 pRoamProfile->ch_params.ch_width =
11445 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011446 hdd_select_cbmode(pAdapter, operatingChannel,
11447 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011448 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011449 /*
11450 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11451 * or pmf=2 is an explicit configuration in the supplicant
11452 * configuration, drop the connection request.
11453 */
11454 if (pWextState->roamProfile.MFPEnabled &&
11455 !(pWextState->roamProfile.MFPRequired ||
11456 pWextState->roamProfile.MFPCapable)) {
11457 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11458 pWextState->roamProfile.MFPEnabled,
11459 pWextState->roamProfile.MFPRequired,
11460 pWextState->roamProfile.MFPCapable);
11461 return -EINVAL;
11462 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011463
Krunal Soni3091bcc2016-06-23 12:28:21 -070011464 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 hdd_err("Connection refused: conn in progress");
11466 return -EINVAL;
11467 }
11468
Krunal Soni31949422016-07-29 17:17:53 -070011469 /*
11470 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011472 * enhancements, the supplicant is not issuing the scan command
11473 * now. So the unicast frames which are sent from the host are
11474 * not having the additional IEs. If it is P2P CLIENT and there
11475 * is no additional IE present in roamProfile, then use the
11476 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 */
11478
Krunal Sonib4326f22016-03-10 13:05:51 -080011479 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 (!pRoamProfile->pAddIEScan)) {
11481 pRoamProfile->pAddIEScan =
11482 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11483 pRoamProfile->nAddIEScanLength =
11484 pAdapter->scan_info.scanAddIE.length;
11485 }
11486 /*
11487 * When policy manager is enabled from ini file, we shouldn't
11488 * check for other concurrency rules.
11489 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011490 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011491 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011492 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011493 pAdapter, pRoamProfile, &roamId))
11494 return 0;
11495 }
11496
Krunal Soni3091bcc2016-06-23 12:28:21 -070011497 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011498 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11499 pRoamProfile))) {
11500 hdd_err("sap-sta conc will fail, can't allow sta");
11501 hdd_conn_set_connection_state(pAdapter,
11502 eConnectionState_NotConnected);
11503 return -ENOMEM;
11504 }
11505
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011506 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011507 if (!sme_config) {
11508 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011509 hdd_conn_set_connection_state(pAdapter,
11510 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 return -ENOMEM;
11512 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 sme_get_config_param(pHddCtx->hHal, sme_config);
11514 /* These values are not sessionized. So, any change in these SME
11515 * configs on an older or parallel interface will affect the
11516 * cb mode. So, restoring the default INI params before starting
11517 * interfaces such as sta, cli etc.,
11518 */
11519 sme_config->csrConfig.channelBondingMode5GHz =
11520 pHddCtx->config->nChannelBondingMode5GHz;
11521 sme_config->csrConfig.channelBondingMode24GHz =
11522 pHddCtx->config->nChannelBondingMode24GHz;
11523 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011524 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011525 /*
11526 * Change conn_state to connecting before sme_roam_connect(),
11527 * because sme_roam_connect() has a direct path to call
11528 * hdd_sme_roam_callback(), which will change the conn_state
11529 * If direct path, conn_state will be accordingly changed to
11530 * NotConnected or Associated by either
11531 * hdd_association_completion_handler() or
11532 * hdd_dis_connect_handler() in sme_RoamCallback()if
11533 * sme_RomConnect is to be queued,
11534 * Connecting state will remain until it is completed.
11535 *
11536 * If connection state is not changed, connection state will
11537 * remain in eConnectionState_NotConnected state.
11538 * In hdd_association_completion_handler, "hddDisconInProgress"
11539 * is set to true if conn state is
11540 * eConnectionState_NotConnected.
11541 * If "hddDisconInProgress" is set to true then cfg80211 layer
11542 * is not informed of connect result indication which
11543 * is an issue.
11544 */
11545 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011546 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011547 hdd_conn_set_connection_state(pAdapter,
11548 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011549
Komal Seelama89be8d2016-09-29 11:09:26 +053011550 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11551 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11553 pAdapter->sessionId, pRoamProfile,
11554 &roamId);
11555
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011556 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011557 (QDF_STA_MODE == pAdapter->device_mode ||
11558 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011559 hdd_err("sme_roam_connect (session %d) failed with "
11560 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561 pAdapter->sessionId, status);
11562 /* change back to NotAssociated */
11563 hdd_conn_set_connection_state(pAdapter,
11564 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011565 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11566 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 }
11568
11569 pRoamProfile->ChannelInfo.ChannelList = NULL;
11570 pRoamProfile->ChannelInfo.numOfChannels = 0;
11571
Nitesh Shah044fd672016-10-13 18:53:25 +053011572 if (!QDF_IS_STATUS_SUCCESS(
11573 wma_get_current_hw_mode(&hw_mode))) {
11574 hdd_err("wma_get_current_hw_mode failed");
11575 return status;
11576 }
11577
11578 if ((QDF_STA_MODE == pAdapter->device_mode)
11579 && hw_mode.dbs_cap) {
11580 cds_get_channel_from_scan_result(pAdapter,
11581 pRoamProfile, &channel);
11582 if (channel)
11583 cds_checkn_update_hw_mode_single_mac_mode
11584 (channel);
11585 }
11586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011588 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011589 return -EINVAL;
11590 }
11591 EXIT();
11592 return status;
11593}
11594
11595/**
11596 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11597 * @pAdapter: Pointer to adapter
11598 * @auth_type: Auth type
11599 *
11600 * This function is used to set the authentication type (OPEN/SHARED).
11601 *
11602 * Return: 0 for success, non-zero for failure
11603 */
11604static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11605 enum nl80211_auth_type auth_type)
11606{
11607 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11608 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011610 /*set authentication type */
11611 switch (auth_type) {
11612 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011613 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011614 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11615 break;
11616
11617 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011619 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11621 break;
11622
11623 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011624 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011625 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11626 break;
11627#ifdef FEATURE_WLAN_ESE
11628 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011629 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011630 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11631 break;
11632#endif
11633
11634 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011635 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11637 return -EINVAL;
11638 }
11639
11640 pWextState->roamProfile.AuthType.authType[0] =
11641 pHddStaCtx->conn_info.authType;
11642 return 0;
11643}
11644
11645/**
11646 * wlan_hdd_set_akm_suite() - set key management type
11647 * @pAdapter: Pointer to adapter
11648 * @key_mgmt: Key management type
11649 *
11650 * This function is used to set the key mgmt type(PSK/8021x).
11651 *
11652 * Return: 0 for success, non-zero for failure
11653 */
11654static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11655{
11656 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11657
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11659#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11660 /*set key mgmt type */
11661 switch (key_mgmt) {
11662 case WLAN_AKM_SUITE_PSK:
11663 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011665 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011666 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11667 break;
11668
11669 case WLAN_AKM_SUITE_8021X_SHA256:
11670 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011672 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11674 break;
11675#ifdef FEATURE_WLAN_ESE
11676#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11677#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11678 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011679 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11681 break;
11682#endif
11683#ifndef WLAN_AKM_SUITE_OSEN
11684#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11685#endif
11686 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011687 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11689 break;
11690
11691 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011692 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 return -EINVAL;
11694
11695 }
11696 return 0;
11697}
11698
11699/**
11700 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11701 * @pAdapter: Pointer to adapter
11702 * @cipher: Cipher type
11703 * @ucast: Unicast flag
11704 *
11705 * This function is used to set the encryption type
11706 * (NONE/WEP40/WEP104/TKIP/CCMP).
11707 *
11708 * Return: 0 for success, non-zero for failure
11709 */
11710static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11711 u32 cipher, bool ucast)
11712{
11713 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11714 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11715 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11716
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011717 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011718 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11720 } else {
11721
11722 /*set encryption method */
11723 switch (cipher) {
11724 case IW_AUTH_CIPHER_NONE:
11725 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11726 break;
11727
11728 case WLAN_CIPHER_SUITE_WEP40:
11729 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11730 break;
11731
11732 case WLAN_CIPHER_SUITE_WEP104:
11733 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11734 break;
11735
11736 case WLAN_CIPHER_SUITE_TKIP:
11737 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11738 break;
11739
11740 case WLAN_CIPHER_SUITE_CCMP:
11741 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11742 break;
11743#ifdef FEATURE_WLAN_WAPI
11744 case WLAN_CIPHER_SUITE_SMS4:
11745 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11746 break;
11747#endif
11748
11749#ifdef FEATURE_WLAN_ESE
11750 case WLAN_CIPHER_SUITE_KRK:
11751 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11752 break;
11753#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11754 case WLAN_CIPHER_SUITE_BTK:
11755 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11756 break;
11757#endif
11758#endif
11759 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011760 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 return -EOPNOTSUPP;
11762 }
11763 }
11764
11765 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011766 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11768 pWextState->roamProfile.EncryptionType.numEntries = 1;
11769 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11770 encryptionType;
11771 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011772 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11774 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11775 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11776 encryptionType;
11777 }
11778
11779 return 0;
11780}
11781
11782/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011783 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11784 * @wext_state: Pointer to wext state
11785 * @gen_ie: Pointer to IE data
11786 * @len: length of IE data
11787 *
11788 * Return: 0 for success, non-zero for failure
11789 */
11790static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11791 const uint8_t *gen_ie, uint16_t len)
11792{
11793 uint16_t cur_add_ie_len =
11794 wext_state->assocAddIE.length;
11795
11796 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11797 (wext_state->assocAddIE.length + len)) {
11798 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11799 QDF_ASSERT(0);
11800 return -ENOMEM;
11801 }
11802 memcpy(wext_state->assocAddIE.addIEdata +
11803 cur_add_ie_len, gen_ie, len);
11804 wext_state->assocAddIE.length += len;
11805
11806 wext_state->roamProfile.pAddIEAssoc =
11807 wext_state->assocAddIE.addIEdata;
11808 wext_state->roamProfile.nAddIEAssocLength =
11809 wext_state->assocAddIE.length;
11810 return 0;
11811}
11812
11813/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011814 * wlan_hdd_cfg80211_set_ie() - set IEs
11815 * @pAdapter: Pointer to adapter
11816 * @ie: Pointer ot ie
11817 * @ie: IE length
11818 *
11819 * Return: 0 for success, non-zero for failure
11820 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011821static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011822 size_t ie_len)
11823{
11824 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11825 const uint8_t *genie = ie;
11826 uint16_t remLen = ie_len;
11827#ifdef FEATURE_WLAN_WAPI
11828 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11829 u16 *tmp;
11830 uint16_t akmsuiteCount;
11831 int *akmlist;
11832#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011833 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834
11835 /* clear previous assocAddIE */
11836 pWextState->assocAddIE.length = 0;
11837 pWextState->roamProfile.bWPSAssociation = false;
11838 pWextState->roamProfile.bOSENAssociation = false;
11839
11840 while (remLen >= 2) {
11841 uint16_t eLen = 0;
11842 uint8_t elementId;
11843 elementId = *genie++;
11844 eLen = *genie++;
11845 remLen -= 2;
11846
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011847 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848
11849 switch (elementId) {
11850 case DOT11F_EID_WPA:
11851 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 -070011852 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 return -EINVAL;
11854 } else if (0 ==
11855 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11856 uint16_t curAddIELen =
11857 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011858 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859
11860 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11861 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011862 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011863 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011864 return -ENOMEM;
11865 }
11866 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11867 memcpy(pWextState->assocAddIE.addIEdata +
11868 curAddIELen, genie - 2, eLen + 2);
11869 pWextState->assocAddIE.length += eLen + 2;
11870
11871 pWextState->roamProfile.bWPSAssociation = true;
11872 pWextState->roamProfile.pAddIEAssoc =
11873 pWextState->assocAddIE.addIEdata;
11874 pWextState->roamProfile.nAddIEAssocLength =
11875 pWextState->assocAddIE.length;
11876 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011877 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011878 memset(pWextState->WPARSNIE, 0,
11879 MAX_WPA_RSN_IE_LEN);
11880 memcpy(pWextState->WPARSNIE, genie - 2,
11881 (eLen + 2));
11882 pWextState->roamProfile.pWPAReqIE =
11883 pWextState->WPARSNIE;
11884 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11885 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11886 P2P_OUI_TYPE_SIZE))) {
11887 uint16_t curAddIELen =
11888 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011889 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011890
11891 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11892 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011893 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011894 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011895 return -ENOMEM;
11896 }
11897 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11898 memcpy(pWextState->assocAddIE.addIEdata +
11899 curAddIELen, genie - 2, eLen + 2);
11900 pWextState->assocAddIE.length += eLen + 2;
11901
11902 pWextState->roamProfile.pAddIEAssoc =
11903 pWextState->assocAddIE.addIEdata;
11904 pWextState->roamProfile.nAddIEAssocLength =
11905 pWextState->assocAddIE.length;
11906 }
11907#ifdef WLAN_FEATURE_WFD
11908 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11909 WFD_OUI_TYPE_SIZE)) &&
11910 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011911 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011912 pAdapter->device_mode)) {
11913 uint16_t curAddIELen =
11914 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011915 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011916
11917 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11918 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011919 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011920 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011921 return -ENOMEM;
11922 }
11923 /* WFD IE is saved to Additional IE ; it should
11924 * be accumulated to handle WPS IE + P2P IE +
11925 * WFD IE */
11926 memcpy(pWextState->assocAddIE.addIEdata +
11927 curAddIELen, genie - 2, eLen + 2);
11928 pWextState->assocAddIE.length += eLen + 2;
11929
11930 pWextState->roamProfile.pAddIEAssoc =
11931 pWextState->assocAddIE.addIEdata;
11932 pWextState->roamProfile.nAddIEAssocLength =
11933 pWextState->assocAddIE.length;
11934 }
11935#endif
11936 /* Appending HS 2.0 Indication Element in Assiciation Request */
11937 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11938 HS20_OUI_TYPE_SIZE))) {
11939 uint16_t curAddIELen =
11940 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011941 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942
11943 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11944 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011945 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011946 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 return -ENOMEM;
11948 }
11949 memcpy(pWextState->assocAddIE.addIEdata +
11950 curAddIELen, genie - 2, eLen + 2);
11951 pWextState->assocAddIE.length += eLen + 2;
11952
11953 pWextState->roamProfile.pAddIEAssoc =
11954 pWextState->assocAddIE.addIEdata;
11955 pWextState->roamProfile.nAddIEAssocLength =
11956 pWextState->assocAddIE.length;
11957 }
11958 /* Appending OSEN Information Element in Assiciation Request */
11959 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11960 OSEN_OUI_TYPE_SIZE))) {
11961 uint16_t curAddIELen =
11962 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011963 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011964
11965 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11966 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011967 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011968 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011969 return -ENOMEM;
11970 }
11971 memcpy(pWextState->assocAddIE.addIEdata +
11972 curAddIELen, genie - 2, eLen + 2);
11973 pWextState->assocAddIE.length += eLen + 2;
11974
11975 pWextState->roamProfile.bOSENAssociation = true;
11976 pWextState->roamProfile.pAddIEAssoc =
11977 pWextState->assocAddIE.addIEdata;
11978 pWextState->roamProfile.nAddIEAssocLength =
11979 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011980 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11981 MBO_OUI_TYPE_SIZE))){
11982 hdd_info("Set MBO IE(len %d)", eLen + 2);
11983 status = wlan_hdd_add_assoc_ie(pWextState,
11984 genie - 2, eLen + 2);
11985 if (status)
11986 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011987 } else {
11988 uint16_t add_ie_len =
11989 pWextState->assocAddIE.length;
11990
11991 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11992
11993 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11994 (pWextState->assocAddIE.length + eLen)) {
11995 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011996 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997 return -ENOMEM;
11998 }
11999
12000 memcpy(pWextState->assocAddIE.addIEdata +
12001 add_ie_len, genie - 2, eLen + 2);
12002 pWextState->assocAddIE.length += eLen + 2;
12003
12004 pWextState->roamProfile.pAddIEAssoc =
12005 pWextState->assocAddIE.addIEdata;
12006 pWextState->roamProfile.nAddIEAssocLength =
12007 pWextState->assocAddIE.length;
12008 }
12009 break;
12010 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012011 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012012 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12013 memcpy(pWextState->WPARSNIE, genie - 2,
12014 (eLen + 2));
12015 pWextState->roamProfile.pRSNReqIE =
12016 pWextState->WPARSNIE;
12017 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12018 break;
12019 /*
12020 * Appending Extended Capabilities with Interworking bit set
12021 * in Assoc Req.
12022 *
12023 * In assoc req this EXT Cap will only be taken into account if
12024 * interworkingService bit is set to 1. Currently
12025 * driver is only interested in interworkingService capability
12026 * from supplicant. If in future any other EXT Cap info is
12027 * required from supplicat, it needs to be handled while
12028 * sending Assoc Req in LIM.
12029 */
12030 case DOT11F_EID_EXTCAP:
12031 {
12032 uint16_t curAddIELen =
12033 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012034 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012035
12036 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12037 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012038 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012039 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 return -ENOMEM;
12041 }
12042 memcpy(pWextState->assocAddIE.addIEdata +
12043 curAddIELen, genie - 2, eLen + 2);
12044 pWextState->assocAddIE.length += eLen + 2;
12045
12046 pWextState->roamProfile.pAddIEAssoc =
12047 pWextState->assocAddIE.addIEdata;
12048 pWextState->roamProfile.nAddIEAssocLength =
12049 pWextState->assocAddIE.length;
12050 break;
12051 }
12052#ifdef FEATURE_WLAN_WAPI
12053 case WLAN_EID_WAPI:
12054 /* Setting WAPI Mode to ON=1 */
12055 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012056 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012057 tmp = (u16 *) ie;
12058 tmp = tmp + 2; /* Skip element Id and Len, Version */
12059 akmsuiteCount = WPA_GET_LE16(tmp);
12060 tmp = tmp + 1;
12061 akmlist = (int *)(tmp);
12062 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12063 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12064 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012065 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012066 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012067 return -EINVAL;
12068 }
12069
12070 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012071 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072 pAdapter->wapi_info.wapiAuthMode =
12073 WAPI_AUTH_MODE_PSK;
12074 }
12075 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012076 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012077 pAdapter->wapi_info.wapiAuthMode =
12078 WAPI_AUTH_MODE_CERT;
12079 }
12080 break;
12081#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012082 case DOT11F_EID_SUPPOPERATINGCLASSES:
12083 {
12084 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12085 status = wlan_hdd_add_assoc_ie(pWextState,
12086 genie - 2, eLen + 2);
12087 if (status)
12088 return status;
12089 break;
12090 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012092 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012093 /* when Unknown IE is received we should break and continue
12094 * to the next IE in the buffer instead we were returning
12095 * so changing this to break */
12096 break;
12097 }
12098 genie += eLen;
12099 remLen -= eLen;
12100 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012101 return 0;
12102}
12103
12104/**
12105 * hdd_is_wpaie_present() - check for WPA ie
12106 * @ie: Pointer to ie
12107 * @ie_len: Ie length
12108 *
12109 * Parse the received IE to find the WPA IE
12110 *
12111 * Return: true if wpa ie is found else false
12112 */
12113static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12114{
12115 uint8_t eLen = 0;
12116 uint16_t remLen = ie_len;
12117 uint8_t elementId = 0;
12118
12119 while (remLen >= 2) {
12120 elementId = *ie++;
12121 eLen = *ie++;
12122 remLen -= 2;
12123 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012124 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012125 return false;
12126 }
12127 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12128 /* OUI - 0x00 0X50 0XF2
12129 * WPA Information Element - 0x01
12130 * WPA version - 0x01
12131 */
12132 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12133 return true;
12134 }
12135 ie += eLen;
12136 remLen -= eLen;
12137 }
12138 return false;
12139}
12140
12141/**
12142 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12143 * @pAdapter: Pointer to adapter
12144 * @req: Pointer to security parameters
12145 *
12146 * Return: 0 for success, non-zero for failure
12147 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012148static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12149 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012150{
12151 int status = 0;
12152 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12153 ENTER();
12154
12155 /*set wpa version */
12156 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12157
12158 if (req->crypto.wpa_versions) {
12159 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12160 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12161 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12162 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12163 }
12164 }
12165
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012166 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167
12168 /*set authentication type */
12169 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12170
12171 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012172 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012173 return status;
12174 }
12175
12176 /*set key mgmt type */
12177 if (req->crypto.n_akm_suites) {
12178 status =
12179 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12180 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012181 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012182 return status;
12183 }
12184 }
12185
12186 /*set pairwise cipher type */
12187 if (req->crypto.n_ciphers_pairwise) {
12188 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12189 req->crypto.
12190 ciphers_pairwise[0],
12191 true);
12192 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012193 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012194 return status;
12195 }
12196 } else {
12197 /*Reset previous cipher suite to none */
12198 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12199 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012200 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012201 return status;
12202 }
12203 }
12204
12205 /*set group cipher type */
12206 status =
12207 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12208 false);
12209
12210 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012211 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012212 return status;
12213 }
12214#ifdef WLAN_FEATURE_11W
12215 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12216#endif
12217
12218 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12219 if (req->ie_len) {
12220 status =
12221 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12222 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012223 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 return status;
12225 }
12226 }
12227
12228 /*incase of WEP set default key information */
12229 if (req->key && req->key_len) {
12230 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12231 || (WLAN_CIPHER_SUITE_WEP104 ==
12232 req->crypto.ciphers_pairwise[0])
12233 ) {
12234 if (IW_AUTH_KEY_MGMT_802_1X
12235 ==
12236 (pWextState->
12237 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012238 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012239 return -EOPNOTSUPP;
12240 } else {
12241 u8 key_len = req->key_len;
12242 u8 key_idx = req->key_idx;
12243
12244 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12245 key_len)
12246 && (CSR_MAX_NUM_KEY > key_idx)
12247 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012248 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012250 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012251 Keys.
12252 KeyMaterial[key_idx][0],
12253 req->key, key_len);
12254 pWextState->roamProfile.Keys.
12255 KeyLength[key_idx] = (u8) key_len;
12256 pWextState->roamProfile.Keys.
12257 defaultIndex = (u8) key_idx;
12258 }
12259 }
12260 }
12261 }
12262
12263 return status;
12264}
12265
12266/**
12267 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12268 * @pAdapter: Pointer to adapter
12269 *
12270 * This function is used to disconnect from previous connection
12271 *
12272 * Return: 0 for success, non-zero for failure
12273 */
12274static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12275{
12276 unsigned long rc;
12277 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012278 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012279
12280 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12281
Jeff Johnson9edf9572016-10-03 15:24:49 -070012282 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012283 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12284 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12285 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012286 hdd_conn_set_connection_state(pAdapter,
12287 eConnectionState_Disconnecting);
12288 /* Issue disconnect to CSR */
12289 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012290
12291 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12292 pAdapter->sessionId,
12293 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12294 /*
12295 * Wait here instead of returning directly, this will block the
12296 * next connect command and allow processing of the scan for
12297 * ssid and the previous connect command in CSR. Else we might
12298 * hit some race conditions leading to SME and HDD out of sync.
12299 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012300 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012301 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12302 } else if (0 != status) {
12303 hdd_err("csrRoamDisconnect failure, returned %d",
12304 (int)status);
12305 pHddStaCtx->staDebugState = status;
12306 result = -EINVAL;
12307 goto disconnected;
12308 }
12309
12310 rc = wait_for_completion_timeout(
12311 &pAdapter->disconnect_comp_var,
12312 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012313 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012314 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12315 pAdapter->sessionId, pHddStaCtx->staDebugState);
12316 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012317 }
12318 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012319 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012321 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012323 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012325 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012326 }
12327 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012328disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012329 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12330 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331}
12332
12333/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012334 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12335 * @adapter: Pointer to the HDD adapter
12336 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012337 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012338 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012339 * This function will start reassociation if prev_bssid is set and bssid/
12340 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012341 *
Naveen Rawat07332902016-07-27 09:13:17 -070012342 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012343 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012344#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12345 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012346static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12347 struct cfg80211_connect_params *req,
12348 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012349{
Naveen Rawat07332902016-07-27 09:13:17 -070012350 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012351 const uint8_t *bssid = NULL;
12352 uint16_t channel = 0;
12353
12354 if (req->bssid)
12355 bssid = req->bssid;
12356 else if (req->bssid_hint)
12357 bssid = req->bssid_hint;
12358
12359 if (req->channel)
12360 channel = req->channel->hw_value;
12361 else if (req->channel_hint)
12362 channel = req->channel_hint->hw_value;
12363
12364 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012365 reassoc = true;
12366 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012367 channel, MAC_ADDR_ARRAY(bssid));
12368 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012369 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012370 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012371 }
Naveen Rawat07332902016-07-27 09:13:17 -070012372 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012373}
12374#else
Naveen Rawat07332902016-07-27 09:13:17 -070012375static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12376 struct cfg80211_connect_params *req,
12377 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012378{
Naveen Rawat07332902016-07-27 09:13:17 -070012379 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012380}
12381#endif
12382
12383/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12385 * @wiphy: Pointer to wiphy
12386 * @dev: Pointer to network device
12387 * @req: Pointer to cfg80211 connect request
12388 *
12389 * This function is used to start the association process
12390 *
12391 * Return: 0 for success, non-zero for failure
12392 */
12393static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12394 struct net_device *ndev,
12395 struct cfg80211_connect_params *req)
12396{
12397 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012398 u16 channel;
12399#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12400 const u8 *bssid_hint = req->bssid_hint;
12401#else
12402 const u8 *bssid_hint = NULL;
12403#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12405 hdd_context_t *pHddCtx;
12406
12407 ENTER();
12408
Anurag Chouhan6d760662016-02-20 16:05:43 +053012409 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012410 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012411 return -EINVAL;
12412 }
12413
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012414 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012415 TRACE_CODE_HDD_CFG80211_CONNECT,
12416 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012417 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 hdd_device_mode_to_string(pAdapter->device_mode),
12419 pAdapter->device_mode);
12420
Krunal Sonib4326f22016-03-10 13:05:51 -080012421 if (pAdapter->device_mode != QDF_STA_MODE &&
12422 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012423 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012424 hdd_device_mode_to_string(pAdapter->device_mode),
12425 pAdapter->device_mode);
12426 return -EINVAL;
12427 }
12428
12429 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12430 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012431 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432 return -EINVAL;
12433 }
12434
12435 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012436 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012437 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012438
Naveen Rawat07332902016-07-27 09:13:17 -070012439 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012440 return status;
12441
Agrawal Ashishf156e942016-08-04 14:54:47 +053012442 wlan_hdd_disable_roaming(pAdapter);
12443
12444 /* Try disconnecting if already in connected state */
12445 status = wlan_hdd_try_disconnect(pAdapter);
12446 if (0 > status) {
12447 hdd_err("Failed to disconnect the existing connection");
12448 return -EALREADY;
12449 }
12450
12451 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012452 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012453 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012454 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455 pAdapter->device_mode),
12456 req->channel->hw_value, HW_MODE_20_MHZ)) {
12457 hdd_err("This concurrency combination is not allowed");
12458 return -ECONNREFUSED;
12459 }
12460 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012461 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012462 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12464 hdd_err("This concurrency combination is not allowed");
12465 return -ECONNREFUSED;
12466 }
12467 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469 /*initialise security parameters */
12470 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12471
12472 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012473 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012474 return status;
12475 }
12476
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012477 if (req->channel)
12478 channel = req->channel->hw_value;
12479 else
12480 channel = 0;
12481 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12482 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012483 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012484 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012485 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 return status;
12487 }
12488 EXIT();
12489 return status;
12490}
12491
12492/**
12493 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12494 * @wiphy: Pointer to wiphy
12495 * @dev: Pointer to network device
12496 * @req: Pointer to cfg80211 connect request
12497 *
12498 * Return: 0 for success, non-zero for failure
12499 */
12500static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12501 struct net_device *ndev,
12502 struct cfg80211_connect_params *req)
12503{
12504 int ret;
12505 cds_ssr_protect(__func__);
12506 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12507 cds_ssr_unprotect(__func__);
12508
12509 return ret;
12510}
12511
12512/**
12513 * wlan_hdd_disconnect() - hdd disconnect api
12514 * @pAdapter: Pointer to adapter
12515 * @reason: Disconnect reason code
12516 *
12517 * This function is used to issue a disconnect request to SME
12518 *
12519 * Return: 0 for success, non-zero for failure
12520 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012521static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522{
12523 int status, result = 0;
12524 unsigned long rc;
12525 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12526 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12527
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012528 ENTER();
12529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 status = wlan_hdd_validate_context(pHddCtx);
12531
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012532 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012534
12535 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012536 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012537 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12538 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012539 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012540 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12541 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12542
12543 /*issue disconnect */
12544
12545 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12546 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012547 /*
12548 * Wait here instead of returning directly, this will block the next
12549 * connect command and allow processing of the scan for ssid and
12550 * the previous connect command in CSR. Else we might hit some
12551 * race conditions leading to SME and HDD out of sync.
12552 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012553 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012554 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012556 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012557 (int)status);
12558 pHddStaCtx->staDebugState = status;
12559 result = -EINVAL;
12560 goto disconnected;
12561 }
12562 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12563 msecs_to_jiffies
12564 (WLAN_WAIT_TIME_DISCONNECT));
12565
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012566 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012567 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012568 result = -ETIMEDOUT;
12569 }
12570disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012571 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12572#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12573 /* Sending disconnect event to userspace for kernel version < 3.11
12574 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12575 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012576 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012577 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12578 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579#endif
12580
12581 return result;
12582}
12583
12584/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012585 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12586 * @reason: ieee80211 reason code.
12587 *
12588 * This utility function helps log string conversion of reason code.
12589 *
12590 * Return: string conversion of reason code, if match found;
12591 * "Unknown" otherwise.
12592 */
12593static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12594{
12595 switch (reason) {
12596 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12597 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12598 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12599 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12600 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12601 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12602 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12603 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12604 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12605 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12606 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12607 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12608 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12609 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12610 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12611 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12612 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12613 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12614 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12615 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12616 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12617 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12618 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12619 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12620 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12621 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12622 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12623 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12624 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12625 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12626 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12627 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12628 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12629 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12630 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12631 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12632 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12633 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12634 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12635 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12636 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12637 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12638 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12639 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12640 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12641 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12642 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12643 default:
12644 return "Unknown";
12645 }
12646}
12647
12648/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012649 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12650 * @wiphy: Pointer to wiphy
12651 * @dev: Pointer to network device
12652 * @reason: Disconnect reason code
12653 *
12654 * This function is used to issue a disconnect request to SME
12655 *
12656 * Return: 0 for success, non-zero for failure
12657 */
12658static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12659 struct net_device *dev, u16 reason)
12660{
12661 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12662 int status;
12663 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12664 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12665#ifdef FEATURE_WLAN_TDLS
12666 uint8_t staIdx;
12667#endif
12668
12669 ENTER();
12670
Anurag Chouhan6d760662016-02-20 16:05:43 +053012671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012672 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012673 return -EINVAL;
12674 }
12675
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012676 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012677 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12678 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012679 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012680 hdd_device_mode_to_string(pAdapter->device_mode),
12681 pAdapter->device_mode, reason);
12682
12683 status = wlan_hdd_validate_context(pHddCtx);
12684
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012685 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012686 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012687
12688 /* Issue disconnect request to SME, if station is in connected state */
12689 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12690 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12691 eCsrRoamDisconnectReason reasonCode =
12692 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12693 hdd_scaninfo_t *pScanInfo;
12694
12695 switch (reason) {
12696 case WLAN_REASON_MIC_FAILURE:
12697 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12698 break;
12699
12700 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12701 case WLAN_REASON_DISASSOC_AP_BUSY:
12702 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12703 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12704 break;
12705
12706 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12707 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12708 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12709 break;
12710
12711 case WLAN_REASON_DEAUTH_LEAVING:
12712 reasonCode =
12713 pHddCtx->config->
12714 gEnableDeauthToDisassocMap ?
12715 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12716 eCSR_DISCONNECT_REASON_DEAUTH;
12717 break;
12718 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12719 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12720 break;
12721 default:
12722 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12723 break;
12724 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012725 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012726 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012727 pScanInfo = &pAdapter->scan_info;
12728 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012729 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012730 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12731 eCSR_SCAN_ABORT_DEFAULT);
12732 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012733 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012734#ifdef FEATURE_WLAN_TDLS
12735 /* First clean up the tdls peers if any */
12736 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12737 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12738 pAdapter->sessionId)
12739 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12740 uint8_t *mac;
12741 mac =
12742 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012743 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12744 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012745 pHddCtx->tdlsConnInfo[staIdx].staId,
12746 pAdapter->sessionId,
12747 MAC_ADDR_ARRAY(mac));
12748 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12749 (pAdapter),
12750 pAdapter->sessionId, mac);
12751 }
12752 }
12753#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012754 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012755 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012756 hdd_info("Disconnect request from user space with reason: %s",
12757 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012758 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12759 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012760 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012761 return -EINVAL;
12762 }
12763 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012764 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765 pHddStaCtx->conn_info.connState);
12766 }
12767
12768 return status;
12769}
12770
12771/**
12772 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12773 * @wiphy: Pointer to wiphy
12774 * @dev: Pointer to network device
12775 * @reason: Disconnect reason code
12776 *
12777 * Return: 0 for success, non-zero for failure
12778 */
12779static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12780 struct net_device *dev, u16 reason)
12781{
12782 int ret;
12783 cds_ssr_protect(__func__);
12784 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12785 cds_ssr_unprotect(__func__);
12786
12787 return ret;
12788}
12789
12790/**
12791 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12792 * @pAdapter: Pointer to adapter
12793 * @param: Pointer to IBSS parameters
12794 *
12795 * This function is used to initialize the security settings in IBSS mode
12796 *
12797 * Return: 0 for success, non-zero for failure
12798 */
12799static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12800 struct cfg80211_ibss_params
12801 *params)
12802{
12803 int status = 0;
12804 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12805 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12806 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12807
12808 ENTER();
12809
12810 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012811 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012812 pHddStaCtx->ibss_enc_key_installed = 0;
12813
12814 if (params->ie_len && (NULL != params->ie)) {
12815 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12816 params->ie_len, WLAN_EID_RSN)) {
12817 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12818 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12819 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12820 tDot11fIEWPA dot11WPAIE;
12821 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12822 u8 *ie;
12823
12824 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12825 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12826 params->ie_len,
12827 DOT11F_EID_WPA);
12828 if (NULL != ie) {
12829 pWextState->wpaVersion =
12830 IW_AUTH_WPA_VERSION_WPA;
12831 /* Unpack the WPA IE */
12832 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12833 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12834 &ie[2 + 4],
12835 ie[1] - 4, &dot11WPAIE);
12836 /*Extract the multicast cipher, the encType for unicast
12837 cipher for wpa-none is none */
12838 encryptionType =
12839 hdd_translate_wpa_to_csr_encryption_type
12840 (dot11WPAIE.multicast_cipher);
12841 }
12842 }
12843
12844 status =
12845 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12846 params->ie_len);
12847
12848 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012849 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012850 return status;
12851 }
12852 }
12853
12854 pWextState->roamProfile.AuthType.authType[0] =
12855 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12856
12857 if (params->privacy) {
12858 /* Security enabled IBSS, At this time there is no information
12859 * available about the security paramters, so initialise the
12860 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12861 * The correct security parameters will be updated later in
12862 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12863 * set inorder enable privacy bit in beacons
12864 */
12865
12866 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12867 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012868 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012869 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12870 pWextState->roamProfile.EncryptionType.numEntries = 1;
12871 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12872 encryptionType;
12873 return status;
12874}
12875
12876/**
12877 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12878 * @wiphy: Pointer to wiphy
12879 * @dev: Pointer to network device
12880 * @param: Pointer to IBSS join parameters
12881 *
12882 * This function is used to create/join an IBSS network
12883 *
12884 * Return: 0 for success, non-zero for failure
12885 */
12886static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12887 struct net_device *dev,
12888 struct cfg80211_ibss_params *params)
12889{
12890 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12891 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12892 tCsrRoamProfile *pRoamProfile;
12893 int status;
12894 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12895 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012896 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012897 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898
12899 ENTER();
12900
Anurag Chouhan6d760662016-02-20 16:05:43 +053012901 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012902 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 return -EINVAL;
12904 }
12905
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012906 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012907 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12908 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012909 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012910 hdd_device_mode_to_string(pAdapter->device_mode),
12911 pAdapter->device_mode);
12912
12913 status = wlan_hdd_validate_context(pHddCtx);
12914
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012915 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917
12918 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012919 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12921 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12922 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12923 int indx;
12924
12925 /* Get channel number */
12926 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927 params->
12928 chandef.
12929 chan->
12930 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012931
12932 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12933 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012934 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935 return -EOPNOTSUPP;
12936 }
12937
12938 for (indx = 0; indx < numChans; indx++) {
12939 if (channelNum == validChan[indx]) {
12940 break;
12941 }
12942 }
12943 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012944 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012945 return -EINVAL;
12946 }
12947 }
12948
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012949 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012950 HW_MODE_20_MHZ)) {
12951 hdd_err("This concurrency combination is not allowed");
12952 return -ECONNREFUSED;
12953 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012954
Krunal Soni3091bcc2016-06-23 12:28:21 -070012955 status = qdf_reset_connection_update();
12956 if (!QDF_IS_STATUS_SUCCESS(status))
12957 hdd_err("ERR: clear event failed");
12958
12959 status = cds_current_connections_update(pAdapter->sessionId,
12960 channelNum,
12961 SIR_UPDATE_REASON_JOIN_IBSS);
12962 if (QDF_STATUS_E_FAILURE == status) {
12963 hdd_err("ERROR: connections update failed!!");
12964 return -EINVAL;
12965 }
12966
12967 if (QDF_STATUS_SUCCESS == status) {
12968 status = qdf_wait_for_connection_update();
12969 if (!QDF_IS_STATUS_SUCCESS(status)) {
12970 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 return -EINVAL;
12972 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012973 }
12974
12975 /*Try disconnecting if already in connected state */
12976 status = wlan_hdd_try_disconnect(pAdapter);
12977 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012978 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979 return -EALREADY;
12980 }
12981
12982 pRoamProfile = &pWextState->roamProfile;
12983
12984 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012985 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012986 return -EINVAL;
12987 }
12988
12989 /* enable selected protection checks in IBSS mode */
12990 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12991
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012992 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12994 pHddCtx->config->
12995 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012996 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997 }
12998
12999 /* BSSID is provided by upper layers hence no need to AUTO generate */
13000 if (NULL != params->bssid) {
13001 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013002 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013003 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004 return -EIO;
13005 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013006 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013007 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13008 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013009 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013010 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013011 return -EIO;
13012 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013013 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013014 }
13015 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13016 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13017 pRoamProfile->beaconInterval = params->beacon_interval;
13018 else {
13019 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013020 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013021 params->beacon_interval, pRoamProfile->beaconInterval);
13022 }
13023
13024 /* Set Channel */
13025 if (channelNum) {
13026 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013027 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 pRoamProfile->ChannelInfo.numOfChannels = 1;
13029 pHddStaCtx->conn_info.operationChannel = channelNum;
13030 pRoamProfile->ChannelInfo.ChannelList =
13031 &pHddStaCtx->conn_info.operationChannel;
13032 }
13033
13034 /* Initialize security parameters */
13035 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13036 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013037 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013038 return status;
13039 }
13040
13041 /* Issue connect start */
13042 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13043 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013044 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013045 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013046 operationChannel,
13047 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013048
13049 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013050 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013051 return status;
13052 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013053 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013054 return 0;
13055}
13056
13057/**
13058 * wlan_hdd_cfg80211_join_ibss() - join ibss
13059 * @wiphy: Pointer to wiphy
13060 * @dev: Pointer to network device
13061 * @param: Pointer to IBSS join parameters
13062 *
13063 * This function is used to create/join an IBSS network
13064 *
13065 * Return: 0 for success, non-zero for failure
13066 */
13067static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13068 struct net_device *dev,
13069 struct cfg80211_ibss_params *params)
13070{
13071 int ret = 0;
13072
13073 cds_ssr_protect(__func__);
13074 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13075 cds_ssr_unprotect(__func__);
13076
13077 return ret;
13078}
13079
13080/**
13081 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13082 * @wiphy: Pointer to wiphy
13083 * @dev: Pointer to network device
13084 *
13085 * This function is used to leave an IBSS network
13086 *
13087 * Return: 0 for success, non-zero for failure
13088 */
13089static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13090 struct net_device *dev)
13091{
13092 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13093 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13094 tCsrRoamProfile *pRoamProfile;
13095 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13096 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013097 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013098 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013099 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013100
13101 ENTER();
13102
Anurag Chouhan6d760662016-02-20 16:05:43 +053013103 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013104 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 return -EINVAL;
13106 }
13107
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013108 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13110 pAdapter->sessionId,
13111 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13112 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013113 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013114 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013115
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013116 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013117 hdd_device_mode_to_string(pAdapter->device_mode),
13118 pAdapter->device_mode);
13119 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013120 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013121 return -EIO;
13122 }
13123
13124 pRoamProfile = &pWextState->roamProfile;
13125
13126 /* Issue disconnect only if interface type is set to IBSS */
13127 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013128 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013129 return -EINVAL;
13130 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013131 /* Clearing add IE of beacon */
13132 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13133 sizeof(tSirMacAddr));
13134 updateIE.smeSessionId = pAdapter->sessionId;
13135 updateIE.ieBufferlength = 0;
13136 updateIE.pAdditionIEBuffer = NULL;
13137 updateIE.append = true;
13138 updateIE.notify = true;
13139 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13140 &updateIE,
13141 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013142 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013143 }
13144
13145 /* Reset WNI_CFG_PROBE_RSP Flags */
13146 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147
13148 /* Issue Disconnect request */
13149 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13150 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13151 pAdapter->sessionId,
13152 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013153 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013154 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013155 hal_status);
13156 return -EAGAIN;
13157 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013158
13159 /* wait for mc thread to cleanup and then return to upper stack
13160 * so by the time upper layer calls the change interface, we are
13161 * all set to proceed further
13162 */
13163 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13164 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13165 if (!rc) {
13166 hdd_err("Failed to disconnect, timed out");
13167 return -ETIMEDOUT;
13168 }
13169
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013170 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171 return 0;
13172}
13173
13174/**
13175 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13176 * @wiphy: Pointer to wiphy
13177 * @dev: Pointer to network device
13178 *
13179 * This function is used to leave an IBSS network
13180 *
13181 * Return: 0 for success, non-zero for failure
13182 */
13183static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13184 struct net_device *dev)
13185{
13186 int ret = 0;
13187
13188 cds_ssr_protect(__func__);
13189 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13190 cds_ssr_unprotect(__func__);
13191
13192 return ret;
13193}
13194
13195/**
13196 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13197 * @wiphy: Pointer to wiphy
13198 * @changed: Parameters changed
13199 *
13200 * This function is used to set the phy parameters. RTS Threshold/FRAG
13201 * Threshold/Retry Count etc.
13202 *
13203 * Return: 0 for success, non-zero for failure
13204 */
13205static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13206 u32 changed)
13207{
13208 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13209 tHalHandle hHal = pHddCtx->hHal;
13210 int status;
13211
13212 ENTER();
13213
Anurag Chouhan6d760662016-02-20 16:05:43 +053013214 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013215 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013216 return -EINVAL;
13217 }
13218
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013219 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013220 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13221 NO_SESSION, wiphy->rts_threshold));
13222 status = wlan_hdd_validate_context(pHddCtx);
13223
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013224 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013225 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013226
13227 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13228 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13229 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13230
13231 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13232 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013233 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234 rts_threshold);
13235 return -EINVAL;
13236 }
13237
13238 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13239 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013240 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013241 rts_threshold);
13242 return -EIO;
13243 }
13244
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013245 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013246 }
13247
13248 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13249 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13250 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13251 wiphy->frag_threshold;
13252
13253 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13254 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013255 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013256 frag_threshold);
13257 return -EINVAL;
13258 }
13259
13260 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13261 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013262 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263 frag_threshold);
13264 return -EIO;
13265 }
13266
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013267 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268 }
13269
13270 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13271 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13272 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13273 wiphy->retry_short : wiphy->retry_long;
13274
13275 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13276 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013277 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278 return -EINVAL;
13279 }
13280
13281 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13282 if (0 != sme_cfg_set_int(hHal,
13283 WNI_CFG_LONG_RETRY_LIMIT,
13284 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013285 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286 retry_value);
13287 return -EIO;
13288 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013289 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13291 if (0 != sme_cfg_set_int(hHal,
13292 WNI_CFG_SHORT_RETRY_LIMIT,
13293 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013294 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013295 retry_value);
13296 return -EIO;
13297 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013298 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013299 }
13300 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013301 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013302 return 0;
13303}
13304
13305/**
13306 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13307 * @wiphy: Pointer to wiphy
13308 * @changed: Parameters changed
13309 *
13310 * Return: 0 for success, non-zero for failure
13311 */
13312static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13313{
13314 int ret;
13315
13316 cds_ssr_protect(__func__);
13317 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13318 cds_ssr_unprotect(__func__);
13319
13320 return ret;
13321}
13322
13323/**
13324 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13325 * key
13326 * @wiphy: Pointer to wiphy
13327 * @dev: Pointer to network device
13328 * @key_index: Key index
13329 *
13330 * Return: 0
13331 */
13332static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13333 struct net_device *netdev,
13334 u8 key_index)
13335{
13336 ENTER();
13337 return 0;
13338}
13339
13340/**
13341 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13342 * wlan_hdd_set_default_mgmt_key
13343 * @wiphy: pointer to wiphy
13344 * @netdev: pointer to net_device structure
13345 * @key_index: key index
13346 *
13347 * Return: 0 on success, error number on failure
13348 */
13349static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13350 struct net_device *netdev,
13351 u8 key_index)
13352{
13353 int ret;
13354
13355 cds_ssr_protect(__func__);
13356 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13357 cds_ssr_unprotect(__func__);
13358
13359 return ret;
13360}
13361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013362/**
13363 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13364 * @wiphy: Pointer to wiphy
13365 * @dev: Pointer to network device
13366 * @params: Pointer to tx queue parameters
13367 *
13368 * Return: 0
13369 */
13370static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13371 struct net_device *dev,
13372 struct ieee80211_txq_params *params)
13373{
13374 ENTER();
13375 return 0;
13376}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013377
13378/**
13379 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13380 * @wiphy: pointer to wiphy
13381 * @netdev: pointer to net_device structure
13382 * @params: pointer to ieee80211_txq_params
13383 *
13384 * Return: 0 on success, error number on failure
13385 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013386static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13387 struct net_device *dev,
13388 struct ieee80211_txq_params *params)
13389{
13390 int ret;
13391
13392 cds_ssr_protect(__func__);
13393 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13394 cds_ssr_unprotect(__func__);
13395
13396 return ret;
13397}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398
13399/**
13400 * __wlan_hdd_cfg80211_del_station() - delete station v2
13401 * @wiphy: Pointer to wiphy
13402 * @param: Pointer to delete station parameter
13403 *
13404 * Return: 0 for success, non-zero for failure
13405 */
13406static
13407int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13408 struct net_device *dev,
13409 struct tagCsrDelStaParams *pDelStaParams)
13410{
13411 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13412 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013413 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414 hdd_hostapd_state_t *hapd_state;
13415 int status;
13416 uint8_t staId;
13417 uint8_t *mac;
13418
13419 ENTER();
13420
Anurag Chouhan6d760662016-02-20 16:05:43 +053013421 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013422 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423 return -EINVAL;
13424 }
13425
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013426 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427 TRACE_CODE_HDD_CFG80211_DEL_STA,
13428 pAdapter->sessionId, pAdapter->device_mode));
13429
13430 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13431 status = wlan_hdd_validate_context(pHddCtx);
13432
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013433 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013434 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013435
13436 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13437
Krunal Sonib4326f22016-03-10 13:05:51 -080013438 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13439 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013440
13441 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13442 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013443 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013444 return 0;
13445 }
13446
Anurag Chouhanc5548422016-02-24 18:33:27 +053013447 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448 uint16_t i;
13449 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13450 if ((pAdapter->aStaInfo[i].isUsed) &&
13451 (!pAdapter->aStaInfo[i].
13452 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013453 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013454 mac,
13455 pAdapter->aStaInfo[i].
13456 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013457 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013458 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13459 hdd_ipa_wlan_evt(pAdapter,
13460 pAdapter->
13461 aStaInfo[i].
13462 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013463 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464 mac);
13465 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013466 hdd_notice("Delete STA with MAC::"
13467 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013468 MAC_ADDR_ARRAY(mac));
13469
13470 if (pHddCtx->dev_dfs_cac_status ==
13471 DFS_CAC_IN_PROGRESS)
13472 goto fn_end;
13473
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013474 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013475 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013476 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013477 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013478 hdd_softap_sta_deauth(pAdapter,
13479 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013480 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481 pAdapter->aStaInfo[i].
13482 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013483 qdf_status =
13484 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013485 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013486 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013487 if (!QDF_IS_STATUS_SUCCESS(
13488 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013489 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013490 }
13491 }
13492 }
13493 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013494 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013495 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013496 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013497 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013498 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013499 hdd_notice("Skip DEL STA as this is not used::"
13500 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013501 MAC_ADDR_ARRAY(mac));
13502 return -ENOENT;
13503 }
13504
13505 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13506 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013507 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013508 }
13509
13510 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13511 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013512 hdd_notice("Skip DEL STA as deauth is in progress::"
13513 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013514 MAC_ADDR_ARRAY(mac));
13515 return -ENOENT;
13516 }
13517
13518 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13519
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013520 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013521 MAC_ADDR_ARRAY(mac));
13522
13523 /* Case: SAP in ACS selected DFS ch and client connected
13524 * Now Radar detected. Then if random channel is another
13525 * DFS ch then new CAC is initiated and no TX allowed.
13526 * So do not send any mgmt frames as it will timeout
13527 * during CAC.
13528 */
13529
13530 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13531 goto fn_end;
13532
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013533 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013534 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13535 (pAdapter), pAdapter->sessionId,
13536 (uint8_t *)&pDelStaParams->peerMacAddr,
13537 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013538 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013540 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013541 pAdapter->aStaInfo[staId].isDeauthInProgress =
13542 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013543 hdd_notice("STA removal failed for ::"
13544 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 MAC_ADDR_ARRAY(mac));
13546 return -ENOENT;
13547 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013548 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013549 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013550 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013551 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013552 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013553 }
13554 }
13555 }
13556
13557fn_end:
13558 EXIT();
13559 return 0;
13560}
13561
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013562#if defined(USE_CFG80211_DEL_STA_V2)
13563/**
13564 * wlan_hdd_del_station() - delete station wrapper
13565 * @adapter: pointer to the hdd adapter
13566 *
13567 * Return: None
13568 */
13569void wlan_hdd_del_station(hdd_adapter_t *adapter)
13570{
13571 struct station_del_parameters del_sta;
13572 del_sta.mac = NULL;
13573 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13574 del_sta.reason_code = eCsrForcedDeauthSta;
13575
13576 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13577 &del_sta);
13578}
13579#else
13580void wlan_hdd_del_station(hdd_adapter_t *adapter)
13581{
13582 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13583}
13584#endif
13585
13586#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587/**
13588 * wlan_hdd_cfg80211_del_station() - delete station v2
13589 * @wiphy: Pointer to wiphy
13590 * @param: Pointer to delete station parameter
13591 *
13592 * Return: 0 for success, non-zero for failure
13593 */
13594int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13595 struct net_device *dev,
13596 struct station_del_parameters *param)
13597#else
13598/**
13599 * wlan_hdd_cfg80211_del_station() - delete station
13600 * @wiphy: Pointer to wiphy
13601 * @mac: Pointer to station mac address
13602 *
13603 * Return: 0 for success, non-zero for failure
13604 */
13605#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13606int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13607 struct net_device *dev,
13608 const uint8_t *mac)
13609#else
13610int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13611 struct net_device *dev,
13612 uint8_t *mac)
13613#endif
13614#endif
13615{
13616 int ret;
13617 struct tagCsrDelStaParams delStaParams;
13618
13619 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013620#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013621 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013622 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 return -EINVAL;
13624 }
13625 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13626 param->subtype, &delStaParams);
13627#else
13628 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13629 (SIR_MAC_MGMT_DEAUTH >> 4),
13630 &delStaParams);
13631#endif
13632 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13633 cds_ssr_unprotect(__func__);
13634
13635 return ret;
13636}
13637
13638/**
13639 * __wlan_hdd_cfg80211_add_station() - add station
13640 * @wiphy: Pointer to wiphy
13641 * @mac: Pointer to station mac address
13642 * @pmksa: Pointer to add station parameter
13643 *
13644 * Return: 0 for success, non-zero for failure
13645 */
13646static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13647 struct net_device *dev,
13648 const uint8_t *mac,
13649 struct station_parameters *params)
13650{
13651 int status = -EPERM;
13652#ifdef FEATURE_WLAN_TDLS
13653 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13654 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13655 u32 mask, set;
13656
13657 ENTER();
13658
Anurag Chouhan6d760662016-02-20 16:05:43 +053013659 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013660 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013661 return -EINVAL;
13662 }
13663
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013664 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 TRACE_CODE_HDD_CFG80211_ADD_STA,
13666 pAdapter->sessionId, params->listen_interval));
13667
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013668 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013669 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670
13671 mask = params->sta_flags_mask;
13672
13673 set = params->sta_flags_set;
13674
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013675 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013676 MAC_ADDR_ARRAY(mac));
13677
13678 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13679 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13680 status =
13681 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13682 }
13683 }
13684#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013685 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013686 return status;
13687}
13688
13689/**
13690 * wlan_hdd_cfg80211_add_station() - add station
13691 * @wiphy: Pointer to wiphy
13692 * @mac: Pointer to station mac address
13693 * @pmksa: Pointer to add station parameter
13694 *
13695 * Return: 0 for success, non-zero for failure
13696 */
13697#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13698static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13699 struct net_device *dev,
13700 const uint8_t *mac,
13701 struct station_parameters *params)
13702#else
13703static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13704 struct net_device *dev, uint8_t *mac,
13705 struct station_parameters *params)
13706#endif
13707{
13708 int ret;
13709
13710 cds_ssr_protect(__func__);
13711 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13712 cds_ssr_unprotect(__func__);
13713
13714 return ret;
13715}
13716
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717/**
13718 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13719 * @wiphy: Pointer to wiphy
13720 * @dev: Pointer to network device
13721 * @pmksa: Pointer to set pmksa parameter
13722 *
13723 * Return: 0 for success, non-zero for failure
13724 */
13725static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13726 struct net_device *dev,
13727 struct cfg80211_pmksa *pmksa)
13728{
13729 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13730 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13731 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013732 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013733 int status;
13734 tPmkidCacheInfo pmk_id;
13735
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013736 ENTER();
13737
Anurag Chouhan6d760662016-02-20 16:05:43 +053013738 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013739 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013740 return -EINVAL;
13741 }
13742
13743 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013744 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013745 return -EINVAL;
13746 }
13747
13748 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013749 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 pmksa->bssid, pmksa->pmkid);
13751 return -EINVAL;
13752 }
13753
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013754 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755 MAC_ADDR_ARRAY(pmksa->bssid));
13756
13757 status = wlan_hdd_validate_context(pHddCtx);
13758
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013759 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761
13762 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13763
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013764 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13765 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013766
13767 /* Add to the PMKSA ID Cache in CSR */
13768 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13769 &pmk_id, 1, false);
13770
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013771 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13773 pAdapter->sessionId, result));
13774
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013775 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013776 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777}
13778
13779/**
13780 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13781 * @wiphy: Pointer to wiphy
13782 * @dev: Pointer to network device
13783 * @pmksa: Pointer to set pmksa parameter
13784 *
13785 * Return: 0 for success, non-zero for failure
13786 */
13787static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13788 struct net_device *dev,
13789 struct cfg80211_pmksa *pmksa)
13790{
13791 int ret;
13792
13793 cds_ssr_protect(__func__);
13794 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13795 cds_ssr_unprotect(__func__);
13796
13797 return ret;
13798}
13799
13800/**
13801 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13802 * @wiphy: Pointer to wiphy
13803 * @dev: Pointer to network device
13804 * @pmksa: Pointer to pmksa parameter
13805 *
13806 * Return: 0 for success, non-zero for failure
13807 */
13808static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13809 struct net_device *dev,
13810 struct cfg80211_pmksa *pmksa)
13811{
13812 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13813 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13814 tHalHandle halHandle;
13815 int status = 0;
13816
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013817 ENTER();
13818
Anurag Chouhan6d760662016-02-20 16:05:43 +053013819 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013820 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013821 return -EINVAL;
13822 }
13823
13824 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013825 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 return -EINVAL;
13827 }
13828
13829 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013830 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 return -EINVAL;
13832 }
13833
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013834 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835 MAC_ADDR_ARRAY(pmksa->bssid));
13836
13837 status = wlan_hdd_validate_context(pHddCtx);
13838
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013839 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013841
13842 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13843
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013844 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013845 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13846 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013847 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013848 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849 sme_roam_del_pmkid_from_cache(halHandle,
13850 pAdapter->sessionId, pmksa->bssid,
13851 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013852 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013853 MAC_ADDR_ARRAY(pmksa->bssid));
13854 status = -EINVAL;
13855 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013856 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013857 return status;
13858}
13859
13860/**
13861 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13862 * @wiphy: Pointer to wiphy
13863 * @dev: Pointer to network device
13864 * @pmksa: Pointer to pmksa parameter
13865 *
13866 * Return: 0 for success, non-zero for failure
13867 */
13868static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13869 struct net_device *dev,
13870 struct cfg80211_pmksa *pmksa)
13871{
13872 int ret;
13873
13874 cds_ssr_protect(__func__);
13875 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13876 cds_ssr_unprotect(__func__);
13877
13878 return ret;
13879
13880}
13881
13882/**
13883 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13884 * @wiphy: Pointer to wiphy
13885 * @dev: Pointer to network device
13886 *
13887 * Return: 0 for success, non-zero for failure
13888 */
13889static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13890 struct net_device *dev)
13891{
13892 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13893 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13894 tHalHandle halHandle;
13895 int status = 0;
13896
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013897 ENTER();
13898
Anurag Chouhan6d760662016-02-20 16:05:43 +053013899 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013900 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013901 return -EINVAL;
13902 }
13903
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013904 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905
13906 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13907 status = wlan_hdd_validate_context(pHddCtx);
13908
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013909 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013910 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911
13912 /* Retrieve halHandle */
13913 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13914
13915 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013916 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13918 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013919 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013920 status = -EINVAL;
13921 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013922 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923 return status;
13924}
13925
13926/**
13927 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13928 * @wiphy: Pointer to wiphy
13929 * @dev: Pointer to network device
13930 *
13931 * Return: 0 for success, non-zero for failure
13932 */
13933static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13934 struct net_device *dev)
13935{
13936 int ret;
13937
13938 cds_ssr_protect(__func__);
13939 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13940 cds_ssr_unprotect(__func__);
13941
13942 return ret;
13943}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013944
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013945#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013946/**
13947 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13948 * @wiphy: Pointer to wiphy
13949 * @dev: Pointer to network device
13950 * @ftie: Pointer to fast transition ie parameter
13951 *
13952 * Return: 0 for success, non-zero for failure
13953 */
13954static int
13955__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13956 struct net_device *dev,
13957 struct cfg80211_update_ft_ies_params *ftie)
13958{
13959 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13960 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13961 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13962 int status;
13963
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013964 ENTER();
13965
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013966 status = wlan_hdd_validate_context(hdd_ctx);
13967 if (status)
13968 return status;
13969
Anurag Chouhan6d760662016-02-20 16:05:43 +053013970 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013971 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013972 return -EINVAL;
13973 }
13974
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013975 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13977 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13978 /* Added for debug on reception of Re-assoc Req. */
13979 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013980 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013982 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013984 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013986
13987 /* Pass the received FT IEs to SME */
13988 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13989 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013990 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013991 return 0;
13992}
13993
13994/**
13995 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13996 * @wiphy: Pointer to wiphy
13997 * @dev: Pointer to network device
13998 * @ftie: Pointer to fast transition ie parameter
13999 *
14000 * Return: 0 for success, non-zero for failure
14001 */
14002static int
14003wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14004 struct net_device *dev,
14005 struct cfg80211_update_ft_ies_params *ftie)
14006{
14007 int ret;
14008
14009 cds_ssr_protect(__func__);
14010 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14011 cds_ssr_unprotect(__func__);
14012
14013 return ret;
14014}
14015#endif
14016
14017#ifdef WLAN_FEATURE_GTK_OFFLOAD
14018/**
14019 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14020 * @callbackContext: Callback context
14021 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14022 *
14023 * Callback rountine called upon receiving response for get offload info
14024 *
14025 * Return: none
14026 */
14027void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14028 tpSirGtkOffloadGetInfoRspParams
14029 pGtkOffloadGetInfoRsp)
14030{
14031 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14032 uint8_t tempReplayCounter[8];
14033 hdd_station_ctx_t *pHddStaCtx;
14034
14035 ENTER();
14036
14037 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014038 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014039 return;
14040 }
14041
14042 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014043 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014044 return;
14045 }
14046
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014047 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014048 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014049 return;
14050 }
14051
14052 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14053 /* Update replay counter */
14054 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14055 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14056
14057 {
14058 /* changing from little to big endian since supplicant
14059 * works on big endian format
14060 */
14061 int i;
14062 uint8_t *p =
14063 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14064
14065 for (i = 0; i < 8; i++) {
14066 tempReplayCounter[7 - i] = (uint8_t) p[i];
14067 }
14068 }
14069
14070 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014071 cfg80211_gtk_rekey_notify(pAdapter->dev,
14072 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 tempReplayCounter, GFP_KERNEL);
14074}
14075
14076/**
14077 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14078 * @wiphy: Pointer to wiphy
14079 * @dev: Pointer to network device
14080 * @data: Pointer to rekey data
14081 *
14082 * This function is used to offload GTK rekeying job to the firmware.
14083 *
14084 * Return: 0 for success, non-zero for failure
14085 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014086static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14088 struct net_device *dev,
14089 struct cfg80211_gtk_rekey_data *data)
14090{
14091 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14092 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14093 hdd_station_ctx_t *pHddStaCtx;
14094 tHalHandle hHal;
14095 int result;
14096 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014097 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098
14099 ENTER();
14100
Anurag Chouhan6d760662016-02-20 16:05:43 +053014101 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014102 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014103 return -EINVAL;
14104 }
14105
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014106 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014107 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14108 pAdapter->sessionId, pAdapter->device_mode));
14109
14110 result = wlan_hdd_validate_context(pHddCtx);
14111
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014112 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014113 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114
14115 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14116 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14117 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014118 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014119 return -EAGAIN;
14120 }
14121
14122 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14123 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14124 NL80211_KCK_LEN);
14125 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14126 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014127 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014128 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014129 {
14130 /* changing from big to little endian since driver
14131 * works on little endian format
14132 */
14133 uint8_t *p =
14134 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14135 ullKeyReplayCounter;
14136 int i;
14137
14138 for (i = 0; i < 8; i++) {
14139 p[7 - i] = data->replay_ctr[i];
14140 }
14141 }
14142
14143 if (true == pHddCtx->hdd_wlan_suspended) {
14144 /* if wlan is suspended, enable GTK offload directly from here */
14145 memcpy(&hddGtkOffloadReqParams,
14146 &pHddStaCtx->gtkOffloadReqParams,
14147 sizeof(tSirGtkOffloadParams));
14148 status =
14149 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14150 pAdapter->sessionId);
14151
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014152 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014153 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014154 status);
14155 return -EINVAL;
14156 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014157 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014158 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014159 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014160 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014161 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014162 return result;
14163}
14164
14165/**
14166 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14167 * @wiphy: Pointer to wiphy
14168 * @dev: Pointer to network device
14169 * @data: Pointer to rekey data
14170 *
14171 * This function is used to offload GTK rekeying job to the firmware.
14172 *
14173 * Return: 0 for success, non-zero for failure
14174 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014175static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014176int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14177 struct net_device *dev,
14178 struct cfg80211_gtk_rekey_data *data)
14179{
14180 int ret;
14181
14182 cds_ssr_protect(__func__);
14183 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14184 cds_ssr_unprotect(__func__);
14185
14186 return ret;
14187}
14188#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14189
14190/**
14191 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14192 * @wiphy: Pointer to wiphy
14193 * @dev: Pointer to network device
14194 * @param: Pointer to access control parameter
14195 *
14196 * Return: 0 for success, non-zero for failure
14197 */
14198static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14199 struct net_device *dev,
14200 const struct cfg80211_acl_data *params)
14201{
14202 int i;
14203 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14204 hdd_hostapd_state_t *pHostapdState;
14205 tsap_Config_t *pConfig;
14206 v_CONTEXT_t p_cds_context = NULL;
14207 hdd_context_t *pHddCtx;
14208 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014209 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210
14211 ENTER();
14212
Anurag Chouhan6d760662016-02-20 16:05:43 +053014213 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014214 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 return -EINVAL;
14216 }
14217
14218 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014219 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014220 return -EINVAL;
14221 }
14222
14223 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14224 status = wlan_hdd_validate_context(pHddCtx);
14225
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014226 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228
14229 p_cds_context = pHddCtx->pcds_context;
14230 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14231
14232 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014233 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234 return -EINVAL;
14235 }
14236
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014237 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238 params->n_acl_entries);
14239
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014240 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014241 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14242 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014243 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14245
14246 /* default value */
14247 pConfig->num_accept_mac = 0;
14248 pConfig->num_deny_mac = 0;
14249
14250 /**
14251 * access control policy
14252 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14253 * listed in hostapd.deny file.
14254 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14255 * listed in hostapd.accept file.
14256 */
14257 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14258 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14259 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14260 params->acl_policy) {
14261 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14262 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014263 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 params->acl_policy);
14265 return -ENOTSUPP;
14266 }
14267
14268 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14269 pConfig->num_accept_mac = params->n_acl_entries;
14270 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014271 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14272 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014273 MAC_ADDR_ARRAY(
14274 params->mac_addrs[i].addr));
14275
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014276 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 params->mac_addrs[i].addr,
14278 sizeof(qcmacaddr));
14279 }
14280 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14281 pConfig->num_deny_mac = params->n_acl_entries;
14282 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014283 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14284 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014285 MAC_ADDR_ARRAY(
14286 params->mac_addrs[i].addr));
14287
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014288 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014289 params->mac_addrs[i].addr,
14290 sizeof(qcmacaddr));
14291 }
14292 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014293 qdf_status = wlansap_set_mac_acl(
14294 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014295 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014296 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014297 return -EINVAL;
14298 }
14299 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014300 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 hdd_device_mode_to_string(pAdapter->device_mode),
14302 pAdapter->device_mode);
14303 return -EINVAL;
14304 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014305 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014306 return 0;
14307}
14308
14309/**
14310 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14311 * __wlan_hdd_cfg80211_set_mac_acl
14312 * @wiphy: pointer to wiphy structure
14313 * @dev: pointer to net_device
14314 * @params: pointer to cfg80211_acl_data
14315 *
14316 * Return; 0 on success, error number otherwise
14317 */
14318static int
14319wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14320 struct net_device *dev,
14321 const struct cfg80211_acl_data *params)
14322{
14323 int ret;
14324
14325 cds_ssr_protect(__func__);
14326 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14327 cds_ssr_unprotect(__func__);
14328
14329 return ret;
14330}
14331
14332#ifdef WLAN_NL80211_TESTMODE
14333#ifdef FEATURE_WLAN_LPHB
14334/**
14335 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14336 * @pHddCtx: Pointer to hdd context
14337 * @lphbInd: Pointer to low power heart beat indication parameter
14338 *
14339 * Return: none
14340 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014341static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14342 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343{
14344 struct sk_buff *skb;
14345
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014346 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014348 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014349 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014350
14351 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014352 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014353 return;
14354 }
14355
14356 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14357 wiphy, sizeof(tSirLPHBInd),
14358 GFP_ATOMIC);
14359 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014360 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014361 return;
14362 }
14363
14364 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014365 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014366 goto nla_put_failure;
14367 }
14368 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014369 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014370 goto nla_put_failure;
14371 }
14372 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014373 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014374 goto nla_put_failure;
14375 }
14376 cfg80211_testmode_event(skb, GFP_ATOMIC);
14377 return;
14378
14379nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014380 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014381 kfree_skb(skb);
14382
14383 return;
14384}
14385#endif /* FEATURE_WLAN_LPHB */
14386
14387/**
14388 * __wlan_hdd_cfg80211_testmode() - test mode
14389 * @wiphy: Pointer to wiphy
14390 * @data: Data pointer
14391 * @len: Data length
14392 *
14393 * Return: 0 for success, non-zero for failure
14394 */
14395static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14396 void *data, int len)
14397{
14398 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14399 int err;
14400 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14401
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014402 ENTER();
14403
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014404 err = wlan_hdd_validate_context(pHddCtx);
14405 if (err)
14406 return err;
14407
14408 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14409 len, wlan_hdd_tm_policy);
14410 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014411 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014412 return err;
14413 }
14414
14415 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014416 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014417 return -EINVAL;
14418 }
14419
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014420 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014421 TRACE_CODE_HDD_CFG80211_TESTMODE,
14422 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014423 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14424#ifdef FEATURE_WLAN_LPHB
14425 /* Low Power Heartbeat configuration request */
14426 case WLAN_HDD_TM_CMD_WLAN_HB:
14427 {
14428 int buf_len;
14429 void *buf;
14430 tSirLPHBReq *hb_params = NULL;
14431 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014432 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433
14434 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014435 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014436 return -EINVAL;
14437 }
14438
14439 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14440 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14441
14442 hb_params_temp = (tSirLPHBReq *) buf;
14443 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14444 && (hb_params_temp->params.lphbTcpParamReq.
14445 timePeriodSec == 0))
14446 return -EINVAL;
14447
14448 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014449 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014451 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 return -ENOMEM;
14453 }
14454
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014455 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014456 smeStatus =
14457 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14458 hb_params,
14459 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014460 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014461 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014462 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014463 }
14464 return 0;
14465 }
14466#endif /* FEATURE_WLAN_LPHB */
14467
14468#if defined(QCA_WIFI_FTM)
14469 case WLAN_HDD_TM_CMD_WLAN_FTM:
14470 {
14471 int buf_len;
14472 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014473 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014475 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476 return -EINVAL;
14477 }
14478
14479 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14480 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14481
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014482 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014483
14484 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14485
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014486 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014487 err = -EBUSY;
14488 break;
14489 }
14490#endif
14491
14492 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014493 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014494 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14495 return -EOPNOTSUPP;
14496 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014497 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014498 return err;
14499}
14500
14501/**
14502 * wlan_hdd_cfg80211_testmode() - test mode
14503 * @wiphy: Pointer to wiphy
14504 * @dev: Pointer to network device
14505 * @data: Data pointer
14506 * @len: Data length
14507 *
14508 * Return: 0 for success, non-zero for failure
14509 */
14510static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14512 struct wireless_dev *wdev,
14513#endif
14514 void *data, int len)
14515{
14516 int ret;
14517
14518 cds_ssr_protect(__func__);
14519 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14520 cds_ssr_unprotect(__func__);
14521
14522 return ret;
14523}
14524
14525#if defined(QCA_WIFI_FTM)
14526/**
14527 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14528 * @buf: Pointer to buffer
14529 * @buf_len: Buffer length
14530 *
14531 * Return: none
14532 */
14533void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14534{
14535 struct sk_buff *skb;
14536 hdd_context_t *hdd_ctx;
14537
14538 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014539 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014540 return;
14541 }
14542
Anurag Chouhan6d760662016-02-20 16:05:43 +053014543 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014545 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014546 return;
14547 }
14548
14549 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14550 buf_len, GFP_KERNEL);
14551 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014552 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014553 return;
14554 }
14555
14556 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14557 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14558 goto nla_put_failure;
14559
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014560 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561
14562 cfg80211_testmode_event(skb, GFP_KERNEL);
14563 return;
14564
14565nla_put_failure:
14566 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014567 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014568}
14569#endif
14570#endif /* CONFIG_NL80211_TESTMODE */
14571
14572#ifdef QCA_HT_2040_COEX
14573/**
14574 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14575 * @wiphy: Pointer to wiphy
14576 * @dev: Pointer to network device
14577 * @chandef: Pointer to channel definition parameter
14578 *
14579 * Return: 0 for success, non-zero for failure
14580 */
14581static int
14582__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14583 struct net_device *dev,
14584 struct cfg80211_chan_def *chandef)
14585{
14586 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14587 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014588 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014589 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014590 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014591
Anurag Chouhan6d760662016-02-20 16:05:43 +053014592 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014593 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014594 return -EINVAL;
14595 }
14596
14597 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14598 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014599 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014600 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014601
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014602 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603 sme_get_config_param(pHddCtx->hHal, &sme_config);
14604 switch (chandef->width) {
14605 case NL80211_CHAN_WIDTH_20:
14606 if (sme_config.csrConfig.channelBondingMode24GHz !=
14607 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14608 sme_config.csrConfig.channelBondingMode24GHz =
14609 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14610 sme_update_config(pHddCtx->hHal, &sme_config);
14611 cbModeChange = true;
14612 }
14613 break;
14614
14615 case NL80211_CHAN_WIDTH_40:
14616 if (sme_config.csrConfig.channelBondingMode24GHz ==
14617 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14618 if (NL80211_CHAN_HT40MINUS ==
14619 cfg80211_get_chandef_type(chandef))
14620 sme_config.csrConfig.channelBondingMode24GHz =
14621 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14622 else
14623 sme_config.csrConfig.channelBondingMode24GHz =
14624 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14625 sme_update_config(pHddCtx->hHal, &sme_config);
14626 cbModeChange = true;
14627 }
14628 break;
14629
14630 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014631 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632 return -EINVAL;
14633 }
14634
14635 if (!cbModeChange)
14636 return 0;
14637
Krunal Sonib4326f22016-03-10 13:05:51 -080014638 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014639 return 0;
14640
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014641 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014642 sme_config.csrConfig.channelBondingMode24GHz);
14643
14644 /* Change SAP ht2040 mode */
14645 status = hdd_set_sap_ht2040_mode(pAdapter,
14646 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014647 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014648 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014649 return -EINVAL;
14650 }
14651
14652 return 0;
14653}
14654
14655/**
14656 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14657 * @wiphy: Pointer to wiphy
14658 * @dev: Pointer to network device
14659 * @chandef: Pointer to channel definition parameter
14660 *
14661 * Return: 0 for success, non-zero for failure
14662 */
14663static int
14664wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14665 struct net_device *dev,
14666 struct cfg80211_chan_def *chandef)
14667{
14668 int ret;
14669
14670 cds_ssr_protect(__func__);
14671 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14672 cds_ssr_unprotect(__func__);
14673
14674 return ret;
14675}
14676#endif
14677
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014678#ifdef CHANNEL_SWITCH_SUPPORTED
14679/**
14680 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14681 * channel in SAP/GO
14682 * @wiphy: wiphy pointer
14683 * @dev: dev pointer.
14684 * @csa_params: Change channel params
14685 *
14686 * This function is called to switch channel in SAP/GO
14687 *
14688 * Return: 0 if success else return non zero
14689 */
14690static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14691 struct net_device *dev,
14692 struct cfg80211_csa_settings *csa_params)
14693{
14694 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14695 hdd_context_t *hdd_ctx;
14696 uint8_t channel;
14697 uint16_t freq;
14698 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014699 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014700
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014701 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014702 csa_params->chandef.chan->center_freq);
14703
14704 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14705 ret = wlan_hdd_validate_context(hdd_ctx);
14706
14707 if (0 != ret)
14708 return ret;
14709
Krunal Sonib4326f22016-03-10 13:05:51 -080014710 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14711 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014712 return -ENOTSUPP;
14713
14714 freq = csa_params->chandef.chan->center_freq;
14715 channel = cds_freq_to_chan(freq);
14716
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014717 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14718
14719 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014720 return ret;
14721}
14722
14723/**
14724 * wlan_hdd_cfg80211_channel_switch()- function to switch
14725 * channel in SAP/GO
14726 * @wiphy: wiphy pointer
14727 * @dev: dev pointer.
14728 * @csa_params: Change channel params
14729 *
14730 * This function is called to switch channel in SAP/GO
14731 *
14732 * Return: 0 if success else return non zero
14733 */
14734static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14735 struct net_device *dev,
14736 struct cfg80211_csa_settings *csa_params)
14737{
14738 int ret;
14739
14740 cds_ssr_protect(__func__);
14741 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14742 cds_ssr_unprotect(__func__);
14743 return ret;
14744}
14745#endif
14746
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747/**
14748 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14749 * translation from NL to policy manager type
14750 * @type: Generic connection mode type defined in NL
14751 *
14752 *
14753 * This function provides the type translation
14754 *
14755 * Return: cds_con_mode enum
14756 */
14757enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14758 enum nl80211_iftype type)
14759{
14760 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14761 switch (type) {
14762 case NL80211_IFTYPE_STATION:
14763 mode = CDS_STA_MODE;
14764 break;
14765 case NL80211_IFTYPE_P2P_CLIENT:
14766 mode = CDS_P2P_CLIENT_MODE;
14767 break;
14768 case NL80211_IFTYPE_P2P_GO:
14769 mode = CDS_P2P_GO_MODE;
14770 break;
14771 case NL80211_IFTYPE_AP:
14772 mode = CDS_SAP_MODE;
14773 break;
14774 case NL80211_IFTYPE_ADHOC:
14775 mode = CDS_IBSS_MODE;
14776 break;
14777 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014778 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014779 type);
14780 }
14781 return mode;
14782}
14783
14784/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014785 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14786 * @wiphy: Handle to struct wiphy to get handle to module context.
14787 * @chandef: Contains information about the capture channel to be set.
14788 *
14789 * This interface is called if and only if monitor mode interface alone is
14790 * active.
14791 *
14792 * Return: 0 success or error code on failure.
14793 */
14794static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14795 struct cfg80211_chan_def *chandef)
14796{
14797 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14798 hdd_adapter_t *adapter;
14799 hdd_station_ctx_t *sta_ctx;
14800 struct hdd_mon_set_ch_info *ch_info;
14801 QDF_STATUS status;
14802 tHalHandle hal_hdl;
14803 struct qdf_mac_addr bssid;
14804 tCsrRoamProfile roam_profile;
14805 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014806 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014807 int ret;
14808 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14809
14810 ENTER();
14811
14812 ret = wlan_hdd_validate_context(hdd_ctx);
14813 if (ret)
14814 return ret;
14815
14816 hal_hdl = hdd_ctx->hHal;
14817
14818 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14819 if (!adapter)
14820 return -EIO;
14821
14822 hdd_info("%s: set monitor mode Channel %d and freq %d",
14823 adapter->dev->name, chan_num, chandef->chan->center_freq);
14824
14825 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14826 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014827 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14828 roam_profile.ChannelInfo.numOfChannels = 1;
14829 roam_profile.phyMode = ch_info->phy_mode;
14830 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014831 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014832
14833 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14834 QDF_MAC_ADDR_SIZE);
14835
14836 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014837 /*
14838 * CDS api expects secondary channel for calculating
14839 * the channel params
14840 */
14841 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14842 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14843 if (chan_num >= 1 && chan_num <= 5)
14844 sec_ch = chan_num + 4;
14845 else if (chan_num >= 6 && chan_num <= 13)
14846 sec_ch = chan_num - 4;
14847 }
14848 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014849 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14850 &roam_profile);
14851 if (status) {
14852 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14853 status);
14854 ret = qdf_status_to_os_return(status);
14855 return ret;
14856 }
14857 EXIT();
14858 return 0;
14859}
14860
14861/**
14862 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14863 * @wiphy: Handle to struct wiphy to get handle to module context.
14864 * @chandef: Contains information about the capture channel to be set.
14865 *
14866 * This interface is called if and only if monitor mode interface alone is
14867 * active.
14868 *
14869 * Return: 0 success or error code on failure.
14870 */
14871static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14872 struct cfg80211_chan_def *chandef)
14873{
14874 int ret;
14875
14876 cds_ssr_protect(__func__);
14877 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14878 cds_ssr_unprotect(__func__);
14879 return ret;
14880}
14881
14882/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 * struct cfg80211_ops - cfg80211_ops
14884 *
14885 * @add_virtual_intf: Add virtual interface
14886 * @del_virtual_intf: Delete virtual interface
14887 * @change_virtual_intf: Change virtual interface
14888 * @change_station: Change station
14889 * @add_beacon: Add beacon in sap mode
14890 * @del_beacon: Delete beacon in sap mode
14891 * @set_beacon: Set beacon in sap mode
14892 * @start_ap: Start ap
14893 * @change_beacon: Change beacon
14894 * @stop_ap: Stop ap
14895 * @change_bss: Change bss
14896 * @add_key: Add key
14897 * @get_key: Get key
14898 * @del_key: Delete key
14899 * @set_default_key: Set default key
14900 * @set_channel: Set channel
14901 * @scan: Scan
14902 * @connect: Connect
14903 * @disconnect: Disconnect
14904 * @join_ibss = Join ibss
14905 * @leave_ibss = Leave ibss
14906 * @set_wiphy_params = Set wiphy params
14907 * @set_tx_power = Set tx power
14908 * @get_tx_power = get tx power
14909 * @remain_on_channel = Remain on channel
14910 * @cancel_remain_on_channel = Cancel remain on channel
14911 * @mgmt_tx = Tx management frame
14912 * @mgmt_tx_cancel_wait = Cancel management tx wait
14913 * @set_default_mgmt_key = Set default management key
14914 * @set_txq_params = Set tx queue parameters
14915 * @get_station = Get station
14916 * @set_power_mgmt = Set power management
14917 * @del_station = Delete station
14918 * @add_station = Add station
14919 * @set_pmksa = Set pmksa
14920 * @del_pmksa = Delete pmksa
14921 * @flush_pmksa = Flush pmksa
14922 * @update_ft_ies = Update FT IEs
14923 * @tdls_mgmt = Tdls management
14924 * @tdls_oper = Tdls operation
14925 * @set_rekey_data = Set rekey data
14926 * @sched_scan_start = Scheduled scan start
14927 * @sched_scan_stop = Scheduled scan stop
14928 * @resume = Resume wlan
14929 * @suspend = Suspend wlan
14930 * @set_mac_acl = Set mac acl
14931 * @testmode_cmd = Test mode command
14932 * @set_ap_chanwidth = Set AP channel bandwidth
14933 * @dump_survey = Dump survey
14934 * @key_mgmt_set_pmk = Set pmk key management
14935 */
14936static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14937 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14938 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14939 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14940 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014941 .start_ap = wlan_hdd_cfg80211_start_ap,
14942 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14943 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014944 .change_bss = wlan_hdd_cfg80211_change_bss,
14945 .add_key = wlan_hdd_cfg80211_add_key,
14946 .get_key = wlan_hdd_cfg80211_get_key,
14947 .del_key = wlan_hdd_cfg80211_del_key,
14948 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14949 .scan = wlan_hdd_cfg80211_scan,
14950 .connect = wlan_hdd_cfg80211_connect,
14951 .disconnect = wlan_hdd_cfg80211_disconnect,
14952 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14953 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14954 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14955 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14956 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14957 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14958 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14959 .mgmt_tx = wlan_hdd_mgmt_tx,
14960 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14961 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14962 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014963 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014964 .get_station = wlan_hdd_cfg80211_get_station,
14965 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14966 .del_station = wlan_hdd_cfg80211_del_station,
14967 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014968 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14969 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14970 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014971#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014972 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14973#endif
14974#ifdef FEATURE_WLAN_TDLS
14975 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14976 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14977#endif
14978#ifdef WLAN_FEATURE_GTK_OFFLOAD
14979 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14980#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14981#ifdef FEATURE_WLAN_SCAN_PNO
14982 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14983 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14984#endif /*FEATURE_WLAN_SCAN_PNO */
14985 .resume = wlan_hdd_cfg80211_resume_wlan,
14986 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14987 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14988#ifdef WLAN_NL80211_TESTMODE
14989 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14990#endif
14991#ifdef QCA_HT_2040_COEX
14992 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14993#endif
14994 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014995#ifdef CHANNEL_SWITCH_SUPPORTED
14996 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14997#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014998 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014999#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15000 defined(CFG80211_ABORT_SCAN)
15001 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15002#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015003};